jQueryを使うと、ajax 経由で取得した XML ドキュメントのような、ブラウザ(window,document)と切り離された対象でも簡単に操作することができます。例えば、リモートから取得したRSSであれば、以下のようなコードで各項目(item)のタイトル(title)やリンク先(link)、日時(dc:date)を取得することができます*1。
$.ajax( { url : "http://www.example.com/rss.xml", dataType : "xml", type : "get", success : function( xml ){ var s = ""; $( xml ).find( "item" ).each( function(){ s += $(this).find( "title" ).text() + " <" + $(this).find( "link" ).text() + ">(" + $(this).find( "dc\\:date" ).text() + ")\n"; } ); alert( s ); } } );
このように、jQueryを使うと直接DOMを操作するのに比べてXMLでも楽に扱えるので、ブラウザから切り離された環境である WSH / JScript でも jQuery を使ってみたいと思うのは当然でもあります。というわけで、jQuery を WSH 環境で使えるのか試してみました。
結論から言うと、簡単な準備をしてくことで、少し制限はあるものの十分実用的に WSH 環境でも jQuery を利用することができました。
以下、jQuery をWSHで使うためのコードです。
// グローバル名前空間に window や document などを準備する (function(){ if( typeof( document ) == "undefined" ){ document = new ActiveXObject( "htmlfile" ); document.write("<html></html>"); // これ重要 } if( typeof( window ) == "undefined" ) window = document.parentWindow; if( typeof( alert ) == "undefined" ) //alert = window.alert; alert = function(s){ return window.alert( s )}; if( typeof( confirm ) == "undefined" ) confirm = function(s){ return window.confirm(s) }; if( typeof( location ) == "undefined" ) location = window.location; if( typeof( navigator ) == "undefined" ) navigator = window.navigator; _util = {}; _util.cat = function( filename ){ var fso = new ActiveXObject( "Scripting.FileSystemObject" ); var f = fso.OpenTextFile( filename, 1, false ); return f.ReadAll(); } })(); // jQuery の読み込み eval( _util.cat( "jquery-1.3.2.min.js" ) ); // 簡単な jQuery オブジェクトの操作例 WScript.Echo( $( "<div>" ).attr( "a", "fo" ).get(0).outerHTML ); // もちろん alert も使える。 alert( $( "<div>" ).attr( "a", "fo" ).get(0).outerHTML ); // jQuery.ajax を使ってリモートからXMLを読み込み $.ajax( { url : "http://www.example.com/rss.xml", dataType : "xml", type : "get", async : false, // これ重要 success : function( xml ){ var s = ""; $( xml ).find( "item" ).each( function(){ s += $(this).find( "title" ).text() + " <" + $(this).find( "link" ).text() + "> (" + $(this).find( "dc\\:date" ).text() + ")\n"; } ); alert( s ); } } );
まず、グローバルに document を用意するため、new ActiveXObject( "htmlfile" ) でHTMLDocumentを生成します。これは new ActiveXObject( "Internet Explorer.Application" ) とした場合と異なり、アウトプロセスでIEのインスタンスを生成しないため、非常に軽量です。これで、グローバルな document が用意できたのですが、このままだと document.body や document.documentElement が null なままですので、とりあえずダミーで body を用意してやるために document.write( "" ); としてやります。ここまでで document の準備が完了です。
つぎに window ですが、これは document.parentWindow がそのまま利用可能なので、グローバル名前空間に放り出してやります。
通常の JavaScript であればグローバル名前空間は window に支配されているので、例えば alert を呼び出せばそれは暗黙のうちに window.alert の呼び出しとなるわけですが、WSH ではグローバルな名前空間は window とは無関係ですので、window のメンバのうち必要そうなものをグローバルな名前空間に export してやる必要があります。navigator のような単純なプロパティであれば同名のグローバル変数を用意してそこに代入するだけでよいのですが、alert のようなメソッドをexportする場合、alert = window.alert; のような代入では、なぜか呼び出しに失敗するため*2、ラッパ関数を用意してやる必要があります。
window、document をはじめとする一連のグローバルなオブジェクト類の準備ができればあとはjQueryを読み込み、いつもどおりのプログラミングができます。
ただし、本当の window を持っていないため setInterval や setTimeout がうまく扱えません。そのため、jQuery.ajax を呼び出す場合には、async:false が必須となりますので、注意が必要です。(2009-09-30追記: seInterval を誤魔化して async:true で動きました。)もちろん、dataType:"jsonp" などはうまく動きません。
以上、IE8環境でのテストですので他のバージョンのIEでは異なる動作となるかも知れませんが、jQueryが動けばWSHでのちょっとしたツールの作成もとても簡単で楽しいものになります!
追記:激しくガイシュツというのを umq さん、ZIGOROu さんに教えてもらった(´・ω・`)ショボーン
*1:":"を含む要素名のセレクタの書き方は、Wassrでmonmonさんに教えてもらいました。ありがとうございます。
*2:typeof(alert) == "object"になっている