それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

JavaScriptを動的に書き出す

EfficientJavaScript によると
http://www.hyuki.com/yukiwiki/wiki.cgi?EfficientJavaScript

evalは重いので非推奨らしい。

さて、ではどうするか

JavaScriptタグを動的に書き出す方針でやってみた。

動かない例1 InnerHTMLで追加してみる(InnerText)も同じ

script = document.createElement("script");
script.type="text/javascript";
script.innerHTML = "alert('')";

動かない例2 Textノードで追加してみる

script = document.createElement("script");
script.type="text/javascript";
script.appendChild(document.createTextNode("alert()"));

ScriptタグにInnerHTMLを書き出すのは無理だった。

つまり、DOMで参照してるから無理って事のようだ。DOMでアクセスしているからどちらの例も同じ結果でも納得できる。

Scriptタグ内にソースを書出す方法


動きそうな例 をみつけた
http://d.hatena.ne.jp/brazil/20061105/1162722198

のコメントによると

script = document.createElement("script");
script.type="text/javascript";
script.text = "alert()";

だと動くらしい。ただ、これは未検証。

textプロパティの参照は微妙かも

さがしてみした結果 (IE6で検証)
http://d.hatena.ne.jp/shogo4405/20061107/1162886968
によると

script = document.createElement("script");
script.type="text/javascript";
script.text = "alert()";

textプロパティーは動作するらしい。でもバッドノウハウ

defer属性が正攻法のようです。

id:shogo4405さんの別のエントリ
http://d.hatena.ne.jp/shogo4405/20070306/1173160753

deferなるAttributeが存在するらしい。試してみた

div = document.createElement("div");
div.innerHTML = "&nbsp;<script defer='defer'>alert('');</script>";
document.body.appendChild(div);

おおお動いた。

defer属性すごいよ。script src="xxx.js"だとタイミング制御が難しいが。
これならタイミングを制御できる。(*)動作検証したソース無くしたので、サンプルソースは適当。Scriptタグの直前にTextノードを書き出すのがミソ


しかしドコで使うか微妙。

2012-01-05 追記 async と defer

defer はDomContentLoadedのイベントで実行される。
async は onload の直前で実行される。

【レポート】script要素、asyncとdeferの効果 | 開発・SE | マイナビニュース

asyncはedvakfさんに教えてもらった。



WSHからIEを操作するときに使える

WSH(js)でYahooをスクレーピングするときに、CSSセレクタが使えると便利。

/**
* WSHでIEを制御して必要なデータを取り出す
*/
var url = "http://www.yahoo.co.jp"; 
var ie = WScript.CreateObject("InternetExplorer.Application");
ie.Navigate2( url );
ie.visible = true;
while( ie.ReadyState != 4 ){ WScript.Sleep(1); } 
var document = ie.Document;

//Prototype.jsなどライブラリを読み込む
//JScriptとIEのJavaScriptを連携させる
var fs = WScript.CreateObject("Scripting.FileSystemObject");
fs.OpenTextFile( "ext.js" );//Extライブラリを読み込んでみる
ext_src = fs.ReadAll();
div = document.createElement("div");
div.innerHTML = "&nbsp;<script defer='defer'>"+ext_src+"</script>";
document.body.appendChild(div);
div = document.createElement("div");
div.innerHTML = "&nbsp;<script defer='defer'>"
                +"var obj = Ext.query('#element div');"
                +"</script>";
document.body.appendChild(div);

//取り出した結果をJSDBでデータベースへ
//JSDBの使い方をまだ調べてない


こんな感じ?でも動作しない。ext.jsが大きすぎる?

XPATHつかえるからCSS Selectorライブラリって余り使わないよね。。。
やっぱりdeferの使いどころが難しい。

参考
http://youmos.com/news/css_selector_js

うまくいけば、Youtube動画を保存しながらMHTMLを作れるかなと思ったのだが。

ところでevalより軽いの?


作業が脱線したので動作速度は検証できてない 笑


どうなんだろう

まとめ

副産物が生まれた。WSHからIEのDocumentオブジェクトをどうさせる方法
EmEditorのマクロでHTMLプレビューしながら動的に連携出来るよね。
EmEditorのマクロがイベントドリブンすれば・・・)きっと萌ディタなら出来るぞ。

最速のma.laさんがやってた、動的ロードDEMOがローカルだけで出来るんじゃないかなと妄想してみた。

/**
* WSHでIE書き換えてAlertを出す。
*/
var url = "http://www.yahoo.co.jp"; 
var ie = WScript.CreateObject("InternetExplorer.Application");
ie.Navigate2( url );
ie.visible = true;
while( ie.ReadyState != 4 ){ WScript.Sleep(1); } 
var document = ie.Document;
var window = document.parentWindow;

with(window){
  //このスコープがIEとほぼ同じスコープになる
  alert("Hello form IE window");
}

コレをベースに

  1. IEのWindowを再利用するClass作って
  2. HTMLソースを書き換えるClass作る
  3. エディタのイベントでbodyを書き換える

でも、contentEditableを応用した方が楽だろう・・・

もしかして

FireBugのようなconsleもeval使わずに作れるかも。