jQueryのprevAllメソッドを使う際の注意


兄弟要素のうち、指定要素より前の要素をすべて取得するprevAllメソッド。仕様を少し勘違いしていたのでここにメモしておきます。

例えば、下記のようなHTMLがあったとします。

この状態でJavaScriptを下記のように記述します。

上記の記述は、IDがli_e、つまり『え』と書かれた要素より前の兄弟要素を全て取得し、その一つ目(eq(0))の要素内のテキストをコンソールに出力という指定です。

ここで問題です。コンソールにはどういう文字が出力されるでしょう。自分はこういう記述の場合、『あ』となるだろうと思ってました。

正解は『う』です。ちなみに、eq(1)とすると『い』と出力されます。prevAllで取得した要素は実際の順序とは逆になってしまうんですね。確かに直前の要素が一つ目というのはある意味便利かもしれませんが、ちょっと予想外の動きでした。

jQueryのanimateメソッドではJavaScriptオブジェクトも操作できるという話


jQueryのanimateメソッド、名前のとおりアニメーションを表現する際に利用することもあり、とても重宝しています。例えば、以下のようなコード。

上記のコードは、animate_divというIDのついた要素のwidthを1秒掛けて500pxにするアニメーションを実現するコードです。

ところで、このanimateメソッド、jQuery最高の教科書という本を読んで知ったのですが、JavaScriptオブジェクトの操作もできるみたいなのです。これだけだとちょっと意味が分からないと思うので、下記にカウントダウンのような動きをするサンプルコードを記してみます。

こうすることで、{‘count’:10}というJavaScriptオブジェクトを操作して、10秒(10000ミリ秒)で{‘count’:0}という状態にまで変化させます。progressというオプションはアニメーションのステップごとに実行する関数です(参考:.animate() | jQuery 1.9 日本語リファレンス | js STUDIO)。

というわけで、以下実行結果。

ちなみに、console.timeとconsole.timeEndはそれぞれの引数に指定した文字列が同じ組の間の時間をコンソールに表示するメソッドです。試してみると、10秒より少し大きい数値がコンソールに表示されると思います。

jQueryのセレクタ指定においてnth-childは1始まりだが、eqは0始まり


もしかしたら、jQueryの基本中の基本なのかもしれませんが、最近知ったので、一応メモ。

jQueryのセレクタ指定において、:nth-child(n)は要素を1始まりで取得しますが、:eq(n)は0始まりなようです。

例えば以下のようなHTMLソースがある場合、

以下のようなコードを書くと、

“liタグ1つ目”と書かれたliタグの背景は赤くなり、”liタグ2つ目”と書かれたliタグの背景は青くなります。

憶え方としては、CSSの擬似クラスにもある指定方法は1始まりで、jQueryオリジナルの指定は0始まりとのこと。例えば、CSSにもある:nth-of-typeも1始まり。

上記のようなコードの場合は、”pタグ1つ目”と書かれたpタグの背景は赤くなり、”pタグ2つ目”と書かれたpタグの背景は青くなる。なお、nth-of-typeは子要素のうち擬似クラスがついたタグのみで考えるのにたいし、nth-childは子要素すべてを数えるので、”pタグ1つ目”と書かれたpタグの背景は緑色にならない(もし、h3タグがなければ緑色になる)。

なお、これは偶数を指定するeven(奇数ならodd)でも同様。

例えば上記のようなコードがある場合、”liタグ1つ目”,”liタグ3つ目”,”liタグ5つ目”と書かれたliタグの背景は青くなり、”liタグ2つ目”,”liタグ4つ目”,”liタグ6つ目”と書かれたliタグの背景は赤くなる。

実行サンプル:jQueryのnth-childは1始まりで、eqは0始まり

jQueryで作成した要素をランダムに並び替えて表示する方法


jQueryで作成した複数の要素をランダムに並び替えて表示したいという状況に遭遇したのでいろいろ工夫してやってみました。

具体的にいうと、クイズコンテンツを作ろうとしたのですが、100問あるクイズはランダムに表示するようにしたいと思いました。最初にとりあえず100問分の要素を作成したうえでそれをランダムに並び替えて・・・。と思ったのですが、それだとかなり効率が悪そうな気がしました(そもそも、うまい実装方法が思いつかない)。

ただ、よくよく考えたら、まず最初に作ったのを一つおき、2つ目はその前後2つのうちどちらかランダムで挿入、3つ目は最初か1つ目の要素と2つ目の要素の間か最後の3つのうちどれかにランダムで挿入、n個目は挿入できるn個の場所のどれかにランダムで挿入・・・というようにしたらランダムで並び替えたことになるんじゃないかと思って実装してみました。
以下、実装サンプルです。久々にjsfiddleを使ってみました。

ただたんに、0~100の数値が書かれたdiv要素をランダムに並び替えて表示するプログラムです。多分、これで問題ないはずです。何度か試しましたが、偏ってなさそうでした。

Hammer.jsを使ってダブルタップを実装してみた


仕事でiPad用のウェブサービス作っているのですが、仕様書を見ると『ダブルクリックで拡大』なんて項目がありました(注:ダブルクリックとはダブルタップのことです)。調べてみると、JavaScriptでダブルクリック用のイベントを実装してもiPadではダブルクリック≠ダブルタップのようで、ダブルタップを実装したい場合は独自に実装しなきゃいけないということが発覚(参考:iPhone/iPadでダブルタップをJavaScriptで実装する – to-R)。

そこで、何かいいライブラリがないだろうかと探してみたらHammer.jsというタッチ対応ライブラリを見つけたのでさっそく使ってみました(参考:スマホのマルチタッチジェスチャーを判断できるjQueryプラグイン「Hammer.js」: 小粋空間)。
Hammer.js – A javascript library for multi-touch gestures
jQueryプラグインがどこにあるか分からず少し探したので、jQueryで使う場合のjquery.hammer.jsのインストールページも下記にリンクしておきます。
EightMedia/jquery.hammer.js · GitHub

まず、headタグ内にjQuery、Hammer.js、Hammer.jsのjQueryライブラリという順番に読み込む。

参考に、JavaScript内にはliタグをダブルタップすると、そのliの要素のHTML(innerHTML)をbodyの最後に挿入するようという動作を実現するコードは以下。

ただし、これだとダブルタップした時にその部分を拡大表示してしまうという動きになってしまうという問題があります。この解決方法として、metaタグのviewportのcontent属性に”user-scalable=no”とすれば拡大しなくなります。が、これだとピンチインやピンチアウトでも拡大縮小しなくなります。やりたいことはあくまで、対象の要素にダブルタップした時に拡大しないようにしたいだけなので、下記のように書きなおすことに。

タッチがはずれた時の標準イベントをe.preventDefault()で止めています。これで、拡大しないようになりました。

以下、実行サンプル
hammer.js テスト

数値をダブルタップすると、ページ下にダブルタップした位置の数値とダブルタップした位置のドキュメント内相対座標とウィンドウ内の座標を書くようにしています。また、親要素のulタグをクリックした場合には”ul”と書くようにもしています。標準イベント(拡大)については、奇数の数値のみ($(‘li:odd’)のみ)ストップするようにしています。つまり、0の箇所をダブルタップすると拡大しますが、1のところをダブルタップしても拡大しません。

iPod touchのSafariで試してみましたが、奇数の文字をダブルタップしても拡大されませんでした。偶数の文字をダブルタップすると拡大するのですが、なぜか”ul”が表示されません(PC版Chromeでは表示されました)。左側のulのpadding部分をタップしてみると”ul”と表示されたのでulタグをタップすると”ul”と表示されるのですが・・・。

まあとにかく、Hammer.jsは便利そうです。ホールドも実装できるので、いろいろと面白いUIも実現できそうですね。ただ、指定できるオプションについてはほとんど分かっていない状態なので、活用していくにはまだ勉強が必要そうです。