Micro-Templatingはすごく優秀! raw html, include, wrapを可能 <- include, wrapは、外した
var me = arguments.callee; が非推奨!! -> なしバージョンにカスタム
lodashのテンプレートエンジンと同じ変数記法が使える
ただし、挿入する変数にタグが含まれる場合は、記述を、<%=raw 変数名 %>にする。
記法の変更が簡単! -> laraabelのBladeテンプレートと統一するかを検討中
wrapは、_$(hoge).wrap($tpl,$data)でwrapできるようにしている。
includeは、別の関数を作成しているが、将来カスタムして組み込む?(SEO対策やロードバーツのJavaScript実行は?)
重要:TODO)セキュリティについての配慮:javascriptセキュリティ
Micro-Templatingのアップデート: Rick Stahl's blog
let $test = '<div id="<%=id%>" class="<%=clss%>"><%=body%></div>';
let $data = {
id: "reingo",
clss: "d-inline-block red text-white p-2 rounded",
body: "hogeee!"
}
document.querySelector('#micro').innerHTML = $_tpl($test, $data);
// ---- 重要 -------
// ---- 挿入する変数にタグが含まれる場合は、記述を、<%=raw 変数名 %>にする。
let thumimg = '<img src="' + $option.pdfpath + $thum + '" class="img-fluid" data-file="' + $thum + '">';
<%=raw thumimg %>
(function(){
let $test = '<div id="hogfe" class="hogera">hoge--</div>';
let $data2 = {
id: "reingo",
clss: "d-inline-block red text-white p-2 rounded",
body: "hogeee!"
}
document.querySelector('#micro2').innerHTML = $_tpl($test, $data2);
}());
let $test3 = '<div id="<%=id%>" class="<%=clss%>"><%=raw self%></div>';
let $data3 = {
id: "reingo",
clss: "d-inline-block red text-white p-2 rounded",
}
_$('#micro3').wrap($test3, $data3);
let $test4 = '<div class="black text-white my-3 p-2 rounded"><%=raw self%></div>';
_$('#micro4').wrap($test4);
var str = 'abcdefghij';
// dより前の文字が欲しい
var cut1 = str.substr(0, str.indexOf('d'));
console.log(cut1);
// 結果
abc
// dより後の文字が欲しい
var cut2 = str.substr(str.indexOf('d') + 1);
console.log(cut2);
// 結果
fghij
indexOf(特定文字) 文字の位置を返す(0スタート:ないときは -1)
substr(開始位置, 終了位置)で切り出し
substr(数字)で数字から終了位置まで切り出し
とにかく軽い:jQueryのジョン・グレグ氏作
ほんの少しコードが増えるけど:Micro-Templating改良版
//こんだけーーーーー!!!
// Simple JavaScript Templating
// John Resig - https://johnresig.com/ - MIT Licensed
(function(){
var cache = {};
this.tmpl = function tmpl(str, data){
var fn = !/\W/.test(str) ?
cache[str] = cache[str] ||
tmpl(document.getElementById(str).innerHTML) :
new Function("obj",
"var p=[],print=function(){p.push.apply(p,arguments);};" +
"with(obj){p.push('" +
str
.replace(/[\r\t\n]/g, " ")
.split("<%").join("\t")
.replace(/((^|%>)[^\t]*)'/g, "$1\r")
.replace(/\t=(.*?)%>/g, "',$1,'")
.split("\t").join("');")
.split("%>").join("p.push('")
.split("\r").join("\\'")
+ "');}return p.join('');");
return data ? fn( data ) : fn;
};
})();
--------------------------------------------
var _tmplCache = {}
this.parseTemplate = function(str, data) {
var err = "";
try {
var func = _tmplCache[str];
if (!func) {
var strFunc =
"var p=[],print=function(){p.push.apply(p,arguments);};" +
"with(obj){p.push('" +
str.replace(/[\r\t\n]/g, " ")
.replace(/'(?=[^#]*#>)/g, "\t")
.split("'").join("\\'")
.split("\t").join("'")
.replace(/<#=(.+?)#>/g, "',$1,'")
.split("<#").join("');")
.split("#>").join("p.push('")
+ "');}return p.join('');";
func = new Function("obj", strFunc);
_tmplCache[str] = func;
}
return func(data);
} catch (e) { err = e.message; }
return "< # ERROR: " + err.htmlEncode() + " # >";
}
------------------------------------------------------------------------
function $_tpl(id, data) {
// var me = arguments.callee;
//arguments.calleeの使用は非推奨:廃止になるので、関数名で置き換えた
var me = $_tpl;
if (!me.cache[id]) me.cache[id] = (function () {
var name = id, string = /^[\w\-]+$/.test(id) ? me.get(id): (name = '$_tpl(string)', id); // no warnings
var line = 1, $body = (
"try { " +
(me.variable ? "var " + me.variable + " = this.stash;" : "with (this.stash) { ") +
"this.ret += '" +
string.
replace(/<%/g, '\x11').replace(/%>/g, '\x13'). // if you want other tag, just edit this line
replace(/'(?![^\x11\x13]+?\x13)/g, '\\x27').
replace(/^\s*|\s*$/g, '').
replace(/\n|\r\n/g, function () { return "';\nthis.line = " + (++line) + "; this.ret += '\\n" }).
replace(/\x11=raw(.+?)\x13/g, "' + ($1) + '").
replace(/\x11=(.+?)\x13/g, "' + this.escapeHTML($1) + '").
replace(/\x11(.+?)\x13/g, "'; $1; this.ret += '") +
"'; " + (me.variable ? "" : "}") + "return this.ret;" +
"} catch (e) { throw 'templateError: ' + e + ' (on " + name + "' + ' line ' + this.line + ')'; } " +
"//# sourceURL=" + name + "\n" // source map
).replace(/this\.ret \+= '';/g, '');
var func = new Function($body);
var map = { '&' : '&', '<' : '<', '>' : '>', '\x22' : '"', '\x27' : ''' };
var escapeHTML = function (string) { return (''+string).replace(/[&<>\'\"]/g, function (_) { return map[_] }) };
return function (stash) { return func.call(me.context = { escapeHTML: escapeHTML, line: 1, ret : '', stash: stash }) };
})();
return data ? me.cache[id](data) : me.cache[id];
}
$_tpl.cache = {};
$_tpl.get = function (id) { return document.getElementById(id).innerHTML };
window.$_tpl = $_tpl;
<script type="text/html" id="item_tmpl">
<div id="<%=id%>" class="<%=(i % 2 == 1 ? " even" : "")%>">
<div class="grid_1 alpha right">
<img class="righted" src="<%=profile_image_url%>"/>
</div>
<div class="grid_6 omega contents">
<p><b><a href="/<%=from_user%>"><%=from_user%></a>:</b> <%=text%></p>
</div>
</div>
</script>
var results = document.getElementById("results");
results.innerHTML = tmpl("item_tmpl", dataObject);
<script type="text/html" id="user_tmpl">
<% for ( var i = 0; i < users.length; i++ ) { %>
<li><a href="<%=users[i].url%>"><%=users[i].name%></a></li>
<% } %>
</script>
問題点あり・・・。
// 読み込みたい箇所にDOM
<div id="○○" data-parts="パーツファイルのパス" data-call="△△△(読み込み後に実行するjavascript)"></div>
// 読み込み後に実行するjavascriptを「nJa_.func.△△△」で関数として登録。
nJa_.func.△△△ = function() {
$('#navact').navACT();
$('#main').codeESCAPE();
$('#spo1').guideNinja({
guide_footer_btn: '<div style="" class="fa-sm footer-btn white line-text rounded p-1"><i class="fas nja-open-door line-text mr-1"></i>ログアウト</div>',
guide_footer_msg: 'ここにメッセージ',
});
};
// 以上で、読み込みが行われ、javascriptも実行される。
// **** 課題 *****
// タブ化したファイル読み込みで、javascript実行がスムースに行われない。
// キャッシュクリアの再読み込みが必要になるケースが多い。
絶対パス・相対パス・ルート相対パス、全部で動作するように
リンク仕様/ハッシュタグ仕様
.load()で読み込まれた要素には適用されない。
/*
$('#navact').navACT({
debug: false,
type: 'link',
active: 'active',
txt_mute: 'text-muted',
txt_act: 'text-dark',
done: null,
error: null,
});
*/
.load()のコールバック関数で読み込ませる。関数を指定した配列に登録。属性に関数名を指定してload時に呼び出しする。
/*
javascriptでincludeする場合
<div id="header" data-parts="header.html" data-call="navact"></div>
nJa_.func.navact = function() {
$('#navact').navACT(); // ←←←← これがナビactive自動化用関数の実行
};
//オプション・ハッシュタグ仕様
$('#navact').navACT({
type: 'hash',
active: 'active',
txt_mute: 'text-muted',//非アクティブリンクテキストカラークラス
txt_act: 'text-dark',//アクティブリンクテキストカラークラス
});
*/
/*
// For PC
$('#psc').swipNAV({
parents: '.nav',
class_back: '.navback',
class_go: '.navgo',
back_btn : '<div class="navback"><div class="w24"><div class="maru bg-kagero btn-back"><div class="navback"><div class="w24"><div class="maru bg-kagero btn-back">></div></div></div>'</div></div></div>',
go_btn : '<div class="navgo"><div class="w24"><div class="maru bg-kagero btn-go"></div></div></div>',
done: null,
error: null,
});
.swip-nav { position: relative; z-index: 2;
max-height: 3.75rem; overflow-y: hidden;
}
.swip-nav .nav { display: -ms-flexbox; display: flex;
-ms-flex-wrap: nowrap; flex-wrap: nowrap;
overflow-x: auto; overflow-y: hidden;
white-space: nowrap;
}
*/
flex要素内の子要素の配置は、.flex-center .flex-middleでOK!
/*
Sortable.create($('#sortbox')[0], {
animation: 150,
ghostClass: 'rgba-blue-slight',
}
);
//オプション
draggable: ".item",
handle: ".my-handle",
ghostClass: "sortable-ghost", // Class name for the drop placeholder
direction: "horizontal", //vertical
onStart: function (/**Event*/ evt) {
evt.oldIndex; // element index within parent
},
onEnd: function (/**Event*/ evt) {
var itemEl = evt.item; // dragged HTMLElement
evt.to; // target list
evt.from; // previous list
evt.oldIndex; // element's old index within old parent
evt.newIndex; // element's new index within new parent
evt.oldDraggableIndex; // element's old index within old parent, only counting draggable elements
evt.newDraggableIndex; // element's new index within new parent, only counting draggable elements
evt.clone; // the clone element
evt.pullMode; // when item is in another sortable: `"clone"` if cloning, `true` if moving
},
*/
jquery ui resizable の代替
その1:CSSのresizeプロパティとobserverを使用
resizeプロパティ:ie,saffarでサポート外
/*
//css
#resizeable{ overflow: auto; resize: both;}
//javascript:ResizeObserve
const resizeObserver = new ResizeObserver(entries => {
for (const entry of entries) { ... }
});
const target = document.querySelector('div');
// target の監視を開始する
resizeObserver.observe(target);
// target の監視を終了する
resizeObserver.unobserve(target);
//ResizeObserverEntry
const resizeObserver = new ResizeObserver(entries => {
for (const entry of entries) {
// 変更を検知した要素
console.log(entry.target);
// 検知した変更の矩形
const rect = entry.contentRect;
console.log(rect.top, rect.left);
console.log(rect.width, rect.height);
}
});
// 監視を追加する
resizeObserver.observe(document.querySelector('#foo'));
resizeObserver.observe(document.querySelector('#bar'));
resizeObserver.observe(document.querySelector('#baz'));
/ 監視を終了する
resizeObserver.disconnect();
*/
その2:javascriptで実現