jQuery1.4 リリース
2010年1月14日に、jQuery1.4がリリースされました。
昨年のjQuery1.3のリリース以来、ちょうど1年ぶりのメジャーバージョンアップです。
速度の劇的向上
jQueryの売りである速度がさらにブラッシュアップされました。 画像はこちらsetter関数がより簡単に
今までも.attr()を使って、コールバック関数の戻り値をDOMの属性にセットすることができましたが、この機能が全てのsetter関数に拡張されました。(.css(), .attr(), .val(), .html(), .text(), .append(), .prepend(), .before(), .after(), .replaceWith(), .wrap(), .wrapInner(), .offset(), .addClass(), .removeClass(), .toggleClass())
さらにこれらのうちいくつかのメソッドでは第二引数に現在の値を渡すことができます。
(.css(), .attr(), .val(), .html(), .text(), .append(), .prepend(), .offset(), .addClass(), .removeClass(), .toggleClass())
// aタグの中からアンパサンド(&)を見つけ、spanタグで囲む $('a').html(function(i,html){ return html.replace(/&/gi,'<span class="amp">&</span>'); }); // aタグのtitleに文字を付け足す $('a[target]').attr("title", function(i,title){ return title + " (別ウィンドウが開きます)"; });
Ajax
配列のserialization
jQuery1.4からjQuery.param()において引数に配列(入れ子構造のパラメータ)が使えるようになりました。例えば{foo:["bar","baz"]}はserializeの結果、"foo[]=bar&foo[]=baz"と出力されます。
jQuery1.3では {foo: ["bar", "baz"]} はserializeされると"foo=bar&foo=baz"と出力されていました。
この古いバージョンの挙動の方がいいという場合は下記の方法で設定が選べます。
// 全てのserializationを一括で設定 jQuery.ajaxSettings.traditional = true; // この1回のみ設定 jQuery.param( stuff, true ); // この1回のAjax通信のみ設定 $.ajax({ data: stuff, traditional: true });
詳しくはこちら(jQuery.param(),jQuery.ajax())
content-typeで自動制御
AjaxのレスポンスがJSON mime typeで返ってきた場合、特に指定がなければdataTypeはデフォルトで"json"に設定されます。
JavaSript mime type の場合は、同じくデフォルトのdataTypeは"script"となります。これによりスクリプトが自動実行されます。
Etagサポート始めました
デフォルトではjQueryはブラウザのキャッシュを使わず都度リクエストを行なうように、Last-Modifiedヘッダを無視します。
ifModifiedをtrueに指定すると、ブラウザのキャッシュを利用します。
jQuery1.4からはさらにifModifiedを指定した場合、If-None-Matchヘッダも送信します。
JSON形式への変換が厳密に
jQuery1.3以前のバージョンでは受け取ったJSON形式のデータをevalで評価していました。
jQuery1.4からは可能であればnativeのJSONパーサを利用します。
引数として受け取ったJSON形式のデータもチェックします。
ですので例えば{foo: "bar"}という誤ったフォーマットのデータはjQuery.getJSONでは受け取れません。
これはAjax RequestでdataTypeを"json"と指定した場合も同様です。
HTML5の要素もserialize対応
新しいHTML標準であるHTML5のinput要素(datetimeやrangeなど)もserialize()されます。
Ajax通信の書き方
Ajax通信は以下のように行ないます。
コールバック関数をこのように書くことでコードを短縮し、場合によってはクロージャや他のオブジェクトを使わずに済みます。
jQuery.ajax({ url: "test.html", context: document.body, success: function(){ jQuery(this).addClass("done"); } });
Success時のコールバック関数が第三引数にXHRを受け取るように
success時のコールバック関数が第三引数にXMLHttpRequestオブジェクトを受け取るようになりました。
以前のバージョンだとこのXMLHttpRequestオブジェクトは$.ajaxの戻り値としてしかアクセスできませんでした。
content-typeは正確に
jQuery1.3では、送信データが空だった場合contentTypeオプションは無視されます。
jQuery1.4では、contentTypeは毎回送られます。この変更はレスポンスの種類を決めるバックエンド処理に多少影響します。
Avoid pre-flighting cross-domain XHR
クロスドメインのAjax通信をサポートしているブラウザであっても今後はデフォルトでクロスドメイン通信は禁止されます。
タイマーではなくonreadystatechangeイベントを
Ajax通信の際には、タイマーを使って順次問合せを自前で実装するよりもonreadystatechangeイベントを使った方が簡単です。
Attributes
.css()と.attr()が速くなりました
.attr()が引数にsetter関数を使えるように
attr()で関数を使えるだけでなく、その関数に現在の属性の値も渡すことができるようになりました。
//"enter.png"という画像のalt属性に、 //"Please, enter you name"("Please,"以降の文字列はalt属性から取得)をセットする jQuery('<img src="enter.png" alt="enter your name" />') .attr("alt", function(index, value) { return "Please, " + value; });
.val()の引数に関数を使えるようになりました
<input class="food" type="text" /> <input class="food" type="text" />
jQuery("input:text.food").hide(); jQuery("⁢ul class='sortable'> <li>Peanut Butter</li><li>Jelly</li></ul>") .sortable() .bind("endsort", function() { $(":text.food").val(function() { return $("ul.sortable li:eq(" + $(this).attr("data-index") + ")").text(); }); });</li>
.text()がテキストだけでなくCDATAセクションでも使えるようになりました
Core
要素を素早く生成
jQueryで要素を生成すると同時に、オブジェクトに渡すことでその要素にAttributeやEventを追加することができます。
jQuery(" <div>", { id: "foo", css: { height: "50px", width: "50px", color: "blue", backgroundColor: "#ccc" }, click: function() { $(this).css("backgroundColor", "red"); } }).appendTo("body");</div>
.eq(-N), .get(-N)
.get()と.eq()にマイナスの数を指定できるようになりました。
例えば、最後から2つめのdivを取得したい場合は以下のように書きます。
$("div").eq(-2); $("div").get(-2);
.first()と.last()が新たに追加
よく使われるので.first()は.eq(0)の、.last() は.eq(-1)のエイリアスとして追加されまし> た。
.toArray()が新たに追加
.get() はVer.1.3まで戻り値の型は配列でした。
ですが、今後の混乱を避けるために配列を返すための関数として.toArray()を追加しました。
.get()と違い、.toArray()は引数を取りません。
jQuery()が空のセットを返すようになります
Ver.1.3ではjQuery()の戻り値はdocumentのみを含むjQueryのsetでしたが、Ver.1.4からは空のjQueryのsetに変更になりました。
これは戻り値で動的に要素を生成する際に便利です。
注意:jQuery().ready()を使ったテクニックはVer.1.4でも動作しますが、非推奨です。
jQuery(document).ready()もしくはjQuery(function(){})を使ってください。
jQuery("タグ名")
1つしか存在しないタグ名でセレクトすると高速です。
jQuery("<div>") と jQuery("<div/>") と jQuery("<div></div>")
この3つのやり方は内部ではどれも同じコードパスを経由します。(document.createElementを利用)
jQuery("<div></div>")と書いた場合の速度を改善しました。
属性を指定した場合、jQuery内部では利用ブラウザのネイティブのパーサを使うことに注意してください。
CSS
.css()の速度が約2倍向上しました
.addClass(), .removeClass(), .hasClass()の速度が約3倍向上しました。
画像はこちら p>
.toggleClass()で複数のclassを指定できるようになりました
$("div").toggleClass("current active");
Data
data()はgetter関数に、.data(Object)はsetter関数に
要素に結びついたデータをそっくりそのまま(完全な形で)使いたいケースはよくあるのではないでしょうか?
よくある例である要素のクローンを作る際にその要素の全てのデータをコピーしたいというケースがあります。
Ver.1.4では、.data()を引数なしで使った場合は完全なデータを返し、 .data(Object)というように引数にオブジェクトを渡すとその内容をセットします。
このオブジェクトには要素にバインドされたイベントも含まれるので使う際には注意してください。
Data cache は必要な時にだけ生成
jQueryは特定の要素に対して.data()で情報を取得する際に、独自の拡張を行なっています。
今回のVer.アップで、検索されたデータが見つからなかった場合、この拡張をしないように修正しました。
これによりパフォーマンスの向上とDOMの汚染防止が期待できます。
Effects
各プロパティごとにEasingを指定可能に
animationごとにeasing関数を指定できるようになったことに加え、それぞれのプロパティごとにもeasing animationが指定できるようになりました。
これについてはJames Padolseyがこのエントリーで詳しく述べています。デモもあります。
$("#clickme")click(function() { $("div").animate({ width:["+=200px","swing"], height:["+=50px","linear"], }, 2000, function() { $(this.after(" <div>Animation complete.</div> "); }); });
Events
新しいメソッド: jQuery.proxy()
あるスコープの内部に限り"this"が示す値を固定したいという場合は、jQuery.proxy()を使うことができます。
var obj = { name: "John", test: function() { alert( this.name ); $("#test").unbind("click", obj.test); } }; $("#test").click( jQuery.proxy( obj, "test" ) );
Eventの複数指定
オブジェクトを引数に渡すことで1つの要素に複数のEventを一括バインドできるようになりました。
$("div.test").bind({ click: function(){ $(this).addClass("active"); }, mouseenter: function(){ $(this).addClass("inside"); }, mouseleave: function(){ $(this).removeClass("inside"); } });
'change'と'submit'イベントの挙動を統一
changeイベントとsubmitイベントは通常のイベントハンドリングとlive events共に、ブラウザにより挙動が異なっていました。
今回のリリースでInternet Explorer上での通常のchangeイベントとsubmitイベントの挙動を他のブラウザと統一しました。
新しいイベント: 'focusin'と'focusout'
focusinとfocusoutはfocus、blurとほぼ同義ですが、bubbling処理が行なわれるケースに関しては違います。
focusとblurはlive()では設定できないことに注意してください。
$("form").focusout(function(event) { var tgt = event.target; if (tgt.nodeName == "INPUT" && !tgt.value) { $(tgt).after("<span>nothing here</span>"); } });
ほぼ全てのイベントがLive Events対応
readyとfocus(代わりにfocusin> 利用を推奨)、そしてblur (代わりにfocusout利用を推奨)を除き、bind()でバインドできる全てのイベ ントがliveイベントで使えるようになりました。
.live()で実行される下記イベントのクロスブラウザサポートも実装したことを報告します。(change, submit, focusin, focusout, mouseenter, mouseleave)
前述の通り、focusとblurはバブリング処理に対応していないので、focusイベントを利用する場合は、focus/blurではなくfocusin/focusoutを使ってください。
また、bind()と同様にlive()も引数にDataオブジェクトを受け取れるようになりました。
live()とdie()でコンテキストを指定可に
live()イベントにバインドするセレクターのコンテキストを指定できるようになりました。
この場合、そのコンテキスト内の要素のみにイベントが登録されます。
live()イベントを生成するタイミングで必ずしもその要素が存在する必要はありませんが、そのコンテキストは存在していなければいけません。
readyイベントにbodyの存在は必須
jQueryはbody要素の存在をチェックし、もしない場合はbody要素を生成します。
メモリリーク用の処理を必要としないIE以外のブラウザではUnload()の速度が向上しました。
Manipulation
DOM要素の操作メソッドの速度が大幅に向上しました。
.append()、.prepend()、.before()、そして.after()が早くなりました
.html()が約3倍速くなりました
.remove()とempty()が約4倍速くなりました
新メソッド:detach()
detach()は関連するイベントハンドラはそのままに、DOMから要素のみを削除するメソッドです。
要素を一時的に削除した後、再び生成する際に便利です。
var foo = $("#foo").click(function() { // do something }); foo.detach(); // fooはイベントハンドラを保持している状態 foo.appendTo("body");
新メソッド:unwrap()
新しいメソッドunwrap()は与えられた親要素が持っている子要素を取り出し、 その親要素と置換します。
<div> annie davey stevie</div>
$('div').unwrap();
annie davey stevie
内部関数でキャッシュを保持
jQuery("<div>")や.after("<div>")などのメソッドで生成された要素はjQuery内部でキャッシュとして保持するようにしました。
これにより文字列を引数として使うDOM操作系の関数のパフォーマンスがかなり向上しました。
before()、after()、replaceWith()をDOMにない要素にも適用可
これらのメソッドをDOMに紐付けられていない要素にも使えるようになりました。
これでさらに複雑なDOM操作が可能になり、DOM操作が行なわれている間の描画の再計算も回避できるようになりました。
jQuery("<div>").before("Hello").appendTo("body")</div>
.clone(true)がデータもコピーします
jQuery1.3の.clone(true) は要素だけでなくイベントもコピーしていましたが、データまではコピーしませんでした。
jQuery1.4では、イベントに加えデータもコピーします。
jQuery.extendと同じ文法で用い、今までは使えなかったプレーンなogjectや空の配列のコピーが作れます。
Offset
.offset()
要素に対してオフセットを設定できるようになりました。
また、他のセッター関数と同様に、第2引数として関数を受け取ることができます。
Queueing
キューは全体的に見直され、デフォルトのfxキュー以外のキューを利用できるように改善されました。
(訳注:キューには名前をつけていくつかのキューを並行して管理できるらしい。デフォルトのキューはfx。)
新しい.delay()メソッド
.delay()メソッドはキューに入っている要素の実行を指定したミリ秒ほど遅らせます。
第2引数なしで呼び出した場合は、fxのキューを利用します。
オプションで第2引数を指定して別のキューに入れることができます。
$("div").fadeIn().delay(4000).fadeOut();
Queue next
jQuery1.4ではキューで実行される関数の第1引数として、次に実行される関数が渡されます。
その引数の関数を呼び出すと自動的にキューを一つ進めます。
jQuery("div").queue("ajax", function(next) { var self = this; jQuery.getJSON("/update", function(json) { $(self).html(json.text); next(); // このnextが第1引数で渡されたnextであり、 // 実際に実行されるのは次のキューである↓の無名関数 // dequeue()しなくてもキューが進行する。 }); }).queue("ajax", function() { $(this).fadeIn(); });
.clearQueue()
キューは消去できるようになりました。このメソッドは未実行の関数を全てキューから消去しますが、実行中の関数を停止することはありません。
引数なしで呼び出した場合、fxのキューを消去します。
Selectors
"#id p"と指定した方が速い
ID指定で始まるセレクタは瞬時にDOMを選択できるよう最適化されており、そのように指定したセレクタは常に最速です。
Traversing
.index(), .index(String)
.index()メソッドは書き直され、より直感的で柔軟になりました。
1.4ではある要素の兄弟要素の中でのインデックス(番号)を取得できるようになりました。
// <li class="current">となっている最初のli要素の、 // 兄弟要素(同じulの中のli)の中での番号を取得 $("li.current").index()
index()メソッドの引数にセレクタを渡すことで、そのセレクタにマッチする要素の中での番号を取得できます。
// <h3 id="more-info">の、ドキュメント内全ての<h3>要素内での番号を取得 <h3 id="more-info"> in relation to all</h3> <h3> elements: $("#more-info").index("h3")</h3>
新しい.has()メソッド
このメソッドはセレクタ書式での:has()フィルタをメソッド化したものです。
あるjQueryセットのうち、指定したセレクタにマッチするものだけを返します。
新しい.nextUntil(), .prevUntil(), .parentsUntil()メソッド
これらの新しい"until"系メソッドは、.nextAll(), .prevAll(), .parents()と似た動作をします。
違いは、引数で受け取ったセレクタにマッチしたところで取得をストップするところです。
.add(String,Element)
.add()メソッドにコンテキストを指定できるようになりました。
このことは、(例えばajaxリクエストで返ってきた)追加の要素を他の要素セットに加えて、一緒に操作したいときに便利です。
.closest(filter, DOMElement)
closest()メソッドが第2引数としてDOM要素を受け取り、コンテキストを指定できるようになりました。
コンテキストを指定することでより速く実行することができます。
この方法は、内部的にclosest()を利用しているlive()メソッドにおいても同様です。
Utilities
jQuery.isEmptyObject()
このメソッドは引数のオブジェクトが何もプロパティを持っていなければtrueを返します。
また、jQuery.isEmptyObject()に渡せるのはオブジェクトだけです。
というのも、jQueryは渡された引数に対して(訳注:for (var name in obj) 文で)イテレーションできるかどうかを試み、それ以外はチェックしていないからです。
jQuery.isPlainObject()
jQuery.isPlainObject()は引数のオブジェクトが、オブジェクトリテラルであればtrueを返し、それ以外のオブジェクト(訳注:コンストラクタ関数で生成したオブジェクトや、組み込みオブジェクト)やプリミティブ値であればfalseを返します。
jQuery.contains()
jQuery.contains()は2つの引数がどちらもDOM要素で、かつ、第2引数の要素が第1引数の要素に内包されている場合にtrueを返します。
jQuery.noop
jQuery.noopは空の関数です。関数が必要とされる箇所で利用されています。
(訳注:空の関数が必要な箇所で毎回関数生成するのではなく、jQuery.noopを参照することでパフォーマンスアップしているのでしょう。)
jQuery.unique()
jQuery1.4ではjQuery.unique()メソッド(jQuery内部で、jQuery要素の集合を生成するのに使用されています)は、結果を常にdocumentでの出現順に並び替えて返します。
このことはつまり、あらゆるjQuery関数により返される結果セットはdocumentでの出現順に並んで返されるということになります。
その他もろもろ
jQuery.browserがレンダリングエンジン指向になりました(jQuery.browser)
例えば、jQuery.browser.webkit で「Webkit」かどうかをテストできるようになりました。
(訳注:Safariかどうかではなく、Webkitかどうかのテストができる。)
アプレットのサポートが改善されました
Javaアプレットに対してイベントやデータの束縛を試みなくなりました。(例外を投げる)
arguments.calleeを利用しなくなりました
Cajaに準拠するためと、ECMAScript第5版の仕様にて非推奨の候補となったため、jQuery coreでの全てのarguments.callee使用可所を削除しました。
YUI Minではなく、Closure Compilerを使用するようになりました
内部的なコード再編
1.4で実施した大きなアピール点の一つは、より読みやすく、理解しやすいコードベースを築いた点です。
我々が成し遂げたコードベースの大きな改編は内部的ですが、スタイルガイドラインを確立しはじめました。
実施した大きな変更点のいくつか
- 以前の'core.js'ファイルは‘attribute.js’, ‘css.js’, ‘data.js’, ‘manipulation.js’, ‘traversing.js’, ‘queue.js’に分割されました。
- readyイベントはcore.jsに移動されました。(jQuery自身にとって基礎となる部分なので)
- coreコードの大部分は新しいjQuery Core Style Guidelinesに則っています。
- cssとattributesに対するロジックは分割され、相互に入り組むことはなくなりました。
テスト
jQuery1.4では207個のバグが修正されました(1.3をリリースした時は97個でした)。
加えて、テストの範囲も、1.3.2では1504件のテストケースでしたが、1.4では3060件のテストを実施しました。
jQueryのテストスイートはメジャーなブラウザで100%合格しています。
(Safari 3.2, Safari 4, Firefox 2, Firefox 3, Firefox 3.5, IE 6, IE 7, IE 8, Opera 10.10, Chrome)
後方互換性のない変更点
jQuery1.4ではバージョンアップによる大きなコンフリクトが極力起きないように試みました。
パブリックな関数については型を変えないように調整しました。
ですが念の為、下記の一覧を読んであなたのアプリケーションに問題がないかどうか注意してください。
- .add() は単純にDOMの選択結果を結合していましたが、1.4では、結果を(訳注:重複がないように)マージし、documentにおける出現順にソートするようになりました。
- .clone(true) はDOMに付随しているイベントだけ一緒に複製していましたが、1.4ではイベントとデータも複製するようになりました。(訳注:ここでいうデータとはjQuery.data(key, value)によりDOM要素に対して保存したデータのこと)
- jQuery.data(elem)はidを返していましたが、DOM要素のオブジェクトキャッシュを返すようになりました。
- jQuery()(引数なし)はjQuery(document)と同じ解釈をされなくなりました。
- option要素またはcheckbox要素に対する.val("...")の動作が曖昧ではなくなりました。
(name属性またはvalue属性を見て選択していましたが、常にvalue属性のみを見て選択するようになりました。) - jQuery.browser.versionがレンダリングエンジンのバージョンを返すようになりました。
- 受け取るJSONの書式に対して厳格になり、適格でないJSONを受け取った場合に例外を投げるようになりました。
JavaScriptのリテラル文字列としては妥当であるが、JSON書式としては適格でないJSONを評価する必要がある場合は、文字列としてリクエストし、その後eval()を用いて評価することができます。 - リクエストパラメータの文字列化方法がデフォルトでPHPやRailsの動作と同じになりました。
(訳注:nameが同じパラメータを[]によって配列としてリクエストできることでしょうか。)
ただし、jQuery.ajaxSettings.traditional = true; とすれば以前と同じ動作で文字列化できます。
(訳注:以後全てのAJAXリクエストに対して有効。)
または、jQuery.ajaxメソッドにて、traditional: true オプションを渡すことで、リクエストごとに動作を選択できます。 - jQuery内部で利用されていたjQuery.className が削除されました。
- jQuery.extend(true, ...)が、プレーンなオブジェクトでないものや配列に対して動作しなくなりました。
- Ajaxリクエストにおいて、dataTypeオプションを指定せずに実行し、またレスポンスがtext/javascriptだった場合、そのコードは実行されます。以前のバージョンではdataTypeの指定は必須でした。
- AjaxリクエストのifModifiedオプションを設定するとETagが考慮されるようになりました。
また、過去のバージョンと衝突を起こす可能性のある変更点の全てを後方互換できるようにするプラグインも用意しました。
1.4を導入し、もし問題が起こった場合はそのプラグインをぜひダウンロードし、使用してみてください。
プラグインの使い方は下記のスクリプトを読み込むだけ
<script src="http://code.jquery.com/jquery.js"></script> <script src="http://code.jquery.com/jquery.compat-1.3.js"/></script>