Javascriptを使ってWEBサービスでページ内のエレメントをコントロールする時に、data属性(data-***)をうまく使う事で色々と柔軟な処理を行う事が可能になります。
先日記事で書いた、静的HTMLページにテンプレートHTMLを読み込んでjavascriptを実行させるようにするプログラムで、属性コントロールをもっと柔軟にするように改良する事ができたので、今回紹介したいと思います。
HTML静的ページで部分的な別ファイルのソースを読み込む方法
前回記事で紹介しているajax.jsの中のscriptタグの属性を「src」「class」「id」の3種類しか適応できていなかったので、その他の属性が入った場合は引き継がれない仕様でした。
そもそも、SCRIPTタグにそれ以外の属性が入るとは考えていなかったんですが、APIなどのWEBサービスでは、data-attributeはかなり使われている様なので、対応しておこうと思いました。
属性を全て取得するには
javascriptには、便利な機能が備わっており、「エレメント.attributes」で簡単にセットされている属性一覧が配列で取得されます。
その配列内にそれぞれ、「name」と「value」というobject形式で、格納されている仕様です。
var contents = document.getElementById("contents");
var attrs = contents.attributes;
for(var i=0; i<attrs.length; i++){
console.log(attrs[i].name +"="+ attrs[i].value);
}
上記で、取得されている事が確認できます。
ajax.jsを書き直す
とりあえず、前回記事の"ajax.js"を修正しておきました。
;$$MYNT_AJAX = (function(){
/**
* Ajax
* $$MYNT_AJAX | $$ajax({
* url:"", // "http://***"
* method:"POST", // POST or GET
* async:true, // true or false
* data:{}, // Object
* query:{}, // Object
* querys:[] // Array
* });
*/
var $$ajax = function(options){
if(!options){return}
var ajax = new $$ajax;
var httpoj = $$ajax.prototype.createHttpRequest();
if(!httpoj){return;}
// open メソッド;
var option = ajax.setOption(options);
// 実行
httpoj.open( option.method , option.url , option.async );
// type
httpoj.setRequestHeader('Content-Type', option.type);
// onload-check
httpoj.onreadystatechange = function(){
//readyState値は4で受信完了;
if (this.readyState==4){
//コールバック
option.onSuccess(this.responseText);
}
};
//query整形
var data = ajax.setQuery(option);
//send メソッド
if(data.length){
httpoj.send(data.join("&"));
}
else{
httpoj.send();
}
};
$$ajax.prototype.dataOption = {
url:"",
query:{}, // same-key Nothing
querys:[], // same-key OK
data:{}, // ETC-data event受渡用
async:"true", // [trye:非同期 false:同期]
method:"POST", // [POST / GET]
type:"application/x-www-form-urlencoded", // [text/javascript]...
onSuccess:function(res){},
onError:function(res){}
};
$$ajax.prototype.option = {};
$$ajax.prototype.createHttpRequest = function(){
//Win ie用
if(window.ActiveXObject){
//MSXML2以降用;
try{return new ActiveXObject("Msxml2.XMLHTTP")}
catch(e){
//旧MSXML用;
try{return new ActiveXObject("Microsoft.XMLHTTP")}
catch(e2){return null}
}
}
//Win ie以外のXMLHttpRequestオブジェクト実装ブラウザ用;
else if(window.XMLHttpRequest){return new XMLHttpRequest()}
else{return null}
};
$$ajax.prototype.setOption = function(options){
var option = {};
for(var i in this.dataOption){
if(typeof options[i] != "undefined"){
option[i] = options[i];
}
else{
option[i] = this.dataOption[i];
}
}
return option;
};
$$ajax.prototype.setQuery = function(option){
var data = [];
if(typeof option.query != "undefined"){
for(var i in option.query){
data.push(i+"="+encodeURIComponent(option.query[i]));
}
}
if(typeof option.querys != "undefined"){
for(var i=0;i<option.querys.length;i++){
if(typeof option.querys[i] == "Array"){
data.push(option.querys[i][0]+"="+encodeURIComponent(option.querys[i][1]));
}
else{
var sp = option.querys[i].split("=");
data.push(sp[0]+"="+encodeURIComponent(sp[1]));
}
}
}
return data;
};
$$ajax.prototype.loadHTML = function(filePath , selector){
$$ajax({
url:filePath,
method:"GET",
data:{
selector:selector
},
async:true,
onSuccess:function(res){
var target = document.querySelector(this.data.selector);
if(!target){return;}
// resをelementに変換
var div1 = document.createElement("div");
var div2 = document.createElement("div");
div1.innerHTML = res;
// script抜き出し
var scripts = div1.getElementsByTagName("script");
while(scripts.length){
div2.appendChild(scripts[0]);
}
// script以外
var num = 0;
for(var i=0; i<div1.childNodes.length; i++){
if(div1.childNodes[num].nodeType !== 1){
num++;
continue;
}
target.appendChild(div1.childNodes[num]);
}
// script
$$ajax.prototype.orderScript(div2 , target);
}
});
};
$$ajax.prototype.orderScript = function(tags , target){
if(!tags.childNodes.length){return;}
var div = document.createElement("div");
var newScript = document.createElement("script");
if(tags.childNodes[0].innerHTML){newScript.innerHTML = tags.childNodes[0].innerHTML;}
var attrs = tags.childNodes[0].attributes;
for(var i=0; i<attrs.length; i++){
newScript.setAttribute(attrs[i].name , attrs[i].value);
}
if(typeof tags.childNodes[0].src === "undefined"){
target.appendChild(newScript);
div.appendChild(tags.childNodes[0]);
$$ajax.prototype.orderScript(tags , target);
}
else{
newScript.onload = function(){
$$ajax.prototype.orderScript(tags , target);
};
target.appendChild(newScript);
div.appendChild(tags.childNodes[0]);
}
};
return $$ajax;
})();
簡単解説
146行目あたりの属性判定していた箇所を、for文に書き換えています。
古いscriptタグ(tags.childNodes[0])を新しく作成したscriptタグ(newScript)に属性を全て適用しています。
さほど難しく無いコードなので、読んで理解してみてください。
※わかりにくければ、質問ください。
こうして、静的ページの読み込みajaxが非常に制度が向上しました。
この便利さに気がついているエンジニアの方、めちゃくちゃ高速なWEBサービスが作れることに気がつきましたか?
0 件のコメント:
コメントを投稿