[javascript] javascriptテンプレートエンジン(?)表示の繰り返し更新対応

どうも、懲りない僕です。JavaScriptでビュー書いてるんだから、動的にビュー動かしたいよね?だから、TemplateEngineRunnerは繰り返し実行できなきゃ意味ないよね?なんてわけで、対応しました。
それにしてもアレなサンプル……
http://s-ishigami.appspot.com/files/test.html

ソース

TemplateEngine = new function() {
var currentNode;
this.setCurrentNode = setCurrentNode;
this.propertyModelValue = function(object, propName) { return new PropertyModel(object, propName).getValue; };
this.writeText = function (value) { return new WriteText(value); };
this.writeHtml = function (value) { return new WriteHtml(value); };
this.setAttribute = function (name, value) { return new SetAttribute(name, value); };
this.loopWhile = function(condition, subController) { return new LoopFor(emptyFunction, condition, emptyFunction, subController); }
this.loopFor = function(init, condition, after, subController) { return new LoopFor(init, condition, after, subController); }
function emptyFunction() {}
function setCurrentNode(node) {
currentNode = node;
}
function functionOrValue(f) {
if (typeof f == 'function') {
return f();
}
return f;
}
function PropertyModel(object, propName) {
this.getValue = getValue;
function getValue() {
return object[propName];
}
}
function WriteText(value) {
this.execute = execute;
function execute() {
currentNode.text(functionOrValue(value));
}
}
function WriteHtml(value) {
this.value = value;
this.execute = execute;
function execute() {
currentNode.html(functionOrValue(value));
}
}
function SetAttribute(name, value) {
this.execute = execute;
function execute() {
currentNode.attr(name, functionOrValue(value));
}
}
function LoopFor(init, condition, after, subController) {
this.execute = execute;
function execute() {
init();
while (condition()) {
var clone = currentNode.clone(true);
clone.attr('id', null);
clone.addClass('GENERATED_NODE');
clone.addClass(currentNode.attr('id') + "_CLONE");
if (subController != null) {
var thisNode = currentNode;
TemplateEngineRunner.run(subController, clone);
setCurrentNode(thisNode);
}
clone.find('*').attr('id', null);
clone.insertBefore(currentNode);
after();
}
currentNode.addClass('ORIGINAL_NODE');
currentNode.hide();
}
}
}
TemplateEngineRunner = new function() {
this.run = run;
function run(controller, parentNode) {
clearGeneratedNodes(parentNode);
if (typeof parentNode == 'String') {
parentNode = $('#' + parentNode);
}
for (var key in controller) {
if (parentNode == null) {
TemplateEngine.setCurrentNode($('#' + key));
} else {
TemplateEngine.setCurrentNode(parentNode.find('#' + key));
}
controller[key].execute();
}
}
function clearGeneratedNodes(parentNode) {
if (parentNode == null) {
$('.GENERATED_NODE').remove();
$('.ORIGINAL_NODE').show();
} else {
if (typeof parentNode == 'String') {
parentNode = $('#' + parentNode);
}
parentNode.find('.GENERATED_NODE').remove();
parentNode.find('.ORIGINAL_NODE').show();
}
}
}
var myModel = {
name: 'テスト',
sex: 'male',
position: 0,
goNext: function() {
this.position += 1;
},
nameChange: function() {
this.name = this.name == "テスト" ? "太郎" : "テスト";
}
};
with (TemplateEngine) {
var yamanote = ['大崎', '品川', '田町', '浜松町', '新橋', '有楽町', '東京', '神田', '秋葉原', '御徒町', '上野', '鶯谷', '日暮里', '西日暮里', '田端', '駒込', '巣鴨', '大塚', '池袋', '目白', '高田馬場', '新大久保', '新宿', '代々木', '原宿', '渋谷', '恵比寿', '目黒', '五反田'];
var i = 0;
var controller = {
// オブジェクトのプロパティ出力(動的)
name: writeText(propertyModelValue(myModel, 'name')),
// 固定値出力
test: writeText('生麦生米生卵'),
// 動的値出力
now: writeText(function() {return new Date().toString();}),
// 固定HTML出力
testHtml: writeHtml('<span style="color: blue;">青</span>巻紙<span style="color: red;">赤</span>巻紙<span style="color: yellow;">黄</span>巻紙'),
// 属性変更
attr: setAttribute('style', 'font-size: x-large; color: blue;'),
// ループ(indexを外側の変数で定義しなければいけないことが課題)
'for': loopFor(
function() {i = 0},
function() {return i < 10},
function() {i++;},
{
counterFor: writeText(function() {return yamanote[(myModel.position + i) % yamanote.length];})
}
)
}
}
TemplateEngineRunner.run(controller);
<!DOCTYPE html>
<html lang="ja">
<head>
   <meta charset="utf-8">
   <title>Template Engine Test</title>
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<a href="javascript: myModel.goNext(); TemplateEngineRunner.run(controller)">次の駅へ</a>
<p>現在日時: <span id="now"></span></p>
<table border="1">
<col width="200">
<col width="200">
<tr>
<th bgcolor="silver">key</th>
<th bgcolor="silver">val</th>
</td>
<tr>
<th>氏名</th>
<td align="center"><a href="javascript: myModel.nameChange(); TemplateEngineRunner.run(controller)"><span id="name"></span></a></td>
</td>
<tr>
<th>得意技</th>
<td><span id="attr"><span id="test"></span></span></td>
</td>
<tr>
<th>得意技2</th>
<td><span id="testHtml"></span></td>
</td>
<tr id="for">
<th>次は</th>
<td id="counterFor"></td>
</tr>
</table>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">google.load("jquery", "1.4.2");</script>
<script type="text/javascript" src="templateEngine.js"></script>
<script type="text/javascript" src="test.js"></script>
</body>
</html>


propertyModelValueとか、とてもWicket風。Mayaaを目指したらWicketに似てきた。最初からWicket風につくるべきだったか?

コメントを残す