Archive for the 'jQuery' Category

jQuery:Inside Scroll

jquery

 
ページ内リンクをスムーズスクロールするjQueryプラグイン(Inside Scroll)を使わせていただいています。
ページ内リンクをクリックすると、シュルシュルとスムーズにスクロースする、アレです。
この機能はもちろん大変ありがたいですが、このページは、jQuery Easing Plugin のエフェクトの確認として秀逸です。
アレどうやって動くんだっけと疑問になったときは、ここで確認です。

jQuery:可変グリッドレイアウト(jquery.vgrid.js)

jquery

可変グリッドレイアウトjQueryプラグイン(jquery.vgrid.js)を某プロジェクトで使わせていただいています。
用途としては、固定幅のコンテンツなんで可変である必要はないんですが、リロードするたびにランダムに並び順が変わるという効果として使っています。
 
こういう固定幅のコンテンツの場合、再描画で各画像のポジション計算が狂って上の方に重なって表示される場合があります。(easingのパラメータの調整で出にくくすることもできますが、完全に出ないわけではありません)
たぶん、ウィンドウサイズが変わった場合の再描画では問題がないのでしょうから、ウィンドウサイズが変わらないような状況で使っている方が悪いのですが、たまにでも、画像が上の方に重なるといろいろ不都合が。(「表示上の問題なんです、F5キーを押してください」と言いたいところですが、見た目、いかにもなにか重大なバグが発生したように見えて、結構厳しいです)
 
初期化のあと、すぐ vgrefresh() してみたり、vgsort() してみたり、あと、一緒に動く JSがあるとそうなる頻度が上がるので、後ろの方にずらしてみたりしたんですが、なかなかこれといった対策もなく。
外そうかなと思った瞬間、パッと思いつきました。

#grid-content {
  display:none;
  display:block\9;	/* IE7, IE8 */
  overflow:hidden;
  height:0;
  margin-left:-1px;
}

「最初は消しときゃええやん」と。これでばっちりです。IEだけは消しとくとほんとに出てこなくなりましたので、出しときました。
作者さま、ありがとうございました。

追記:これだとページ内ジャンプのとき、やっぱり表示できないケースがありました。なので、上のIE対応は止めて、基本表示しないで別のタイミング(他のJSが動くとき)、これ(↓)を入れることにしました。

$("#grid-content").css('display', 'block');

なんか泥縄式になっているような気がするのは気のせい?
再追記:これでもうまくいかないことがあったので、更に vgrefresh() を足しました。いよいよ泥縄(泥船)です。

$("#grid-content").css('display', 'block');
$("#grid-content").vgrefresh();

ちなみにランダムの方は上流(コンテンツを準備する側)でやることにしました。

query_posts('category_name=top&posts_per_page=-1&orderby=rand');

posts_per_page=-1 は無制限、orderby=rand が並び順ランダムです。

jQuery:Thickbox

jquery

長年の懸案だった、Thickboxが IEでうまく動かない件がやっと解決しました。それも自力で。エライね>自分。
懸案事項は次の2点。

  • 縦に長い画面で、下にスクロールしたところでウィンドウを出すと、画面中央に出ず、上の方に隠れてしまう。(画面TOPからの固定位置で表示される)
  • このような場合、画面と一緒にスクロールしてしまう

本来は、どのような状況でもウィンドウは画面中央にきて、スクロールは背面の画面がスクロールするだけでウィンドウの位置は変わらないというのが正しい挙動です。もちろん、オフィシャルサイトのデモはそういう動きをしています。
それがどうしておかしくなるかというと、DOCTYPEの「標準モード」と「互換モード」の違いでした。



上が互換モードで、下が標準モードです。
Thickboxを互換モードで動かそうとすると、IEに限って、上のような現象に遭遇します。Firefoxとか Chromeは大丈夫なのが現象をわかりづらくしてますね。

jQuery:Uploadify

jquery

PHPで複数ファイルのアップロードをなるべくスマートにやる方法はないかなぁと探し回ってたどり着いたのが、コレ。
自分的にはベストな解答です、たぶん。
 
詳しい使い方は「Ajax風にファイルをアップロードするjQueryプラグイン「Uploadify」の使い方」が超詳しいので、こちらを参照のこと。
 
以下は自分的にポイントとなったところ。

  1. 既存のPHPシステム(例えば、EC-CUBEなど)とはできるだけ独立した形にしたかったので、少し工夫した。
  2. 呼出し部分は小さいので、display:none で本体のHTMLに組み込む。例えば、こんな感じ。
    
    $(document).ready(function() {
      $("#uploadify").uploadify({
        'uploader'     : '<!--{$TPL_DIR}-->js/uploadify/uploadify.swf',
        'script'         : '<!--{$TPL_DIR}-->js/uploadify/uploadify.php?rand_no=<!--{$rndNo}-->',
        'cancelImg'  : '<!--{$TPL_DIR}-->js/uploadify/cancel.png',
        'folder'         : '<!--{$smarty.const.IMAGE_TEMP_URL}-->',
        'queueID'     : 'fileQueue',
        'auto'          : false,
        'buttonText' : 'Select Files...',
        'multi'         : true
      });
    });
    
    <div>
      <p style="margin:0">画像ファイルを選択して、Uploadしてください。</p>
      <div></div>
      
      <div style="float:right"><a href="fnModeSubmit('upload_image','image_key','sub_image'); tb_remove();">Close Window</a></p></div>
      <p><a href="$('#uploadify').uploadifyUpload();">Upload Files</a> <a href="jQuery('#uploadify').uploadifyClearQueue()">Cancel All Uploads</a></p>
    </div>
    

    ちょっと見慣れない細工コードが入っているのは無視無視。たったこれだけでアップローダ定義完了。

  3. 特殊なことをしている点は、複数の人が同時にこのアップローダを使った場合、同じテンポラリ・フォルダを使うことになるので、ファイル管理用のランダム文字列を持たせたこと。(ほんとは rand()だとかぶる危険性もあるんだけど、今回は管理画面からのアップロードということで、せいぜい10人未満の同時使用しかないだろうから、そこには目を瞑った)
  4. それと、#uploadブロックは通常非表示で、Thickboxのモーダル・ウィンドウで上がってくるようにしている。
    <a href="#TB_inline?height=430&amp;width=405&amp;inlineId=upload&amp;modal=true" title="Uploadify" class="thickbox">Uploadify</a>
    

    こうすると本体のHTMLを汚さなくて済むからいいよね。で、Close Windowのとき、fnModeSubmit()といういままでアップロードボタンに割りつけていた関数を呼んでフックをかけると。

  5. サーバ側もいたってシンプル。
    if (!empty($_FILES)) {
      $tempFile = $_FILES['Filedata']['tmp_name'];
      $targetPath = str_replace('//','/', $_SERVER['DOCUMENT_ROOT'] . $_REQUEST['folder'] . '/');
      $targetFile =  $targetPath . $_FILES['Filedata']['name'];
      move_uploaded_file($tempFile,$targetFile);
    
      $_FILES['Filedata']['tmp_name'] = $targetFile;
      $fp = fopen($targetPath.$_REQUEST['rand_no'], "a");
      fputs($fp, serialize($_FILES['Filedata'])."\n");
      fclose($fp);
      echo "1";
    }
    

    複数ファイルをまとめてアップロードすると、この PHPが回数分呼ばれることになる。
    やってることは、渡されたファイルをフォルダに移して、なんのファイルを移したかファイルに記録しておくだけ。
    このときのファイル名に例のランダム文字列を使ってる。

  6. あとは、この $_FILES がシリアライズされたファイルを読んで、あたかも $_FILESで入ってきたように振舞ってやれば OK。
    $no  = 0;
    $buf = @file(IMAGE_TEMP_DIR . $this-&gt;rndNo);
    if ($buf) {
      foreach ($buf as $e) {
        $no++;
        $key = "sub_image".$no;
        $_FILES[$key] = unserialize($e);
        $this-&gt;arrErr[$key] = $this-&gt;objUpFile-&gt;makeTempFile($key, IMAGE_RENAME);
      }
      @unlink(IMAGE_TEMP_DIR . $this-&gt;rndNo);
      unset($_POST['rand_no']);
      unset($this-&gt;rndNo);
    }
    

    EC-CUBEのコードにがっつり入り込んでいるのでわかりにくいけど、シリアライズされたファイルを読んで、アンシリアライズしたものを $_FILESにセットして、処理を継続しているだけ。終わったら、後始末しておく。

こんな感じで活用させていただいてます。ありがとう、Uploadify

jQuery:Thickbox

jquery

いつもお世話になっている Thickboxですが、画像の拡大表示くらいしか使っていなかったんですけど、よんどころない事情でインライン表示を使うことになって、いまさらながらのポイントもわかり、きっとあとで見ると思うので、メモメモ。
 

  1. 別ファイルをモーダルで表示するとき、どうやって閉じればいいんだ?
    こう「self.parent.tb_remove();」します。具体的には、こんな感じ。
    <a href=”javascript:self.parent.tb_remove();”>Close Window</a>
  2. Thickboxをドラッグ可能にする
    これはまだ試してないけど、動かせなくて不便だなと常々思っていたので、そのうちやってみます。
    jQuery UI Draggable を使えば簡単よ、ということらしい。
  3. Thickbox呼び出し方のまとめ
    <a href="#TB_inline?height=xxx&amp;width=xxx&amp;inlineId=divID" class="thickbox">EXAMPLE</a>
    <a href="#TB_inline?height=xxx&amp;width=xxx&amp;inlineId=divID&amp;modal=true" class="thickbox">EXAMPLE</a>
    <a href="http://url.com?keepThis=true&amp;TB_iframe=true&amp;height=xxx&amp;width=xxx" title="xxx" class="thickbox">EXAMPLE</a>
    <a href="http://url.com?placeValuesBeforeTB_=savedValues&amp;TB_iframe=true&amp;height=xxx&amp;width=xxx&amp;modal=true" title="xxx" class="thickbox">EXAMPLE</a>
    

    keepThis や placeValuesBeforeTB_ はなくてもへっちゃらみたいです。

jQuery:later

jquery

例の CrossSlide がウザいから1回で止めてくれと、お客様じゃなくて社内から声が。あんたが入れろって言ったんじゃんか!と喉元まで出かかった言葉を呑み込んで、ハイハイと素直に答える優しい技術者。
でも、ソースを読んでも、止める方法が書いてない。

$.fn.crossSlideFreeze = function()
{
    this.find('img').stop();
}

crossSlideFreezeという関数を呼べば止まるみたいだけど、どうやって呼べばいいんだ?
スライドに飽きたら[Stop]ボタンをユーザに押してもらうか。そんなバカな。
ということで、ある程度時間が経ったら止めることにしました。

(function($) {
	$.fn.later = function(arg, fn) {
		var self = this;
		var timer = setTimeout(function() {
			clearTimeout(timer);
			self.each(fn);
		}, arg);
		return self;
	};
})(jQuery);

こういうのを外部ファイル(例えば、jquery.later.js)に置いておいて、こんな風にします。

&lt;script type=&quot;text/javascript&quot; src=&quot;/js/jquery.later.js"&gt;

  jQuery(function($) {
    $('#gallery1').later(80000, function() {
       $(this).find('img').stop();
    });
  });

80秒経ったら、gallery1のすべての imgを止めてしまえ、です。フェードの途中でも有無を言わさず止まってしまって面白いです。

jQuery:LavaLamp

lavalamp

LavaLampと書いてもピンときませんよね。
グローバル・ナビゲーションで、マウスをもっていくと、ビヨーンと背景ブロックが追っかけてくるやつです。
こう書いてもきっとわかりませんね。
 
lavalamp1
こんなやつです。使い方。
頭で指定しておくのはお決まり。ULにメニューを書いていきます。
下の例は、ULの背景にメニュー画像を置いて、その上を透過パネル(少し斜がかかったもの)が移動するようにしたものです。
メニュー画像を載せられればわかりやすいんだけど、今制作中のお客様のやつなんでね。


&lt;script type=&quot;text/javascript&quot; src=&quot;/js/jquery.lavalamp.js"&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;/js/jquery.easing.1.1.js"&gt;

  jQuery(function($) {
    $("#nav1").lavaLamp(
      {
        fx: "backout",
        speed: 700
      }
    );
  });

<ul class="lavaLampNoImage">
    <li class="current"><a href="#">MENU</a></li>
    <li><a href="/party/">PARTY PLAN</a></li>
    <li><a href="/access/">ACCESS</a></li>
    <li><a href="/contact">CONTACT</a></li>
</ul>
.lavaLampNoImage {
	background:#fff url(images/top-menu.png) no-repeat;
	width: 898px;
	height: 78px;
	position: relative;
	overflow: hidden;
	padding:1px;
	margin: 0;
	border: none;
}
.lavaLampNoImage li {
	margin:0;
	padding:0;
	float: left;
	list-style: none;
}
.lavaLampNoImage li.back {
	position: absolute;
	z-index: 8;
	height: 76px;
	background-color:#fff;
	opacity:0.2;
	filter:alpha(opacity=20);
	-ms-filter:"alpha( opacity=20 )";
}
.lavaLampNoImage li a {
	position: relative;
	z-index:10;
	display:block;
	overflow: hidden;
	float: left;
	height: 76px;
	font-size:8px;
	color:#C1955C !important;
	text-decoration:none;
}
.lavaLampNoImage li a:hover, .lavaLampNoImage li a:active, .lavaLampNoImage li a:visited {
	border:none;
}
#nav1l1, #nav1l1 a { width:152px;	}
#nav1l2, #nav1l2 a { width:197px; margin-left:2px;	}
#nav1l5, #nav1l5 a { width:121px; margin-left:2px;	}
#nav1l6, #nav1l6 a { width:123px; margin-left:2px;	}

jQuery:CrossSlide

jquery

 
大きな画像を上下左右にスライドさせて表示するプラグイン。
Ken Burns effectみたいにグイングインさせるのではなく、up、downにゆるゆると動かしてフェードみたいな感じが使いたくて。
使い方は割と簡単。
注意点は、jquery.js?ver=1.2.6 だと動かなかったこと。jQuery.isEmptyObject()を使っているので、1.4 over じゃないとダメみたいね。


&lt;script type=&quot;text/javascript&quot; src=&quot;/js/jquery.cross-slide.js"&gt;

  jQuery(function($) {
    $('#gallery1').crossSlide(
    {
      speed: 15, //in px/sec
      fade: 4    //in sec
    },
    [
      { src: '/tops-1.jpg', dir: 'up'   },
      { src: '/tops-2.jpg', dir: 'down' },
      { src: '/tops-3.jpg', dir: 'up'   }
    ]
  );
});

$tmp、$imgはそれぞれのディレクトリを適宜セットすること。
使いたいところに、#gallery1 を書いて、cssは width と height だけ指定しておけば、OK。

<div>Now Loading ...</div>
#gallery1 {
	width:900px;
	height:388px;
}

ウィンドウサイズより画像の方が小さかったり、fadeを大きくすると、すぐエラーで怒られたりするので、使い方がちょっと難しいけど、まぁ、お手軽です。

Nivo Sliderを使ったときの些細な問題点

 
Nivo Slider はすばらしいライブラリなんですが、IE8(or IE7)で使うと、タイミングによってたまに『 ‘undefined’は null またはオブジェクトではありません。』というエラーが出ることがあります。
たまにというのはずいぶんと控えめな表現で、リロードしたりページ切替えしたりしていると、2、3回に1回くらいの頻度でこのエラーが出て、画像が切り替わらないということになります。(私の環境では)
FirefoxやChromeでは相当激しくそうやってもならないので、「IEってバカなのね」で済ましてもいいんですが、まだまだ50%以上のシェアをもつブラウザを無視すると、あとで痛い目にあうのはこっちなので、なんとか対処しなければ。
 
エラーが発生するのは、http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js の中なので、これを見てみるとって、パックされたソースを見るのは嫌!ということで、http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js に置き変えてみたところ、ピタッとエラーが止まりました。
 
そういうことなんですね。

Nivo Slider

Nivo Slider という、jQueryを使ったかっちょいいスライダーです。
サムネイル画像の上にマウスをもっていくと(マウスオーバー)、メインの画像が切り替わるというのはよくやることですよね。
あれはただ、onMouseOver = “jQuery(‘#main-img”).attr(‘src’, ‘sub-img-02.jpg’);” みたいなことをしてるだけで、切替え効果などは特に考えていないわけなんですが、このハデハデ GUI全盛の折にそれでいいのか、ということです。(ボクはシンプルな方が好きなんですけど)
で、Nivo Slider の出番です。

  • サムネイルに対応している
  • 画像にキャプションをかぶせられる
  • 勝手に動かない(スライドショーじゃないので)

こんなわがままな要望をかなえてくれます。
実際に使うときの注意点は、こんなところ。

  • jQueryの 1.2.6には対応していないので、素直に ajax.googleapis.com から最新版(1.4.2)を取ってきましょう。
  • jquery.nivo.slider.pack.jsのソースを見ると、ほぇ?! っとなりますが、大丈夫。これで動きます。
  • $(window).load(function() になっているところもそのままで。入れるタイミングがあるようです。
  • manualAdvance:true にすると勝手に動きません。
  • controlNavThumbs:true でサムネイルが出ます。
  • サムネイルファイルは、画像と同じところに『同じ名前_thumb.jpg』というファイルを作っておきましょう。
  • キャプションは、imgの title に設定します。