MVP の Omar AL Zabir は、いつも奇妙で実用的な小さなことを考え出すのが好きで、それらは非常に参考に値します。最近、彼は JavaScript、CSS、HTML を動的にロードするための ensure という小さなツールを作成しました。これは IE、Firefox、Opera、Safari でサポートされています。それでは、sure が JavaScript と CSS を動的にロードする方法を見てみましょう。
ensure の内部実装を紹介する前に、まずその関数を見てみましょう:
ensure({
html: "popup.html",
javascript: "ポップアップ .js",
css: "popup.css"
}, function() {
Popup.show("hello world");
}
);
ここコード スニペットでは、ensure はまず、popup.html、popup.js、popup.css の 3 つのファイルがロードされていることを確認します。ロードされていない場合は、それらのファイルが動的にロードされます。また彼らを。 3 つのファイルがすべてロードされたことを確認したら、後続の匿名関数を呼び出します。つまり、Popup.show("hello world"); を実行します。
次に、JavaScript と CSS を動的にロードする方法を見てみましょう。
JavaScript の読み込み
確実に、JavaScript の読み込みは Safari と Safari 以外の 2 つの状況で実行されます。
IE、Firefox、Opera での JavaScript のロード
これら 3 つのブラウザで JavaScript をロードするには、script 要素を作成し、ロードする URL を src に指定し、最後に script 要素を追加するだけです。 head 要素についてはそれだけです。この作業は HttpLibrary.createScriptTag() で行われます。ただし、JavaScript をロードするだけでなく、スクリプト要素の onload イベントまたは onreadystatechange イベントによってロードがいつ完了したかを知る必要もあります。
Safari に JavaScript をロードする
Safari 2 は onload または onreadystatechange をサポートしていないため、XHR を介して URL を手動で読み取り、このコードを手動で評価することしかできません。これにより制限が生じます — JavaScript ファイルのみこのドメインはロードできます。 eval の作業は HttpLibrary.globalEval() を通じて確実に行われます。グローバル コンテキストで JavaScript コードを eval にできるようにするには、script 要素を作成し、eval にする JavaScript をその中に配置し、最後に script 要素を head 要素に追加する方法を引き続き使用するようにしてください。
注意深い人は、HttpLibrary.globalEval() が直接 window.eval や eval.call ではなくなぜこのように設計されているのかを尋ねる必要があります。これは、window.eval も eval.call も、IE6 でスクリプト タグを使用して JavaScript コードをロードするのと同じ効果を達成できないためです。これら 2 つのメソッドの eval は、IE6 では依然としてグローバル コンテキストで実行されません。検索すると、関連するディスカッションがいくつか見つかります。たとえば、jQuery はこのタスクを実行するために window.execScript() を使用していました。しかし最終的には、script 要素を追加することが最良のクロスブラウザー ソリューションであることが全員にわかり、現在では jQuery と ensure がこの方法で実装されています。
CSS の読み込み
JavaScript の読み込みと比較すると、CSS の読み込みははるかに簡単で、方法も同様で、link 要素を head 要素に直接追加するだけです。これはまさにloadCSS()が行うことです。
実際には、ensure は実行前に CSS がロードされることを保証しません。これは、ブラウザがページの読み込み後に自動的に CSS を適用できるためであると考えられます。そのため、CSS の読み込み順序は関係ないと考えています。ただし、CSS の読み込み速度が遅すぎると、実際には表示効果に影響を及ぼします。 。
IE6 での CSS の読み込み
今回特に注意が必要なのは Safari ではなく IE6 です。 IE6 が head 要素にリンク要素を追加するときは、ウィンドウのコンテキストで行う必要があるため、リンクを追加する関数は呼び出しを通じてコンテキストを切り替えます。
概要
実際、JavaScript と CSS を動的にロードすることは、ほとんどの場合、対応するサブ要素を head 要素に追加するだけで済みます。これは Safari2 と IE6 だけです。ブラウザには特別な注意が必要です。
/*
スクリプト: Ensure.js
Ensure ライブラリ
JavaScript、HTML、CSS をロードできる便利な関数「ensure」を提供する小さな JavaScript ライブラリ-demand を指定してコードを実行します。関連する
JavaScript および HTML スニペットが、それらを使用するコード
を実行する前にブラウザ DOM に既に存在することを確認します。
このスクリプトの最新バージョンをダウンロードするには、次のリンクを使用します:
バージョン:
1.0 - 初期リリース
互換性:
FireFox - バージョン 2 および 3
Internet Explorer - バージョン 6 および 7
Opera - 9 (おそらく8 も)
Safari - バージョン 2 および 3
Konqueror - バージョン 3 以降
依存関係:
クレジット:
- グローバル Javascript 実行 -
著者:
Omar AL Zabir - http://www.php.cn/
ライセンス:
>Copyright (C) 2008 Omar AL Zabir - http:/ /www.php.cn/
>
> 本ソフトウェアおよび関連する
> ドキュメント ファイル (以下「ソフトウェア」) のコピーを入手するすべての者に、
> に無料で許可が与えられます。
>ソフトウェアを制限なく取り扱うこと。
> ソフトウェアのコピーを使用、コピー、変更、結合、
> 発行、配布、サブライセンス、および/または販売する権利を含みますが、これらに限定されません。
> ;また、ソフトウェアが提供される人にそれを許可するには、
>次の条件に従います。
>
> 上記の著作権表示およびこの許可通知は、ソフトウェアのすべてのコピーまたは実質部分に
> 含まれるものとします。
>
> ソフトウェアは、明示的か黙示的かを問わず、いかなる種類の保証も行わず、「現状のまま」提供されます。
> 商品性、特定の純正品への適合性の保証を含みますが、これに限定されませんポーズと非侵害。
> いかなる場合も、著者または著作権所有者は、契約行為、不法行為またはその他の行為であるかどうかにかかわらず、
> から生じるいかなる請求、
> 損害、その他の責任に対しても責任を負わないものとします。ソフトウェア
>の、またはそれに関連した、またはソフトウェアの使用またはその他の取引。
*/
(function(){
window.ensure = function( data, callback,scope )
{
if( typeof jQuery == "未定義" && typeof Sys == "未定義" && typeof Prototype == "未定義" )
return warning("jQuery、Microsoft ASP.NET AJAX、またはプロトタイプ ライブラリが見つかりません。確実に動作するには、いずれかが存在する必要があります"); >
// false の場合、関連コンポーネントをロードする必要があるテスト基準があります。ただし、true の場合、
// コンポーネントをロードする必要はありません。
if( typeof data.test != "unknown" )
{
var test = function() { return data.test };
if( typeof data.test == "string" )
{
test = function( )
{
// そのような Javascript 変数がなく、ID を持つそのような DOM 要素も存在しない場合、
// 存在する場合、テストは成功します。
return !(eval( " typeof " data.test ) == "未定義"
&& document.getElementById(data.test) == null);
}
}
else if( typeof data.test == "function " )
{
test = data.test;
}
// これでテストの準備ができたので、テストを実行して、いずれかのフィールドで null、未定義、または false が返されるかどうかを確認します。
// シナリオ。存在する場合は、指定された javascript/html/css をロードします。
if( test() === false || typeof test() == "未定義" || test() == null )
new ensureExecutor (データ、コールバック、スコープ);
// テストは成功しました!コールバック
else
callback(); を起動するだけです。
}
else
{
// テストが指定されていません。したがって、必要な javascript/html/css をロードし、コールバックを実行します
新しいensureExecutor(データ、コールバック、スコープ);
}
}
// ensureExecutor は、保証の仕事を行うメインクラスです。
window.ensureExecutor = function(data, callback,scope)
{
this.data = this.clone(data);
this.callback = (typeofscope == "未定義" || null == スコープ ? callback : this.delegate(callback,scope));
this.loadStack = [];
if( data.js && data.js.constructor != Array ) this.data.js = [data.js];
if( data.html && data.html.constructor != Array ) this.data.html = [data.html];
if( data.css && data.css.constructor != Array ) this.data.css = [data.css];
if( typeof data.js == "未定義" ) this.data.js = [];
if( typeof data.html == "未定義" ) this.data.html = [];
if( typeof data.css == "未定義" ) this.data.css = [];
this.init();
this.load();
}
window.ensureExecutor.prototype = {
init : function()
{
// フレームワーク固有のライブラリを使用して Javascript を取得します
if( typeof jQuery != "未定義" )
{
this.getJS = HttpLibrary.loadJavascript_jQuery;
this.httpGet = HttpLibrary.httpGet_jQuery;
}
else if( typeof Prototype != "未定義" )
{
this.getJS = HttpLibrary.loadJavascript_Prototype;
this.httpGet = HttpLibrary.httpGet_Prototype;
}
else if( typeof Sys != "未定義" )
{
this.getJS = HttpLibrary.loadJavascript_MSAJAX;
this.httpGet = HttpLibrary.httpGet_MSAJAX;
}
else
{
throw "jQuery、プロトタイプ、または MS AJAX フレームワークが見つかりません";
}
},
getJS : function(data)
{
// Javascript を取得して実行する抽象関数
},
httpGet : function(url, callback) )
{
// HTTP GET 呼び出しを行う抽象関数
},
load : function()
{
this.loadJavascripts( this.delegate( function() {
this.loadCSS( this.delegate( function() {
this.loadHtml( this.delegate( function() {
this.callback()
} ) )
} ) )
} ) );
},
loadJavascripts : function(complete)
{
var scriptsToLoad = this.data.js.length;
if( 0 === scriptsToLoad ) return complete();
this.forEach(this.data.js, function(href)
{
if( HttpLibrary.isUrlLoaded(href) || this.isTagLoaded('script', 'src', href ) )
{
scriptsToLoad --;
}
else
{
this.getJS({
url: href,
success: this.delegate(function) (コンテンツ)
{
scriptsToLoad --;
HttpLibrary.registerUrl(href);
エラー: this.delegate(function(msg)
{
scriptsToLoad --;
if(this.data.error == "関数") this.data.error(href, msg);
}
});
// すべての外部スクリプトがダウンロードされるまで待ちます
this.until({
test: function() { return scriptsToLoad === 0; },
lay: 50,
コールバック: this.delegate(function()
{
complete();
})
});
},
loadCSS : function(complete)
{
if( 0 === this.data.css.length ) return complete();
var head = HttpLibrary.getHead();
this.forEach(this.data.css, function(href)
{
if( HttpLibrary.isUrlLoaded(href) || this.isTagLoaded('link', 'href', href) )
{
// 何もしない
}
else
{
var self = this;
try
{
(function(href, head)
{
var link = document.createElement('link');
link.setAttribute("href", href); link.setAttribute("type", "text/css");
head.appendChild(link)
HttpLibrary.registerUrl(href); , head]);
}
catch(e)
{
if(typeof self.data.error == "関数") self.data.error(href, e.message);
}
}
});
complete();
},
loadHtml : function(complete)
{
var htmlToDownload = this.data.html.length;
if( 0 === htmlToDownload ) return complete();
this.forEach(this.data.html, function(href)
{
if( HttpLibrary.isUrlLoaded(href) )
{
htmlToDownload --;
}
else
{
this.httpGet({
url: href,
success: this.delegate(function(content)
{
htmlToDownload --;
HttpLibrary.registerUrl(href);
varparent = (this.data.parent || document.body.appendChild(document.createElement("p"))); = "文字列" ) 親 = document.getElementById(parent);
parent.innerHTML = content;
}),
エラー: this.delegate(function(msg)
{
htmlToDownload --;
if(this.data.error == "関数") this.data.error(href, msg)
})
}
} );
// すべての外部スクリプトがダウンロードされるまで待ちます
this.until({
テスト: function() { return htmlToDownload === 0; },
遅延: 50,
コールバック: this.delegate(function()
{
complete();
})
});
},
clone : function(obj)
{
var cloned = {};
for( var p in obj )
{
var x = obj[p];
if( typeof x == "object" )
{
if( x.constructor == Array )
{
var a = [];
for( var i = 0; i クローン[p] = a;
}
else
{
cloned[p] = this.clone(x);
}
}
else
cloned[p] = x;
}
クローンを返します。
},
forEach : function(arr, callback)
{
var self = this;
for( var i = 0; i
},
デリゲート : function( func, obj )
{
var context = obj ||これ;
return function() { func.apply(context, argument); }
},
まで : function(o /* o = { test: function(){...}, late:100, callback: function(){...} } */)
{
if( o.test() === true ) o.callback();
else window.setTimeout( this.delegate( function() { this.until(o); } ), o.lay || 50);
},
isTagLoaded : function(tagName, attName, value)
{
// 一時的なタグを作成して、最終的にブラウザが必要なエンコードを行った後に属性に与える値を確認します
//
var tag = document.createElement(tagName);
タグ[attName] = 値;
var tagFound = false;
var tags = document.getElementsByTagName(tagName);
this.forEach(tags, function(t)
{
if( tag[attName] === t[attName] ) { tagFound = true; return false }
});
戻りタグが見つかりました;
}
}
var userAgent = navigator.userAgent.toLowerCase();
// HttpLibrary は、HTTP GET、DOM へのスクリプトの挿入、ロードされた URL の追跡などの一般的な操作
// を実行するためのクロスブラウザ、クロスフレームワークライブラリです。
// 実装を提供します。 jQuery、MSAJAX、プロトタイプなどのさまざまなフレームワーク用
var HttpLibrary = {
browser : {
version: (userAgent.match( /. (?:rv|it|ra|ie)[/: ]( [d.] )/ ) || [])[1],
safari: /webkit/.test( userAgent ),
opera: /opera/.test( userAgent ),
msie: / msie/.test( userAgent ) && !/opera/.test( userAgent ),
mozilla: /mozilla/.test( userAgent ) && !/(compatibility|webkit)/.test( userAgent )
},
loadedUrls : {},
isUrlLoaded : function(url)
{
return HttpLibrary.loadedUrls[url] === true;
},
unregisterUrl : function(url)
{
HttpLibrary.loadedUrls[url] = false;
},
registerUrl : function(url)
{
HttpLibrary.loadedUrls[url] = true;
},
createScriptTag : function(url, success, error)
{
var scriptTag = document.createElement("script");
scriptTag.setAttribute("type", "text/javascript");
scriptTag.setAttribute("src", url);
scriptTag.onload = scriptTag.onreadystatechange = function()
{
if ( (!this.readyState ||
this.readyState == "ロード済み" || this.readyState == "complete ") ) {
成功();
}
};
scriptTag.onerror = function()
{
error(data.url " 読み込みに失敗しました");
};
var head = HttpLibrary.getHead();
head.appendChild(scriptTag);
},
getHead : function()
{
return document.getElementsByTagName("head")[0] || document.documentElement
},
globalEval : function(data)
{
var script = document.createElement("script");
script.type = "text/javascript";
if ( HttpLibrary.browser.msie )
script.text = data;
else
script.appendChild( document.createTextNode( data ) );
var head = HttpLibrary.getHead();
head.appendChild( script );
//head.removeChild( script );
},
loadJavascript_jQuery : function(data)
{
if( HttpLibrary.browser.safari )
{
return jQuery.ajax({
type: "GET" 、
url: data.url,
data: null,
success: function(content)
{
HttpLibrary.globalEval(content);
data.success();
},
エラー: function(xml, status, e)
{
if( xml && xml.responseText )
data.error(xml.responseText);
else
data.error(url 'n' e.message);
},
dataType: "html"
});
}
else
{
HttpLibrary.createScriptTag(data.url, data.success, data.error);
}
},
loadJavascript_MSAJAX : function(data)
{
if( HttpLibrary.browser.safari )
{
var params =
{
URL: data.url,
成功: function(content)
{
HttpLibrary.globalEval(content);
data.success(コンテンツ);
}、
エラー: data.error
};
HttpLibrary.httpGet_MSAJAX(params);
}
else
{
HttpLibrary.createScriptTag(data.url, data.success, data.error);
}
},
loadJavascript_Prototype : function(data)
{
if( HttpLibrary.browser.safari )
{
var params =
{
URL: data.url,
成功: function(content)
{
HttpLibrary.globalEval(content);
data.success(コンテンツ);
}、
エラー: data.error
};
HttpLibrary.httpGet_Prototype(params);
}
else
{
HttpLibrary.createScriptTag(data.url, data.success, data.error);
}
},
httpGet_jQuery : function(data)
{
return jQuery.ajax({
type: "GET",
url: data.url,
data: null,
success: data.success,
error: function(xml, status, e)
{
if( xml && xml.responseText )
data.error( xml.responseText);
else
data.error("url 'n' e.message);
dataType: "html"
});
},
httpGet_MSAJAX : function(data)
{
var _wRequest = new Sys.Net.WebRequest();
_wRequest.set_url(data.url);
_wRequest.set_httpVerb("GET");
_wRequest.add_completed(function (result)
{
var errorMsg = "ロードに失敗しました:" data.url;
if (result.get_timedOut()) {
errorMsg = "時間指定out";
}
if (result.get_aborted()) {
errorMsg = "中止";
}
if (result.get_responseAvailable()) data.success( result.get_responseData() );
else data.error(errorMsg );
var executor = new Sys.Net.XMLHttpExecutor();
_wRequest.set_executor(エグゼキュータ);
executor.executeRequest();
},
httpGet_Prototype : function(data)
{
new Ajax.Request(data.url, {
method: 'get',
evalJS: false, // Make確かに、プロトタイプはスクリプトを自動的に実行しません
onSuccess: function(transport, json)
{
data.success(transport.responseText || "");
},
onFailure : data。エラー
});
}
};
})();