Нашел в закромах свой старый JavaScript шаблонизатор, почитал отзывы в прошлой статье и решил кое-то переделать, изменений не так много, но они вполне существенны, добавил поддержку функций и методов в шаблонах…
В прошлой версии я просто полез сюда иукрал позаимствовал код для своих нужд, так как не хотел использовать полностью библиотеку из-за этой мелочи. Почитал коментарии к прошлой статье, просмотрел ссылки и добавил одно маленькое но весомое изменение, в данном варианте возможно вставлять в шаблон методы или функции для обработки вставляемого контента… мелочь а приятно
меньше слов, небольшой пример все прояснит:
в итоге у нас получается такой результат:
В прошлой версии я просто полез сюда и
меньше слов, небольшой пример все прояснит:
<html>
<head>
<script>
// собственно сам шаблонизатор
function Template( template )
{
var _template = template.toString();
// паттерн вырезающий нужные ключи
var _pattern = /#\{(.*?)\}/g;
// паттерн проверки на использование функций
var _funcPattern = /(\w+)\((.*)\)/;
// паттерн проверки на использование методов
var _methodPattern = /(\w+)\.(\w+)\((.*)?\)/;
this.evaluate = function(object)
{
if( !( object instanceof Array ) )
{
object = new Array( object );
}
var result = [];
for( var q = 0; q < object.length; q++ )
{
var tmpTemplate = _template;
result.push( tmpTemplate.replace(_pattern, function(match, key)
{
if( undefined !== object[q][key] )
{
return object[q][key];
}
else
{
if( key.indexOf('.') && ( matches = key.match(_methodPattern) ) )
{
key = matches[1];
func = matches[2];
params = matches[3].split(',');
if( undefined !== object[q][key] )
{
return object[q][key][func].apply(object[q][key], params);
}
}
if( key.indexOf('(') && ( matches = key.match(_funcPattern) ) )
{
func = matches[1];
params = matches[2].split(',');
var value = null;
for(var w = 0; w < params.length; w++)
{
if( undefined !== object[q][params[w]] )
{
key = params[w];
params[w] = object[q][params[w]];
break;
}
}
if( undefined !== object[q][key] )
{
return window[func].apply(window, params);
}
}
}
return '';
}) );
}
return result.join("\n");
}
};
// функция для обработки данных,
// обрезает длинные коментарии, и вставляет "..." в конце
function cut(text, count)
{
if( text.length < count )
{
return text;
}
return text.substr(0, count) + ' ...'
}
</script>
</head>
<body>
<div id="result">
</div>
<script>
var table = "<table>#{content}</table>";
// шаблон строк с данными
// #{email.replace(@,[dog])} тут применяем стандартный метод строки, просто заменяем @ на [dog]
// #{cut(comment,20)} тут мы применяем описанную выше функцию для обрезки длинных коментариев
var row = "<tr><td>#{name}</td><td>#{email.replace(@,[dog])}</td><td>#{salary}</td><td>#{cut(comment,20)}</td></tr>";
// принимаемые данные
var data = [
{name:'John', email:'john@mail.com', salary:1000, comment:'some text'},
{name:'Tina', email:'tina@mail.com', salary:1300, comment:'some other text'},
{name:'Megan', email:'megan@mail.com', salary:800, comment:'some comment'},
{name:'Richi', email:'richi@mail.com', salary:500, comment:'blah blah blah'},
{name:'Max', email:'max@mail.com', salary:2000, comment:'UFO is goes here'},
{name:'Leonard', email:'leonard@mail.com', salary:1250, comment:'i saw UFO to'},
{name:'Kenny', email:'kenny@mail.com', salary:970, comment:'some wery long long long text, it should be cutted'},
{name:'Martha', email:'martha@mail.com', salary:670, comment:'she is driver'},
{name:'Arnold', email:'arnold@mail.com', salary:550, comment:'works very bad'},
{name:'Michael', email:'michael@mail.com', salary:430, comment:'qweqweqwe'}
];
// манипуляции с двумя шаблонами (почему два? просто для наглядности работы)
var content = new Template(table);
var rowTemplater = new Template(row);
var rowsResult = rowTemplater.evaluate(data);
var result = content.evaluate( {content:rowsResult} );
// вставляем результат в нужное место
document.getElementById('result').innerHTML = result;
</script>
</body>
</html>
* This source code was highlighted with Source Code Highlighter.
в итоге у нас получается такой результат:
<table>
<tr>
<td>John</td>
<td>john[dog]mail.com</td>
<td>1000</td>
<td>some text</td>
</tr>
<tr>
<td>Tina</td>
<td>tina[dog]mail.com</td>
<td>1300</td>
<td>some other text</td>
</tr>
<tr>
<td>Megan</td>
<td>megan[dog]mail.com</td>
<td>800</td>
<td>some comment</td>
</tr>
<tr>
<td>Richi</td>
<td>richi[dog]mail.com</td>
<td>500</td>
<td>blah blah blah</td>
</tr>
<tr>
<td>Max</td>
<td>max[dog]mail.com</td>
<td>2000</td>
<td>UFO is goes here</td>
</tr>
<tr>
<td>Leonard</td>
<td>leonard[dog]mail.com</td>
<td>1250</td>
<td>i saw UFO to</td>
</tr>
<tr>
<td>Kenny</td>
<td>kenny[dog]mail.com</td>
<td>970</td>
<td>some wery long long ...</td>
</tr>
<tr>
<td>Martha</td>
<td>martha[dog]mail.com</td>
<td>670</td>
<td>she is driver</td>
</tr>
<tr>
<td>Arnold</td>
<td>arnold[dog]mail.com</td>
<td>550</td>
<td>works very bad</td>
</tr>
<tr>
<td>Michael</td>
<td>michael[dog]mail.com</td>
<td>430</td>
<td>qweqweqwe</td>
</tr>
</table>
Заранее отвечу на некоторые вопросы, которые, мне кажется, будут первыми:
Q. почему не сделать функцию вместо обьекта, почему такие дурацкие скобки, почему такой дурацкий метод evaluate?
A. так как задумка не моя, я ее выдрал из библиотеки prototype я попытался оставить все as is, в как можно большей степени, если вам это кажется недостатками, это легко меняется
Q. как со скоростью?
A. со скоростью все в порядке, этот пример выполняется за 2мс (ибо хорошая машина и маленький пример) в общем тупить сильно не будет, регулярки не сложные, выполняться будут вполне сносно
Q. нафига оно надо, у меня вот jQuery/prototype/mootools/yui/etc... и там этот функционал уже есть
A. рад за вас, я не всегда использую jQuery/prototype/mootools/yui/etc... и когда мне понадобился этот функционал я не использовал библиотек никаких, а только ради этого брать библиотеку не собирался
Q. а я вот на сервере обрабатываю шаблоны и передаю уже готовый html, при условии что твои шаблоны передаются тоже (они не создаются на клиенте и должны как-то туда передаться), то загрузка канала будет такая-же, тогда в чем смысл этого всего?
A. смысл в том что сейчас все браузеры поддерживают persistent storage где и можно хранить шаблоны и при переходах на другие страницы грузить только данные
Вот в принципе и все, это далеко не первая моя статья, можете пинать
зы: убедительная просьба, кого не интересует код, не надо писать об ошибках, я не пишу для лингвистов, я выложил код
upd тестирвано в фф3.5 опера 10.10 ие8
так как вызовы эмулируются, есть парочка НО:
1. строки не нужно обрамлять ковычками
2. не желательно ставить пробел до/после аргментов
* This source code was highlighted with Source Code Highlighter.