<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>jQuery и другое... &#187; javascript</title>
	<atom:link href="http://www.linkexchanger.su/category/javascript/feed" rel="self" type="application/rss+xml" />
	<link>http://www.linkexchanger.su</link>
	<description>css, html, php, javascript, jQuery, ajax ... - решения, примеры, рецепты</description>
	<lastBuildDate>Sun, 08 Jan 2012 13:25:49 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>jQuery Templates plugin: Template Tags</title>
		<link>http://www.linkexchanger.su/2010/644.html</link>
		<comments>http://www.linkexchanger.su/2010/644.html#comments</comments>
		<pubDate>Tue, 09 Nov 2010 12:22:25 +0000</pubDate>
		<dc:creator>Андрей</dc:creator>
				<category><![CDATA[jQuery]]></category>
		<category><![CDATA[jQuery документация]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jQuery Plugins]]></category>

		<guid isPermaLink="false">http://www.linkexchanger.su/?p=644</guid>
		<description><![CDATA[В прошлой статье я рассказал основы использования плагина jQuery Templates plugin и обещал описать возможности синтаксиса шаблонов, чем сегодня и займусь. В этой статье помимо описания инструкций шаблонов будет много примеров, а в конце есть ссылка на демонстрационную страницу с &#171;живыми&#187; примерами &#8211; там их можно посмотреть, поредактировать, поэкспериментировать, попробовать собственные примеры.
Синтаксис шаблонов довольно функционален. [...]]]></description>
			<content:encoded><![CDATA[<p>В <a href="/2010/619.html">прошлой статье</a> я рассказал основы использования плагина <strong>jQuery Templates plugin</strong> и обещал описать возможности синтаксиса шаблонов, чем сегодня и займусь. В этой статье помимо описания инструкций шаблонов будет много примеров, а <a href="#demoLinks">в конце</a> есть ссылка на демонстрационную страницу с &laquo;живыми&raquo; примерами &#8211; там их можно посмотреть, поредактировать, поэкспериментировать, попробовать собственные примеры.</p>
<p>Синтаксис шаблонов довольно функционален. В теле шаблона разработчик может обращаться к полям объекта, к полям полей объекта, вызывать методы объекта и его полей, обращаться к внешним объектам JavaScript и jQuery, просто писать JS-выражения. Кроме всего этого внутри шаблона можно итеративно выводить коллекции, организовать условный вывод, использовать вложенные шаблоны. Но давайте обо всём по порядку.</p>
<p><span id="more-644"></span></p>
<h2>Примеры в статье</h2>
<p>Все примеры я буду приводить ключевыми кусками, чтобы не загромождать материал повторяющимися частями кода. В примере будут присутствовать <strong>текст шаблона</strong>, <strong>JSON данных</strong>, при необходимости <strong>JSON опций</strong> (параметр <strong><em>options</em></strong><em> </em>метода <strong><em>.tmpl( ) </em></strong>) и <strong>результат</strong>. В общем случае полный код примера будет выглядеть так:</p>
<pre class="brush: xml;">
&lt;script type=&quot;text/x-jquery-tmpl&quot;&gt;
    &lt;li&gt; ЭТО ТЕКСТ ШАБЛОНА &lt;/li&gt;
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
var data = [
    // ЭТО МАССИВ ДАННЫХ
];
var options = {
    // ЭТО ОПЦИИ
};
$(function() {
    // ПРИМЕНЕНИЕ ШАБЛОНА И ВЫВОД РЕЗУЛЬТАТА:
    $('script[type=&quot;text/x-jquery-tmpl&quot;]').tmpl(data, options).appendTo($('.output').empty());
});
&lt;/script&gt;
&lt;ul class=&quot;output&quot;&gt;&lt;/ul&gt;
</pre>
<p>Так будет полностью выглядеть приведенный ниже <strong>пример 1.</strong>:</p>
<pre class="brush: xml;">
&lt;script type=&quot;text/x-jquery-tmpl&quot;&gt;
    &lt;li&gt;${Name} ({{html Desc}}); вычисления: ${p1 + p2 + 10}&lt;/li&gt;
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
var data = [
    { Name: &quot;obj1&quot;, Desc: &quot;&lt;em&gt;Object one&lt;/em&gt;&quot;, p1: 1, p2: 10 },
    { Name: &quot;&lt;em&gt;obj2&lt;/em&gt;&quot;, Desc: &quot;&lt;strong&gt;Object two&lt;/strong&gt;&quot;, p1: 3.3, p2: 5 }
];
var options = {
};
$(function() {
    $('script[type=&quot;text/x-jquery-tmpl&quot;]').tmpl(data, options).appendTo($('.output').empty());
});
&lt;/script&gt;
&lt;ul class=&quot;output&quot;&gt;&lt;/ul&gt;
</pre>
<h2>Вставка данных в шаблон ${}, {{= }}, {{html }}</h2>
<p>С помощью этих инструкции можно вставить в шаблон значение поля объекта данных, результат работы метода или результат вычисления некоторого js-выражения, внутри инструкции можно обращаться к глобальным объектам JS, а также к служебным объектам, созданным при обработке шаблона.</p>
<p>Прежде чем перейти к примерам, хочу немного акцентировать внимание на сходстве и разнице этих инструкций. Все три инструкции предназначены для вывода результата в эту точку шаблона. <strong>${<em>expression</em>}</strong> и <strong>{{= <em>expression</em>}}</strong> эквивалентны (первая инструкция &#8211; это сокращённая форма второй), результат вставляется в шаблон в виде текста, если в тексте встречаются символы разметки (&lt;  &gt;  &amp; и пр.), то они будут заменены на соответствующие спецсимволы (&amp;lt;  &amp;gt;  &amp;amp; и пр.). Для вставки же разметки с сохранением html-кода нужно использовать инструкцию <strong>{{html <em>expression</em>}}</strong>.</p>
<h3>Пример 1. Вывод данных с разметкой и без</h3>
<p>Шаблон:</p>
<pre class="brush: xml;">&lt;li&gt;${Name} ({{html Desc}}); вычисления: ${p1 + p2 + 10}&lt;/li&gt;</pre>
<p>Данные:</p>
<pre class="brush: jscript;">[
    { Name: &quot;obj1&quot;, Desc: &quot;&lt;em&gt;Object one&lt;/em&gt;&quot;, p1: 1, p2: 10 },
    { Name: &quot;&lt;em&gt;obj2&lt;/em&gt;&quot;, Desc: &quot;&lt;strong&gt;Object two&lt;/strong&gt;&quot;, p1: 3.3, p2: 5 }
]</pre>
<p>Результат:</p>
<pre class="brush: xml;">&lt;ul class=&quot;output&quot;&gt;
    &lt;li&gt;obj1 (&lt;em&gt;Object one&lt;/em&gt;); вычисления: 21&lt;/li&gt;
    &lt;li&gt;&amp;lt;em&amp;gt;obj2&amp;lt;/em&amp;gt; (&lt;strong&gt;Object two&lt;/strong&gt;); вычисления: 18.3&lt;/li&gt;
&lt;/ul&gt;</pre>
<h2>Доступ к объектам и внутренние параметры шаблона</h2>
<p>Как я уже упоминал, внутри выражения можно обращаться к глобальным объектам и функциям JS, при этом шаблонизатор сам пытается определить, является указанное имя ссылкой на глобальный объект или на часть переданных данных. И конечно же, локальные данные имеют более высокий приоритет, чем глобальные. Давайте определим в документе глобальные объект testObj и функцию testFunc и попробуем их использовать:</p>
<pre class="brush: jscript;">var testObj = {
    Value: 1
};

function testFunc(i) {
    return i % 2 == 1;
}
</pre>
<h3>Пример 2. Использование глобальных объектов</h3>
<p>Шаблон:</p>
<pre class="brush: xml;">&lt;li&gt;${Name}; testObj.Value = ${testObj.Value}; testFunc(${p}) =&gt; ${testFunc(p)}&lt;/li&gt;</pre>
<p>Данные:</p>
<pre class="brush: jscript;">[
    { Name: &quot;obj1&quot;, p: 3, testObj: { Value: 20 } },
    { Name: &quot;obj2&quot;, p: 13, testFunc: function(i) { return i + 7; } }
]</pre>
<p>Результат:</p>
<pre class="brush: xml;">&lt;ul class=&quot;output&quot;&gt;
    &lt;li&gt;obj1; testObj.Value = 20; testFunc(3) =&amp;gt; true&lt;/li&gt;
    &lt;li&gt;obj2; testObj.Value = 1; testFunc(13) =&amp;gt; 20&lt;/li&gt;
&lt;/ul&gt;</pre>
<p>Внутри шаблона есть ещё доступ  к специальным объектам &#8211; внутренним параметрам шаблона: <strong>$item</strong> и <strong>$data</strong>.</p>
<p><strong>$item</strong> &#8211; представляет доступ к обрабатываемой в данный момент единице данных для вставки в шаблон, внутри этого объекта собраны и параметры, переданные пользователем, и дополнительные параметры из аргумента <em><strong>options</strong></em> функции <em><strong>.tmpl( )</strong></em>. Доступ к параметрам из данных осуществляется через вложенный объект <strong>.</strong><strong>data</strong>, а к параметрам аргумента <em><strong>options</strong></em> &#8211; напрямую, т.е. если вызвать <em><strong>$(&#8216;#myTmpl&#8217;).tmpl({ p1: 1 }, { p2: 2 })</strong></em>, то в шаблоне получить доступ к ним можно так: <em><strong>$item.data.p1</strong></em> и <em><strong>$item.p2</strong></em>.</p>
<p><strong>$data</strong> &#8211; это сокращённая версия доступа к данным, по сути это просто синоним для <em><strong>$item.data</strong></em>, в свете этого доступ в шаблоне к p1 и p2 из вызова в абзаце выше может быть таким: <em><strong>$data.p1</strong></em> и <em><strong>$item.p2</strong></em>.</p>
<h3>Пример 3. Параметр options</h3>
<p>Шаблон:</p>
<pre class="brush: xml;">&lt;li&gt;${Name}; p * 100 = ${$item.Method($data.p)}&lt;/li&gt;</pre>
<p>Данные:</p>
<pre class="brush: jscript;">[
    { Name: &quot;obj1&quot;, p: 3.3 },
    { Name: &quot;obj2&quot;, p: 0.13 }
]</pre>
<p>Опции:</p>
<pre class="brush: jscript;">{ Method: function(i) { return i * 100; } }</pre>
<p>Результат:</p>
<pre class="brush: xml;">&lt;ul class=&quot;output&quot;&gt;
    &lt;li&gt;obj1; p * 100 = 330&lt;/li&gt;
    &lt;li&gt;obj2; p * 100 = 13&lt;/li&gt;
&lt;/ul&gt;</pre>
<h2>Условная разметка в шаблоне {{if }} {{else}} {{/if}}</h2>
<p>Внутри шаблона можно отслеживать некие условия и в зависимости от них выводить тот или иной кусок. Для достижения этих целей применяются следующие комбинации инструкций:</p>
<p><strong>{{if <em>expression</em>}} tmplPart {{/if}}</strong> &#8211; простой вывод части шаблона, только если выражение истинно,<br />
<strong>{{if <em>expression</em>}} tmplPart1 {{else}} tmplPart2 {{/if}}</strong> &#8211; вывод части 1 или 2 в зависимости от истинности выражения,<br />
<strong>{{if <em>expr1</em>}} tmplPart1 {{else <em>expr2</em>}} tmplPart2 {{else}} tmplPart3</strong><strong> {{/if}}</strong> &#8211; это уже построение цепочки последовательных проверок (if .. else if .. else if .. else ..), понятное дело, что последний else без выражения необязателен. Думаю, тут всё понятно, давайте посмотрим простенький пример:</p>
<h3>Пример 4. Условный вывод</h3>
<p>Шаблон:</p>
<pre class="brush: xml;">&lt;li&gt;
{{if (
    (typeof(useFirstLastName) != &quot;undefined&quot; ? useFirstLastName : $item.defaultUseFirstLastName) &amp;&amp;
    $data.FirstName &amp;&amp; $data.LastName)}} ${FirstName + &quot; &quot; + LastName}
{{else $data.FullName}} ${FullName}
{{else $data.Name}} ${Name}
{{else}} ${$item.NoName}
{{/if}}
&lt;/li&gt;</pre>
<p>Данные:</p>
<pre class="brush: jscript;">[
    { Name: &quot;obj1&quot;, FullName: &quot;Object 1&quot;, FirstName: &quot;Object&quot;, LastName: &quot;One&quot; },
    { FirstName: &quot;Object&quot;, LastName: &quot;Two&quot;, Name: &quot;obj2&quot;, useFirstLastName: true },
    { Title: &quot;object number 3&quot; }
]</pre>
<p>Опции:</p>
<pre class="brush: jscript;">{ NoName: &quot;[noname]&quot;, defaultUseFirstLastName: false }</pre>
<p>Результат:</p>
<pre class="brush: xml;">&lt;ul class=&quot;output&quot;&gt;
    &lt;li&gt;  Object 1  &lt;/li&gt;
    &lt;li&gt;  Object Two  &lt;/li&gt;
    &lt;li&gt;  [noname]  &lt;/li&gt;
&lt;/ul&gt;</pre>
<p>Поясню, что происходит в шаблоне. Под первым условием мы проверяем, нужно ли выводить имя объекта в виде конкатенации FirstName и LastName &#8211; при этом проверяется условие внутри объекта, если оно не определено, то условие в опциях, и требуется наличие обоих свойств. Обращаясь в условии к этим свойствам через параметр <em><strong>$data</strong></em>, гарантируем их наличие именно в переданных данных, а глобальные объекты при этом игнорируются. Во втором и третьем условиях проверяем последовательно свойства FullName и Name &#8211; выводим первое попавшееся, если нет ни одного из них, то выводим &laquo;заглушку&raquo; из опций.</p>
<h2>Итеративный обход с помощью {{each }}</h2>
<p>Думаю всем знакома функция jQuery <em><strong>.each(func)</strong></em> (а есть ещё и <em><strong>$.map(array, callback)</strong></em> ) и надеюсь многим знакома конструкция JS <em><strong>for (var key in obj)</strong></em> &#8211; эти выражения совершают итеративный обход элементов коллекции. В шаблонах тоже возможен вывод коллекций поэлементно и описывается он следующей инструкцией: <strong>{{each( <em>index</em>, <em>value </em>) <em>data</em>}} <em>tmplText </em>{{/each}}</strong>. <strong>index</strong> и <strong>value</strong> &#8211; это имена параметров (указываются без кавычек) для доступа соответственно к текущему индексу и значению в коллекции. Есть и сокращённая форма этой инструкции: <strong>{{each <em>data</em>}} <em>tmplText</em> {{/each}}</strong> &#8211; при этом в тексте шаблона к текущим индексу и значению можно обратиться по именам по умолчанию: <strong>$index</strong> и <strong>$value</strong>. Выражение <strong>data</strong> должно возвращать в результате массив или объект, объект будет обработан как словарь (коллекция пар имя-значение свойств объекта). Довольно слов, посмотрим на примере:</p>
<h3>Пример 5. Вывод массива</h3>
<p>Шаблон:</p>
<pre class="brush: xml;">&lt;li&gt;
    &lt;table border=&quot;1&quot; cellpadding=&quot;5&quot; cellspacing=&quot;0&quot;&gt;
        &lt;tr&gt;&lt;th align=&quot;left&quot;&gt;n&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;${Expr}&lt;/th&gt;&lt;/tr&gt;
        {{each NumCollection}}
        &lt;tr&gt;&lt;td&gt;${$index}&lt;/td&gt;&lt;td&gt;${$value}&lt;/td&gt;&lt;/tr&gt;
        {{/each}}
        &lt;tr&gt;&lt;td&gt;${$item.EtcName}&lt;/td&gt;&lt;td&gt;${$item.EtcVal}&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
&lt;/li&gt;</pre>
<p>Данные:</p>
<pre class="brush: jscript;">[
    { Expr: &quot;2^n&quot;, NumCollection: [ 1, 2, 4, 8, 16 ] },
    { Expr: &quot;2n-1&quot;, NumCollection: [ 1, 3, 5, 7, 9 ] },
]</pre>
<p>Опции:</p>
<pre class="brush: jscript;">{ EtcName: &quot;etc.&quot;, EtcVal: &quot;...&quot; }</pre>
<p>Результат:</p>
<pre class="brush: xml;">&lt;ul class=&quot;output&quot;&gt;
&lt;li&gt;
     &lt;table border=&quot;1&quot; cellpadding=&quot;5&quot; cellspacing=&quot;0&quot;&gt;
         &lt;tbody&gt;
             &lt;tr&gt;&lt;th align=&quot;left&quot;&gt;n&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;2^n&lt;/th&gt;&lt;/tr&gt;
             &lt;tr&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;
             &lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;
             &lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;/tr&gt;
             &lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;/tr&gt;
             &lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;16&lt;/td&gt;&lt;/tr&gt;
             &lt;tr&gt;&lt;td&gt;etc.&lt;/td&gt;&lt;td&gt;...&lt;/td&gt;&lt;/tr&gt;
         &lt;/tbody&gt;
    &lt;/table&gt;
&lt;/li&gt;&lt;li&gt;
     &lt;table border=&quot;1&quot; cellpadding=&quot;5&quot; cellspacing=&quot;0&quot;&gt;
         &lt;tbody&gt;
             &lt;tr&gt;&lt;th align=&quot;left&quot;&gt;n&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;2n-1&lt;/th&gt;&lt;/tr&gt;
             &lt;tr&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;
             &lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;/tr&gt;
             &lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;/tr&gt;
             &lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;7&lt;/td&gt;&lt;/tr&gt;
             &lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;9&lt;/td&gt;&lt;/tr&gt;
             &lt;tr&gt;&lt;td&gt;etc.&lt;/td&gt;&lt;td&gt;...&lt;/td&gt;&lt;/tr&gt;
        &lt;/tbody&gt;
    &lt;/table&gt;
&lt;/li&gt;
&lt;/ul&gt;</pre>
<h3>Пример 6. Вывод объекта-словаря</h3>
<p>Шаблон:</p>
<pre class="brush: xml;">&lt;li&gt;
JSON = { {{each(key, val) $data}}{{if $item.f}},{{/if}} &quot;${key}&quot;: &quot;${val}&quot;{{if $item.f=true}}{{/if}}{{/each}} }
&lt;/li&gt;</pre>
<p>Данные:</p>
<pre class="brush: jscript;">[
    { Name: &quot;obj1&quot;, FullName: &quot;Object 1&quot;, FirstName: &quot;Object&quot;, LastName: &quot;One&quot; },
    { FirstName: &quot;Object&quot;, LastName: &quot;Two&quot;, Name: &quot;obj2&quot; },
    { Title: &quot;object number 3&quot; }
]</pre>
<p>Опции:</p>
<pre class="brush: jscript;">{ f: false }</pre>
<p>Результат:</p>
<pre class="brush: xml;">&lt;ul class=&quot;output&quot;&gt;
    &lt;li&gt; JSON = {  &quot;Name&quot;: &quot;obj1&quot;, &quot;FullName&quot;: &quot;Object 1&quot;, &quot;FirstName&quot;: &quot;Object&quot;, &quot;LastName&quot;: &quot;One&quot; } &lt;/li&gt;
    &lt;li&gt; JSON = {  &quot;FirstName&quot;: &quot;Object&quot;, &quot;LastName&quot;: &quot;Two&quot;, &quot;Name&quot;: &quot;obj2&quot; } &lt;/li&gt;
    &lt;li&gt; JSON = {  &quot;Title&quot;: &quot;object number 3&quot; } &lt;/li&gt;
&lt;/ul&gt;</pre>
<h2>Вывод шаблона в шаблоне {{tmpl }}</h2>
<p>Внутри шаблона можно использовать другие шаблоны, которые могут быть получены извне (селектором, функцией) или в виде разметки сгенерированной на месте (например, когда сами данные определяют в каком виде их надо вставить в шаблон).</p>
<p>Полный вид инструкции: <strong>{{tmpl(<em>data</em>, <em>options</em>) <em>template</em>}}</strong>.</p>
<p><em><span style="color: #ff0000">(На момент написания статьи в оф.документации показана сигнатура инструкции <span style="text-decoration: underline">{{tmpl( [data], [options] ) template}} content {{/tmpl}}</span> &#8211; это <strong>ОШИБКА</strong>, у этой инструкции нет закрывающего тега <span style="text-decoration: underline">{{/tmpl}}</span> и, соответственно, никакого содержания <span style="text-decoration: underline">content</span>)</span></em></p>
<p>Параметры <strong>data</strong> и <strong>options</strong> &#8211; являются необязательными и имеют то же назначение, что и в функции <em><strong>.tmpl(data, options)</strong></em>, если параметры опущены, то в качестве данных используется текущий объект данных <em><strong>$data</strong></em>, а <em><strong>options</strong></em> &#8211; пустой объект.<br />
Параметр <strong>template</strong> может принимать следующие значения: HTML-разметка, HTML- или jQuery-объект, строка, которая является именем скомпилированного шаблона или скомпилированный шаблон, также можно просто передать строку-селектор для jQuery (это недокументированная возможность, но она фигурирует в примерах).</p>
<h3>Пример 7. Использование сгенерированного шаблона</h3>
<p>Шаблон:</p>
<pre class="brush: xml;">&lt;li&gt; {{tmpl $item.lt+tag+$item.gt+$item.tp+&quot;{content}&quot;+$item.lt+&quot;/&quot;+tag+$item.gt}} &lt;/li&gt;</pre>
<p>Данные:</p>
<pre class="brush: jscript;">[
    { tag: &quot;strong&quot;, content: &quot;&lt;em&gt;Hello&lt;/em&gt;, &quot; },
    { tag: &quot;em&quot;, content: &quot;World!&quot; }
]</pre>
<p>Опции:</p>
<pre class="brush: jscript;">{ lt: &quot;&lt;&quot;, gt: &quot;&gt;&quot;, tp: &quot;$&quot; }</pre>
<p>Результат:</p>
<pre class="brush: xml;">&lt;ul class=&quot;output&quot;&gt;
    &lt;li&gt; &lt;strong&gt;&amp;lt;em&amp;gt;Hello&amp;lt;/em&amp;gt;, &lt;/strong&gt; &lt;/li&gt;
    &lt;li&gt; &lt;em&gt;World!&lt;/em&gt; &lt;/li&gt;
&lt;/ul&gt;</pre>
<p>В шаблоне этого примера при генерировании вложенного шаблона используются строковые значение &laquo;&lt;&raquo;, &laquo;&gt;&raquo;, &laquo;$&raquo; в виде переменных, это сделано для того, чтобы они не воспринимались как разметка и инструкции внешним шаблоном.</p>
<h3>Пример 8. Использование шаблона внутри шаблона</h3>
<p>Шаблон:</p>
<pre class="brush: xml;">&lt;li&gt;${Name} {{if Items}}&lt;ul&gt;{{tmpl(Items) '#tmplSelector'}}&lt;/ul&gt;{{/if}}&lt;/li&gt;</pre>
<p>Тут строку &#8216;#tmplSelector&#8217; &#8211; следует заменить на корректный селектор (или функцию) получения текущего шаблона. Для моих &laquo;живых&raquo; примеров можно использовать такой шаблон:</p>
<pre class="brush: xml;">&lt;li&gt;${Name} {{if Items}}&lt;ul&gt;{{tmpl(Items) $('#example8 script[type=&quot;text/x-jquery-tmpl&quot;]')}}&lt;/ul&gt;{{/if}}&lt;/li&gt;</pre>
<p>, в нём будет применен начальный шаблон, или</p>
<pre class="brush: xml;">&lt;li&gt;${Name} {{if Items}}&lt;ul&gt;{{tmpl(Items) $('#example8')[0].DemoData.Tmpl}}&lt;/ul&gt;{{/if}}&lt;/li&gt;</pre>
<p>, в нём будет применён отредактированный шаблон &#8211; полностью &laquo;живой&raquo; пример.</p>
<p>Данные:</p>
<pre class="brush: jscript;">[
    { Name: &quot;obj1&quot;, Items: [ { Name: &quot;obj11&quot;, Items: [ { Name: &quot;obj111&quot; }, { Name: &quot;obj112&quot; } ] }, { Name: &quot;obj12&quot; } ] },
    { Name: &quot;obj2&quot; }
]</pre>
<p>Опции:</p>
<pre class="brush: jscript;">{ }</pre>
<p>Результат:</p>
<pre class="brush: xml;">&lt;ul class=&quot;output&quot;&gt;
    &lt;li&gt;obj1 &lt;ul&gt;
        &lt;li&gt;obj11 &lt;ul&gt;
            &lt;li&gt;obj111 &lt;/li&gt;
            &lt;li&gt;obj112 &lt;/li&gt;
        &lt;/ul&gt;&lt;/li&gt;
        &lt;li&gt;obj12 &lt;/li&gt;
    &lt;/ul&gt;&lt;/li&gt;
    &lt;li&gt;obj2 &lt;/li&gt;
&lt;/ul&gt;</pre>
<p>В этом примере определён рекурсивный шаблон.</p>
<h2>Шаблон в шаблоне с HTML-содержанием внутри {{wrap }}</h2>
<p><strong>{{wrap (<em>data</em>, <em>options</em>) <em>template</em>}} <em>HTMLcontent </em>{{/wrap}}</strong> &#8211; эта инструкция очень похожа на инструкцию <em><strong>{{tmpl }}</strong></em>, её параметры <em><strong>data</strong></em>, <em><strong>options</strong></em> и <em><strong>template</strong></em> имеют то же назначение. Отличие инструкции <em><strong>{{wrap }}</strong></em> от <em><strong>{{tmpl }}</strong></em> в том, что она может включать HTML-содержание и затем это содержание можно использовать в применяемом шаблоне.</p>
<p>В шаблоне, который передаётся параметром <em><strong>template</strong></em>, можно достать HTML-разметку, заключённую между <em><strong>{{wrap }}</strong></em> и <em><strong>{{/wrap}}</strong></em> с помощью метода <em><strong>$item.html(filter, onlyText)</strong></em>. Первым аргументом можно наложить фильтр в виде селектора jQuery на выбираемые из разметки элементы, а вторым аргументом можно указать, что нужно в результате получить только текст верхнего выбранного элемента.</p>
<h3>Пример 9. Использование {{wrap }}</h3>
<pre class="brush: xml;">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;style&gt;
table { border-collapse:collapse; width:380px; background-color:#f8f8f8; border:2px solid blue; margin:5px; } table td { border:1px solid blue; padding:3px; }
&lt;/style&gt;
  &lt;script src=&quot;http://code.jquery.com/jquery-latest.min.js&quot;&gt;&lt;/script&gt;
  &lt;script src=&quot;http://nje.github.com/jquery-tmpl/jquery.tmpl.js&quot;&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;script id=&quot;myTmpl&quot; type=&quot;text/x-jquery-tmpl&quot;&gt;
    The following wraps and reorders some HTML content:
    {{wrap &quot;#tableWrapper&quot;}}
        &lt;h3&gt;One&lt;/h3&gt;
        &lt;div&gt;
            First &lt;b&gt;content&lt;/b&gt;
        &lt;/div&gt;
        &lt;h3&gt;Two&lt;/h3&gt;
        &lt;div&gt;
            And &lt;em&gt;more&lt;/em&gt; &lt;b&gt;content&lt;/b&gt;...
        &lt;/div&gt;
    {{/wrap}}

    And this wraps different HTML content:
    {{wrap &quot;#tableWrapper&quot;}}
        &lt;div&gt;
            First &lt;b&gt;div&lt;/b&gt;
        &lt;/div&gt;
        &lt;div&gt;
            Second &lt;b&gt;div&lt;/b&gt;
        &lt;/div&gt;
        &lt;div&gt;
            Third &lt;b&gt;div&lt;/b&gt;
        &lt;/div&gt;
        &lt;h3&gt;first h3&lt;/h3&gt;
        &lt;h3&gt;second h3&lt;/h3&gt;
        &lt;h3&gt;third h3&lt;/h3&gt;
    {{/wrap}}
&lt;/script&gt;

&lt;script id=&quot;tableWrapper&quot; type=&quot;text/x-jquery-tmpl&quot;&gt;
    &lt;table&gt;&lt;tbody&gt;
        &lt;tr&gt;
            {{each $item.html(&quot;h3&quot;, true)}}
                &lt;td&gt;
                    ${$value}
                &lt;/td&gt;
            {{/each}}
        &lt;/tr&gt;
        &lt;tr&gt;
            {{each $item.html(&quot;div&quot;)}}
                &lt;td&gt;
                    {{html $value}}
                &lt;/td&gt;
            {{/each}}
        &lt;/tr&gt;
    &lt;/tbody&gt;&lt;/table&gt;
&lt;/script&gt;

&lt;div id=&quot;myWrappedView&quot;&gt;&lt;/div&gt;

&lt;script&gt;
$( &quot;#myTmpl&quot; ).tmpl()
    .appendTo( &quot;#myWrappedView&quot; );
&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Этот пример взят со страницы оф. документации по этой инструкции шаблона. В &laquo;живых&raquo; примерах приведена переработанная под их специфику версия.</p>
<h2>Комментарии в шаблонах {{! }}</h2>
<p>В шаблонах можно вставлять комментарии разработчика, которые не будут попадать в результат, делается это очень просто, а именно так:</p>
<pre class="brush: xml;">{{! это текст комментария}}</pre>
<h2><a name="demoLinks"></a>&laquo;Живые&raquo; примеры из статьи</h2>
<p>По этому адресу страница доступна online: <a href="http://zalab.net/projects/jquery/demo/tmpl/" target="_blank">http://zalab.net/projects/jquery/demo/tmpl/</a><br />
А по этой ссылке можно загрузить эту страничку в архиве: <a href="http://www.linkexchanger.su/wp-content/uploads/2010/11/jq.tmpl_.live_.examples.zip">jq.tmpl.live.examples.zip (33 KB)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.linkexchanger.su/2010/644.html/feed</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Официальные плагины jQuery: Templates plugin</title>
		<link>http://www.linkexchanger.su/2010/619.html</link>
		<comments>http://www.linkexchanger.su/2010/619.html#comments</comments>
		<pubDate>Mon, 01 Nov 2010 13:13:03 +0000</pubDate>
		<dc:creator>Андрей</dc:creator>
				<category><![CDATA[jQuery]]></category>
		<category><![CDATA[jQuery документация]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[jQuery Plugins]]></category>

		<guid isPermaLink="false">http://www.linkexchanger.su/?p=619</guid>
		<description><![CDATA[4 октября 2010 года была опубликована запись в официальном блоге jQuery об анонсе трёх плагинов jQuery, созданных при поддержке команды Microsoft. Эти плагины &#8211; плагин шаблонов (the jQuery Templates plugin), плагин привязки данных (the jQuery Data Link plugin) и плагин глобализации (the jQuery Globalization plugin) &#8211; получили статус “Официальные плагины проекта jQuery” (officially supported plugins [...]]]></description>
			<content:encoded><![CDATA[<p>4 октября 2010 года была опубликована <a href="http://blog.jquery.com/2010/10/04/new-official-jquery-plugins-provide-templating-data-linking-and-globalization/">запись в официальном блоге jQuery</a> об анонсе трёх плагинов jQuery, созданных при поддержке команды Microsoft. Эти плагины &#8211; <strong>плагин шаблонов (the jQuery Templates plugin)</strong>, <strong>плагин привязки данных (the jQuery Data Link plugin)</strong> и <strong>плагин глобализации (the jQuery Globalization plugin)</strong> &#8211; получили статус “Официальные плагины проекта jQuery” (officially supported plugins of the jQuery project).</p>
<p>Плагин шаблонов используется при необходимости вывести объект данных или массив объектов в разметку страницы. Плагин привязки данных нужен для связи объектов с элементами страницы и синхронного изменения значений. Плагин глобализации позволяет выводить такие данные, как числа, дата и время, сумма денег и т.п., на страницу в соответствии с форматом текущего языка.</p>
<p>Следует отметить, что команда Microsoft использовала свои немалые наработки в этих направлениях, как и команда проекта jQuery, и при хорошо сложившемся взаимодействии получились, на мой взгляд, отличные инструменты для разработчиков. В подтверждение моего мнения могу добавить, что разработчики jQuery анонсировали включение плагинов шаблонов и привязки данных в ядро библиотеки jQuery уже версии 1.5, а плагина глобализации &#8211; в соответствующую версию jQuery UI. Плагины пока ещё не получили статус релиза, но уже активно ведется написание документации на сайте <a href="http://api.jquery.com/">http://api.jquery.com</a>. К слову, команда Microsoft последовала традициям разработки jQuery и разместила материалы по разработке плагинов на github.com, где доступны описание и исходники плагинов.</p>
<p>В этой статье я расскажу немного о плагине шаблонов.<br />
<span id="more-619"></span></p>
<h2>jQuery Templates plugin</h2>
<p>Начнём с простенького примера:</p>
<pre class="brush: xml;">&lt;script id=&quot;movieTemplate&quot; type=&quot;text/x-jquery-tmpl&quot;&gt;
  &lt;li&gt;&lt;b&gt;${Name}&lt;/b&gt; (${ReleaseYear})&lt;/li&gt;
&lt;/script&gt;

&lt;script type=&quot;text/javascript&quot;&gt;
var movies = [
  { Name: &quot;The Red Violin&quot;, ReleaseYear: &quot;1998&quot; },
  { Name: &quot;Eyes Wide Shut&quot;, ReleaseYear: &quot;1999&quot; },
  { Name: &quot;The Inheritance&quot;, ReleaseYear: &quot;1976&quot; }
];

$( &quot;#movieTemplate&quot; ).tmpl( movies )
    .appendTo( &quot;#movieList&quot; );
&lt;/script&gt;

&lt;ul id=&quot;movieList&quot;&gt;&lt;/ul&gt;</pre>
<p>Итак, в примере разработчик страницы описал шаблон для вывода объектов в виде разметки (первый элемент <strong><em>script</em></strong>), потом получил откуда-то массив объектов <strong><em>movies </em></strong>и вызвал инструкцию сгенерировать нужную разметку по шаблону, взяв данные из предоставленного массива объектов, а результат добавить в конец списка <strong><em>#movieList</em></strong>.<br />
В результате работы плагина мы получим такую разметку:</p>
<pre class="brush: xml;">&lt;ul id=&quot;movieList&quot;&gt;
  &lt;li&gt;&lt;b&gt;The Red Violin&lt;/b&gt; (1998)&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Eyes Wide Shut&lt;/b&gt; (1999)&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;The Inheritance&lt;/b&gt; (1976)&lt;/li&gt;
&lt;/ul&gt;</pre>
<p>А теперь по сути вопроса.<br />
<strong> Что делает плагин?</strong><br />
Плагин получает на вход строку шаблона и множество объектов (или один объект), которые нужно вывести в строку (или разметку) с форматированием.<br />
<strong> Где это применяется?</strong><br />
В основном этот плагин полезен при динамическом выводе объектов JS на страницу, объекты могут быть получены самыми разными способами, например, при разчётах или по результатам каких-то действий пользователя и, конечно самый часто приводимый пример, в виде JSON в ответе сервера на AJAX запрос.</p>
<h3>Методы плагина</h3>
<p><strong><span style="text-decoration: underline">.tmpl( [ data ], [ options ] )</span></strong><br />
Получает содержимое первого выбранного элемента и использует его в качестве шаблона для форматированного вывода указанных данных.<br />
<strong><em> data </em></strong> &#8211; данные для вывода в шаблон (объект или массив объектов).<br />
<strong><em> options </em></strong> &#8211; опционально, определённое пользователем расширение в виде пар ключ-значение для объекта вывода в шаблон.<br />
<strong><span style="text-decoration: underline"> jQuery.tmpl(template, [ data ], [ options ])</span></strong><br />
Использует указанный шаблон для форматированного вывода указанных данных.<br />
<strong><em> template </em></strong> &#8211; шаблон для форматирования данных, может быть одного из следующих типов: строка с разметкой, HTML-элемент (в том числе и в jQuery-обёртке), строка, соответствующая имени ранее скомпилированного шаблона.<br />
<strong><em> data, options</em></strong> &#8211; имеют то же значение, что и выше<br />
<strong><span style="text-decoration: underline"> .tmplItem()</span></strong><br />
Возвращает для первого выбранного элемента структуру (объект) с результатами работы шаблонизатора. Возвращаемый методом объект обеспечивает доступ к:</p>
<ul>
<li> HTML-частям, из которых состоит шаблон</li>
<li> ассоциированной единице переданных данных</li>
<li> родительскому шаблону, если текущий шаблон является вложенным</li>
<li> текущему шаблону, использованному для вывода</li>
<li> определённому пользователем расширению (полям и методам), переданным в параметр options метода tmpl()</li>
</ul>
<p>Этот метод используется, напрмер, когда после проведенного форматирования данных требуется узнать, а какие же данные были использованы при формировании некоторого куска разметки, или для обновления куска разметки с использованием новых данных.<br />
<strong><span style="text-decoration: underline"> jQuery.tmplItem( element )</span></strong><br />
Аналогичен методу .tmplItem, только структура с результатами работы шаблонизатора ищется для элемента <strong><em>element </em></strong> (HTML-элемент, в том числе и в jQuery-обёртке).<br />
<strong><span style="text-decoration: underline"> .template( [ name ] )</span></strong><br />
Метод делает из содержимого первого выбранного элемента скомпилированную версию шаблона форматирования.<br />
<strong><em> name </em></strong> &#8211; необязательно имя шаблона, если имя указано, то потом можно использовать его для обращения к этому шаблону в методе <strong><em>jQuery.tmpl(name, data, options)</em></strong><br />
<strong><span style="text-decoration: underline"> jQuery.template( [ name, ] template )</span></strong><br />
Метод аналогичен описанному выше, только здесь шаблон передаётся в качестве параметра <strong><em>template </em></strong> &#8211; это может быть строка, строка с разметкой, HTML-элемент (в том числе и в jQuery-обёртке).</p>
<h3>Синтаксис шаблона</h3>
<p>Я вкратце приведу описание нескольких самых основных элементов шаблона, остальное надеюсь более подробно описать в следующей статье (если будет положительный отклик на эту статью)<br />
<strong><span style="text-decoration: underline"> ${fieldNameOrExpression} и {{= fieldNameOrExpression}}</span></strong><br />
Позволяет вставить в шаблон значение поля (свойства) объекта данных, может быть также использовано для вставки результата метода или js-выражения. Напрмер, <strong><em>&laquo;${Name}&raquo;</em></strong> &#8211; вставит в шаблон значение поля obj.Name, а при том, что Languages &#8211; это поле объекта, которому присвоен массив, <strong><em>&laquo;${Languages.length}&raquo;</em></strong> &#8211; вставит в шаблон длину этого массива, и наконец, если у объекта есть метод getLanguages с двумя параметрами, то <strong><em>&laquo;${getLanguages(Languages, &#8216; &#8211; &#8216;)}&raquo;</em></strong> &#8211; вставит в шаблон результат работы этого метода.<br />
<strong><span style="text-decoration: underline"> {{html fieldNameOrExpression}}</span></strong><br />
Элемент шаблона ${field} (или {{= field}}) вставляет в результат значение указанного поля в виде текста, т.е. если в строке будут HTML-теги, то они будут закодированы, а не преобразованы в разметку. Если вам требуется вставить данные в шаблон именно в виде HTML-разметки, то надо использовать синтаксис <strong><em>{{html &lt;что нужно вставить&gt;}}</em></strong>.<br />
Для начала работы с плагином уже достаточно рассказано, могу лишь добавить, что синтаксис шаблонов позволяет вставлять вложенные шаблоны, условные инструкции, обращаться к некоторым объектам JS и jQuery и ещё кое-что&#8230; Остальное &#8211; материал будущей статьи.</p>
<h3>Источники</h3>
<p>Статья написана по материалам, найденным во всемирной паутине. В основном это перевод официальной документации. Оригиналы можно посмотреть по следующим ссылкам:</p>
<ul>
<li> <a href="http://blog.jquery.com/2010/10/04/new-official-jquery-plugins-provide-templating-data-linking-and-globalization/"> Сообщение в блоге jQuery</a> и <a href="http://weblogs.asp.net/scottgu/archive/2010/10/04/jquery-templates-data-link-and-globalization-accepted-as-official-jquery-plugins.aspx"> в блогах MS</a></li>
<li> <a href="http://api.jquery.com/category/plugins/templates/"> Страница документации плагина</a> (примеры взяты оттуда)</li>
</ul>
<h3>Об авторе</h3>
<p>Зовут меня Зайцев Андрей, <a href="http://blog.zalab.net/">мой маленький блог</a>, профиль на форуме <a href="http://linkexchanger.su/forum/memberlist.php?mode=viewprofile&amp;u=106">zandroid</a></p>
<p>Это моя первая статья в этом блоге, надеюсь, и не последняя <img src='http://www.linkexchanger.su/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Большое спасибо Геннадию за возможность публикации и за полезные советы по написанию и оформлению материала.</p>
<h3>Примеры</h3>
<p><strong>Пример 1: Динамическое переключение применяемого шаблона</strong></p>
<pre class="brush: xml;">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;style&gt;
    table { cursor:pointer; border-collapse:collapse; border:2px solid blue; width:300px; margin:8px; }
    table tr { border:1px solid blue; color:blue; background-color:#f8f8f8; } table td { padding:3px; } table tr:hover { color:red; }
    .movieDetail { background-color:yellow; } .movieDetail.row1 { border-bottom:none; } .movieDetail.row2 { border-top:none; }
  &lt;/style&gt;
  &lt;script src=&quot;http://code.jquery.com/jquery-latest.min.js&quot;&gt;&lt;/script&gt;
  &lt;script src=&quot;http://nje.github.com/jquery-tmpl/jquery.tmpl.js&quot;&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;script id=&quot;summaryTemplate&quot; type=&quot;text/x-jquery-tmpl&quot;&gt;
  &lt;tr class='movieSummary'&gt;&lt;td colspan='2'&gt;${Name}&lt;/td&gt;&lt;/tr&gt;
&lt;/script&gt;

&lt;script id=&quot;detailTemplate&quot; type=&quot;text/x-jquery-tmpl&quot;&gt;
  &lt;tr class='movieDetail row1'&gt;&lt;td colspan='2'&gt;${Name}&lt;/td&gt;&lt;/tr&gt;&lt;tr class='movieDetail row2'&gt;&lt;td&gt;${ReleaseYear}&lt;/td&gt;&lt;td&gt;Director: ${Director}&lt;/td&gt;&lt;/tr&gt;
&lt;/script&gt;

Click for details:
&lt;table&gt;&lt;tbody id=&quot;movieList&quot;&gt;&lt;/tbody&gt;&lt;/table&gt;

&lt;script type=&quot;text/javascript&quot;&gt;
var movies = [
  { Name: &quot;The Red Violin&quot;, ReleaseYear: &quot;1998&quot;, Director: &quot;François Girard&quot; },
  { Name: &quot;Eyes Wide Shut&quot;, ReleaseYear: &quot;1999&quot;, Director: &quot;Stanley Kubrick&quot; },
  { Name: &quot;The Inheritance&quot;, ReleaseYear: &quot;1976&quot;, Director: &quot;Mauro Bolognini&quot; }
];
var selectedItem = null;

/* Render the summaryTemplate with the &quot;movies&quot; data */
$( &quot;#summaryTemplate&quot; ).tmpl( movies ).appendTo( &quot;#movieList&quot; );

/* Add onclick handlers for movie template items
using the summary or details template */
$(&quot;#movieList&quot;)
  .delegate( &quot;.movieSummary&quot;, &quot;click&quot;, function () {
    if (selectedItem) {
      // Set the template on the previously selected item
      // back to the summary template
      selectedItem.tmpl = $( &quot;#summaryTemplate&quot; ).template();
      selectedItem.update();
    }
    /* Get the data structure for the template item
       which this clicked element belongs to, and make
       it the selected item */
    selectedItem = $.tmplItem(this);

    /* Set the template on this item to the detail template */
    selectedItem.tmpl = $( &quot;#detailTemplate&quot; ).template();
    selectedItem.update();
  })
  .delegate( &quot;.movieDetail&quot;, &quot;click&quot;, function () {
    /* Set the template on this item to the summary template */
    selectedItem.tmpl = $( &quot;#summaryTemplate&quot; ).template();
    selectedItem.update();
    selectedItem = null;
  });
&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Довольно сложный и объемный, в нём используются сразу несколько методов плагина, взят с <a href="http://api.jquery.com/jquery.tmplitem/"> этой страницы</a>.</p>
<p><strong>Пример 2: Вставка данных с разметкой в шаблон</strong></p>
<pre class="brush: xml;">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;style&gt;
    .role {font-weight:bold;font-style: italic;} #movieContainer {padding-left: 8px;}
  &lt;/style&gt;
  &lt;script src=&quot;http://code.jquery.com/jquery-latest.min.js&quot;&gt;&lt;/script&gt;
  &lt;script src=&quot;http://nje.github.com/jquery-tmpl/jquery.tmpl.js&quot;&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;script id=&quot;movieTemplate&quot; type=&quot;text/x-jquery-tmpl&quot;&gt;
  &lt;h4&gt;${Name}&lt;/h4&gt;
  &lt;p&gt;{{html Synopsis}}&lt;/p&gt;
&lt;/script&gt;

&lt;div id=&quot;movieContainer&quot;&gt;&lt;/div&gt;

&lt;script&gt;
/* The Synopsis data field contains HTML markup. */
var movie = {
  Name: &quot;Meet Joe Black&quot;,
  Synopsis: &quot;The &lt;span class='role'&gt;grim reaper&lt;/span&gt; (&lt;a href='http://www.netflix.com/RoleDisplay/Brad_Pitt/73919'&gt;Brad Pitt&lt;/a&gt;) visits &lt;span class='role'&gt;Bill Parrish&lt;/span&gt; (&lt;a href='http://www.netflix.com/RoleDisplay/Anthony_Hopkins/43014'&gt;Anthony Hopkins&lt;/a&gt;)...&quot;
};

/* Render the template with the movie data.
   The template uses the {{html}} template tag
   to  insert the Synopsis HTML markup data. */
$( &quot;#movieTemplate&quot; ).tmpl( movie )
  .appendTo( &quot;#movieContainer&quot; );
&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;</pre>
<p>В этом примере в шаблон добавляются как простые строковые значения полей, так и значения с разметкой, взято вот с <a href="http://api.jquery.com/template-tag-html/"> этой страницы</a>.</p>
<h3>P.S.</h3>
<p>Примеры не стал расписывать, если аудитория поддержит мои начинания, то можно пошагово расписать что, как и почему, и привести ещё несколько примерчиков.</p>
<p>Вопросы по плагину прошу задавать на <a href="/forum/">форуме</a>, если есть комменты именно по статье &#8211; то комментируйте ниже.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.linkexchanger.su/2010/619.html/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>JavaScript мастер-классы</title>
		<link>http://www.linkexchanger.su/2010/117.html</link>
		<comments>http://www.linkexchanger.su/2010/117.html#comments</comments>
		<pubDate>Mon, 25 Jan 2010 06:34:55 +0000</pubDate>
		<dc:creator>Gennady</dc:creator>
				<category><![CDATA[jQuery]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[comet]]></category>

		<guid isPermaLink="false">http://www.linkexchanger.su/2010/117.html</guid>
		<description><![CDATA[Недавно узнал, что 20-21 февраля в Москве и 27-28 февраля в Санкт-Петербурге пройдут мастер-классы по Javascript, которые будет вести Илья Кантор &#8211; создатель  сайтов algolist.manual.ru и javascript.ru.
Это  мой уважаемый коллега, человек с большим опытом разработки сложных  приложений, в прошлом один из разработчиков javascript-фреймворка Dojo Toolkit.
» Профессиональное javascript-программирование
»  Сложный AJAX и COMET: [...]]]></description>
			<content:encoded><![CDATA[<p>Недавно узнал, что 20-21 февраля в Москве и 27-28 февраля в Санкт-Петербурге пройдут мастер-классы по Javascript, которые будет вести Илья Кантор &#8211; создатель  сайтов <a href="http://algolist.manual.ru">algolist.manual.ru</a> и <a href="http://javascript.ru">javascript.ru</a>.</p>
<p>Это  мой уважаемый коллега, человек с большим опытом разработки сложных  приложений, в прошлом один из разработчиков javascript-фреймворка <a href="http://dojotoolkit.org/">Dojo Toolkit</a>.</p>
<p>» Профессиональное javascript-программирование<br />
»  Сложный AJAX и COMET: тонкости Web 2.0<br />
» Мастер-класс по клиентской оптимизации<br />
» Секреты jQuery</p>
<p>Такие мастер-классы помогут узнать много нового, понять уровень своих знаний, получить новые идеи.</p>
<p>И еще, очень интересно! Принять участие в мастер-классе &laquo;<strong>Секреты jQuery</strong>&raquo; можно будет в режиме on-line.</p>
<p><strong><a href="http://javascript.ru/mk">Исходное объявление на javascript.ru »</a></strong><br />
<span id="more-117"></span></p>
<p>Для понимания материала необходимо знать javascript на минимальном уровне, писать простые скрипты. Содержание мастер-классов построено так, чтобы максимально глубоко раскрыть темы за короткий срок.</p>
<p>Теперь подробнее о содержании мастер-классов.</p>
<h3>&laquo;Профессиональное javascript-программирование&raquo;</h3>
<blockquote><p>- Javascript, browser tips &amp; tricks.<br />
- Фишки DOM, функции/замыкания, ООП &#8211; понятно и в деталях.<br />
- Малоизвестные возможности javascript и браузеров.<br />
- Javascript-фреймворки. Сравнение современных возможностей. jQuery в деталях.<br />
- Полезный инструментарий, который сделает вашу разработку быстрее и качественнее. Гораздо больше, чем Firebug.<br />
- Обмен информацией между окнами с разных доменов<br />
- HTML5: что уже есть, а что нас ждет уже скоро.</p></blockquote>
<p>Этот мастер класс &#8211; отнюдь не об основах javascript, здесь присутствует много информации для профессионалов.<br />
Москва: суббота, 20 февраля, 11.00<br />
Санкт-Петербург: суббота, 27 февраля, 11.00<br />
<em>Продолжительность &#8211; 4 часа.</em></p>
<h3>&laquo;Клиентская оптимизация&raquo;</h3>
<blockquote><p>- Способы и принципы сжатия javascript, что делать, чтобы код сжимался эффективнее.<br />
- Идеальное кеширование. Скрипты и серверная часть.<br />
- Эффективная оптимизация javascript. Подходы, цифры, рецепты.<br />
- Основные приемы оптимизации jQuery.<br />
- Ускорение загрузки страницы через HTTP pipelining.<br />
- Оптимизация с Google Gears и HTML5.<br />
- Google Closure Compiler в деталях<br />
- Удобные инструменты для оптимизации и профайлинга.</p></blockquote>
<p>Про то, как ускорить страницу, почти ничего не делая, и как серьезно ускорить страницу и сайт, если что-то сделать.<br />
Москва: воскресенье, 21 февраля, 11.00<br />
Санкт-Петербург: воскресенье, 28 февраля, 11.00<br />
<em>Продолжительность &#8211; 4 часа.</em></p>
<h3>&laquo;Сложный AJAX и COMET: тонкости Web 2.0&#8243;</h3>
<blockquote><p>- Асинхронная подгрузка событий с сервера (COMET) &#8211; различные варианты, сравнение и примеры реализации.<br />
- Кнопки back-forward, закладки и история с AJAX.<br />
- Cпособы написания чата/оповещающего демона, аспекты производительности и решения.<br />
- Кросс-доменные ограничения, способы их преодоления.<br />
- Асинхронный try..catch. Удобная работа с асинхронностью.<br />
- Инструменты для разработки и отладки сложных AJAX-приложений.<br />
- Специализированный COMET-сервер, установка, расширение, интеграция. Поднимем COMET прямо на мастер-классе.</p></blockquote>
<p>Мастер-класс сделает современные подходы простыми и понятными для вас, позволит улучшить те приложения, которые есть сейчас, и перейти к качественно новой разработке в будущем.<br />
Москва: суббота, 20 февраля, 16.00<br />
Санкт-Петербург: суббота, 27 февраля, 16.00<br />
<em>Продолжительность &#8211; 4 часа.</em></p>
<h3>&laquo;Секреты jQuery&raquo;</h3>
<blockquote><p>1. Как работает поисковой движок jQuery $(&#8216;&#8230;&#8217;).<br />
- Внутреннее устройство. Алгоритм поиска. No magic.<br />
- Почему некоторые очевидные запросы тормозят, и как их ускорять.<br />
- Расширение поискового движка, добавление своих фильтров.<br />
2. Система событий в jQuery.<br />
- Внутреннее устройство.<br />
- Слабо- и недокументированные фичи, отсутствующие в обычных javascript-событиях.<br />
- Влияние системы событий на быстродействие и DOM-манипуляции. Что тормозит и почему.<br />
- Обход утечек памяти.<br />
3. Фишки AJAX.<br />
- Особенные фичи AJAX в jQuery, которых нет в других библиотеках и полезные приемы работы с ними.<br />
4. $.изнутри.<br />
- Внутреннее устройство функции $. Что она делает быстро, а что &#8211; нет.<br />
- Создание плагинов. Внутренний механизм работы $.fn.plugin.<br />
5. jQuery UI.<br />
- Обзор и устройство jQuery UI.<br />
- Написание собственных виджетов. Объявление, вызов методов и т.п. Примеры.<br />
- Приемы для более удобной работы с виджетами.<br />
6. Профайлинг jQuery-приложения<br />
- Как из каши $(вызовов) получить читаемый профиль.<br />
7. Дополнительно.<br />
- Общий обзор библиотеки jQuery, ее сильных и слабых мест. Сравнение с другими фреймворками. Новое в jQuery 1.4.</p></blockquote>
<p>Мастер-класс посвящен слабо документированным особенностям и устройству фреймворка jQuery. Это не вводный курс. Знакомство и опыт работы с фреймворком jQuery &#8211; обязательны.<br />
Москва: воскресенье, 21 февраля, 16.00<br />
Санкт-Петербург: воскресенье, 28 февраля, 16.00<br />
<em>Продолжительность &#8211; 3 часа.</em><br />
<strong>On-line</strong>: суббота, 27 февраля, 20.00-21.50 и воскресенье, 28 февраля, 20.00-21.50</p>
<p><strong><a href="http://javascript.ru/mk">Дополнительная информация, запись на мастер-классы »</a></strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.linkexchanger.su/2010/117.html/feed</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Некоторые концепции JavaScript, необходимые для эффективного применения jQuery.</title>
		<link>http://www.linkexchanger.su/2009/90.html</link>
		<comments>http://www.linkexchanger.su/2009/90.html#comments</comments>
		<pubDate>Wed, 20 May 2009 12:08:27 +0000</pubDate>
		<dc:creator>Gennady</dc:creator>
				<category><![CDATA[jQuery]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://www.linkexchanger.su/2009/90.html</guid>
		<description><![CDATA[Эта статья написана &#171;по мотивам&#187; одной из глав книги &#171;jQuery &#8211; подробное руководство по продвинутому JavaScript&#187;. Информация, содержащаяся в этой главе, показалась мне настолько полезной, что я не мог не поделиться ей. Здесь не освещаются все концепции языка &#8211; внимание уделено лишь тем, понимание которых поможет эффективнее овладеть библиотекой jQuery.
Итак, первое на чем мы остановим [...]]]></description>
			<content:encoded><![CDATA[<p>Эта статья написана &laquo;по мотивам&raquo; одной из глав книги &laquo;jQuery &#8211; подробное руководство по продвинутому JavaScript&raquo;. Информация, содержащаяся в этой главе, показалась мне настолько полезной, что я не мог не поделиться ей. Здесь не освещаются все концепции языка &#8211; внимание уделено лишь тем, понимание которых поможет эффективнее овладеть библиотекой jQuery.<span id="more-90"></span></p>
<p>Итак, первое на чем мы остановим свое внимание &#8211; это определение и работа с функциями, с использованием подхода при котором они являются обычными объектами JavaScript. Но для того, чтобы к этому подойти, давайте сначала посмотрим, как создаются</p>
<h2>Объекты в JavaScript</h2>
<pre class="brush: jscript;">var card = new Object();</pre>
<p>Весьма просто, но совсем неинтересно, поскольку наш объект не содержит никакой информации. Давайте исправим это:</p>
<pre class="brush: jscript;">var card = new Object();
card.firstname = 'Ivan';
card.lastname = 'Ivanov';
card.year = '1974';
card.employed = new Date(2004,1,12);</pre>
<p>Это уже что-то полезное &#8211; создав новый экземпляр объекта, мы присвоили его переменной <strong>card</strong> и наполнили свойствами различных типов: <em>строка</em>, <em>число</em>, и <em>дата</em>.</p>
<p>Что же получается? Получается, что объект JavaScript &#8211; это набор свойств, каждое из которых состоит из имени и значения. При этом в качестве имени может выступать только строка, а вот значением (и это важный момент!!!) может быть и строка, и число, и массив, и конечно функция&#8230;</p>
<p><strong>Вывод:</strong> <em>основная цель экземпляра объекта &#8211; служить контейнером для именованных наборов других объектов.</em></p>
<p>Давайте немного усложним наш код, который мы используем в качестве примера:</p>
<pre class="brush: jscript;">var card = new Object();
card.firstname = 'Ivan';
card.lastname = 'Ivanov';
card.year = '1974';
card.employed = new Date(2004,1,12);
var phone = new Object();
phone.home = '(495)353-5353';
phone.mobile = '(903)261-1777';
card.phone = phone;</pre>
<p>мы создали еще один объект, который содержит номера телефонов и сделали этот объект значением свойства нашего первого объекта.</p>
<p>А теперь попробуем записать все тоже самое в литеральной нотации, плавно двигаясь к тому синтаксису, который присутствует в jQuery-коде практически повсеместно.</p>
<pre class="brush: jscript;">var card = {
  firstname : 'Ivan',
  lastname  : 'Ivanov',
  year      : '1974',
  employed  : new Date(2004,1,12),
  phone     : {
    home   : '(495)353-5353',
    mobile : '(903)261-1777'
  }
};</pre>
<p>Вот собственно такая форма записи и называется <strong>JSON</strong> &#8211; посмотрите, насколько проста и понятна структура:</p>
<p>- объект &#8211; пара фигурных скобок<br />
- свойства перечислены внутри скобок, через запятую<br />
- каждое свойство &#8211; это пара состоящая из имени и значения, разделенных двоеточием.</p>
<p>Давайте теперь отметим для себя еще один очень важный момент, воспользовавшись следующим простым примером:</p>
<pre class="brush: jscript;">var someVar = 'В лесу родилась елочка!';</pre>
<p>Простейшая инструкция, в которой переменной присваивается экземпляр объекта String. Если мы попробуем выполнить:</p>
<pre class="brush: jscript;">alert(someVar);</pre>
<p>увидим то, что и ожидали &#8211; сенсационное сообщение о том, что в лесу родилась елочка. Как Вы думаете, что мы увидим после выполнения следующего кода?</p>
<pre class="brush: jscript;">alert(window.someVar);</pre>
<p>Можете попробовать, но сразу скажу, что в результате получится абсолютно тоже самое сообщение! Поскольку инструкции эквивалентны, то какой же вывод из этого можно сделать?</p>
<p>Правильно! Когда ключевое слово <em>var</em> используется за пределами какой-либо функции, на глобальном уровне, оно является всего лишь ссылкой на свойство объекта <em>window</em>.</p>
<p>Ну вот, с объектами мы более-менее разобрались. Но давайте кратко сформулируем то, о чем мы говорили. Итак:</p>
<p>- объект в JavaScript &#8211; это неупорядоченный набор свойств;<br />
- свойство состоит из имени и значения;<br />
- объекты можно объявлять с помощью литералов;<br />
- глобальные переменные &#8211; есть свойства объекта window;</p>
<h2>Функция как объект JavaScript</h2>
<p>Вот теперь мы готовы к тому, чтобы вернуться к тому утверждению, что функции в JavaScript можно рассматривать как обычные объекты. Почему же в JavaScript функцию можно считать обычным объектом? Давайте возьмем для сравнения объекты других типов, например <em>String</em> или <em>Number</em>.</p>
<p>Если объекты <em>String</em> или <em>Number</em> определяются соответствующими конструкторами, то функции также определяются конструктором, в данном случае конструктором <em>Function</em>. Точно также, как и другие объекты функции могут:</p>
<p>- присваиваться переменным и свойствам объектов<br />
- передаваться в виде параметров<br />
- возвращаться как результат других функций<br />
- создаваться с использованием литералов</p>
<p>Но есть на первый взгляд одно очень существенное отличие от тех же упомянутых объектов <em>String</em> или <em>Number</em> &#8211; у функции есть имя! Но это только на первый взгляд.</p>
<p>Посмотрим простенький пример:</p>
<pre class="brush: jscript;">function hello() {
  alert('Hello, world!');
}</pre>
<p>такая запись очень часто используется для создания глобальных функций, но это совершенно не означает, что мы только что создали функцию с именем <strong>hello</strong>. Вспомните наши примеры с ключевым словом <em>var</em>. Тут практически тоже самое, только в примере с функцией ключевое слово <em>function</em> автоматически создает экземпляр объекта и присваивает его свойству объекта <em>window</em>. А имя этого свойства совпадает с именем нашей функции. Т.е. мы могли бы написать так:</p>
<pre class="brush: jscript;">hello = function () {
  alert('Hello, world!');
}</pre>
<p>или даже так:</p>
<pre class="brush: jscript;">window.hello = function () {
  alert('Hello, world!');
}</pre>
<p>Это есть синтаксис <strong>литерала функции</strong> &#8211; привыкайте, в jQuery-коде Вы будете использовать такую форму записи очень часто. Но самый главный <strong>вывод, который мы должны сделать</strong> &#8211; <em>экземпляры Function являются значениями!!!, которые можно присвоить переменным, свойствам или параметрам, через которые на них можно ссылаться</em>.</p>
<h2>Функции обратного вызова</h2>
<p>Следующий шаг &#8211; попробуем передавать функцию в качестве параметра и тут же разберем одно из самых распространенных понятий &#8211; функция обратного вызова. Смотрим код:</p>
<pre class="brush: jscript;">function hello() {
  alert('Hello, word!');
}
setTimeout(hello,5000);</pre>
<p>Объявляем функцию с именем <strong>hello</strong> и устанавливаем таймер на 5 секунд. Смотрите, передача функции в качестве параметра ничем не отличается от передачи любого другого значения &#8211; в первом параметре мы передали функцию, а во втором &#8211; число. Когда время таймера истечет, будет вызвана функция <strong>hello</strong>. Поскольку метод <em>setTimeout()</em> делает вызов функции в нашем собственном программном коде &#8211; эту функцию называют <strong>функцией обратного вызова</strong>.</p>
<p>Однако есть более изящный способ записи этого кода:</p>
<pre class="brush: jscript;">setTimeout(function(){ alert('Hello, word!'); },5000);</pre>
<p>если функцию не требуется вызывать где-то в другом месте страницы, нет никакой необходимости создавать свойство <strong>hello</strong> в объекте <em>window</em>. Такой подход будет очень часто встречаться в программном коде jQuery.</p>
<h2>Реализация this в JavaScript</h2>
<p>В объектно-ориентированных языках основанных на классах, указатель <strong>this</strong>, как правило, ссылается на экземпляр класса, в пределах которого был объявлен метод. Реализация <strong>this</strong> в JavaScript отличается едва различимым, но очень существенным образом. В JavaScript, где функции являются обычными объектами (мы говорили об этом выше), они не объявляются как часть чего-либо. <em>Объект, на который ссылается this, называется контекстом функции и определяется не тем, как функция объявляется, а тем как она вызывается.</em> Это значит, что функция может иметь различный контекст в зависимости от того, как она была вызвана.</p>
<p>Давайте вернемся к примеру и немного дополним его:</p>
<pre class="brush: jscript;">var card = {
  firstname : 'Ivan',
  lastname  : 'Ivanov',
  year      : '1974',
  employed  : new Date(2004,1,12),
  phone     : {
    home    : '(495)353-5353',
    mobile  : '(903)261-1777'
  },
  showData   : function() {
    return this.lastname+'
            '+this.firstname+'
            '+this.phone.mobile;
  }
};</pre>
<p>К первоначальному коду мы добавили свойство с именем <strong>showData</strong>, которое ссылается на экземпляр <em>Function</em>. Если теперь вызвать функцию через свойство:</p>
<pre class="brush: jscript;">alert(card.showData());</pre>
<p>то в качестве контекста функции будет установлен экземпляр объекта на который указывает <strong>card</strong>. В результате мы увидим следующее:</p>
<blockquote><p><strong>Ivanov Ivan (903)261-1777</strong></p></blockquote>
<p>Ну это все вполне естественно, гораздо более интересен следующий пример. JavaScript позволяет четко установить, что будет использоваться в качестве контекста функции. Вызывая функцию с помощью методов <em>call()</em> или <em>apply()</em> экземпляра <em>Function</em>, мы можем передать в качестве контекста все, что угодно.</p>
<pre class="brush: jscript;">var obj1 = { myProperty: 'object 1' };
var obj2 = { myProperty: 'object 2' };
var obj3 = { myProperty: 'object 3' };
window.myProperty = 'object window';

function showProperty() {
  return this.myProperty;
}

obj1.identifyMe = showProperty;

alert(showProperty());
alert(obj1.identifyMe());
alert(showProperty.call(obj2));
alert(showProperty.apply(obj3));</pre>
<p>Определили три простых объекта, у каждого из которых есть свойство <strong>myProperty</strong>. Добавили свойство <strong>myProperty</strong> в экземпляр объекта <em>window</em>. Определили глобальную функцию, которая возвращает значение свойства <strong>myProperty</strong> для любого объекта, используемого в качестве контекста этой функции. И еще присвоили эту же самую функцию свойству с именем i<strong>dentifyMe</strong> объекта <strong>obj1</strong>.</p>
<p>Дальше самое интересное &#8211; четыре раза мы вызываем один и тот же экземпляр функции другим способом и посмотрите, что получается:<br />
- в первом случае вызываем функцию как глобальную и контекстом функции является экземпляр объекта <em>window</em> о чем свидетельствует текст в окне предупреждения &#8211; &laquo;<strong>object window</strong>&laquo;.<br />
- во втором случае вызываем функцию как свойство объекта <strong>obj1</strong> и контекстом функции становится этот объект. Текст в окне предупреждения &#8211; &laquo;<strong>object 1</strong>&laquo;.<br />
- в третьем случае используем метод <em>call()</em> объекта <em>Function</em> и контекстом функции становится объект, переданный методу <em>call()</em> в качестве первого параметра. Текст в окне предупреждения &#8211; &laquo;<strong>object 2</strong>&laquo;.<br />
- наконец в четвертом случае используем метод <em>apply()</em>, передавая ему в качестве первого аргумента <strong>obj3</strong>, и получаем текст в окне предупреждения &#8211; &laquo;<strong>object 3</strong>&laquo;.</p>
<blockquote><p><a href="http://www.linkexchanger.su/jquery_articles/someConcepts1.html" target="_blank">Пример</a> можно открыть в отдельном окне.</p></blockquote>
<p><strong>Вывод такой:</strong> <em>функция fn действует как метод объекта ob, когда объект ob выступает в качестве контекста при вызове функции fn.</em></p>
<h2>Что такое замыкание?</h2>
<p><strong>Замыкание (closure)</strong> &#8211; это экземпляр <em>Function</em> вместе с локальными переменными из его окружения, необходимыми для выполнения.</p>
<p>Функция при объявлении может ссылаться на любые переменные, находящиеся в области ее видимости на момент объявления. Эти переменные будут достижимы для функции даже после того, как текущее положение в объявлении выйдет из области видимости, замыкая объявление.</p>
<p>Лучше всего пояснить это на простом примере (здесь уже используем библиотеку jQuery):</p>
<pre class="brush: jscript;">$(function(){
  var local = 1;
  window.setInterval(function(){
    $('#result').append(new Date()+
                ' значение local = '+local+'   ');
    local++;
  },5000);
});</pre>
<p>После загрузки DOM объявляем переменную <strong>local</strong> и присваиваем ей числовое значение 1. С помощью метода <em>setInterval()</em> взводим таймер, который будет срабатывать каждые 5 секунд. В качестве функции обратного вызова для таймера, определяем функцию, которая каждые пять секунд будет добавлять текущее время и значение переменной <strong>local</strong>. Кроме того, при каждом срабатывании таймера значение переменной local должно увеличиваться на единицу.</p>
<blockquote><p><a href="http://www.linkexchanger.su/jquery_articles/someConcepts2.html" target="_blank">Пример</a> можно открыть в отдельном окне.</p></blockquote>
<p>Можно было подумать, что поскольку функция обратного вызова запустится только лишь спустя 5 секунд после готовности DOM, то во время выполнения функции переменная <strong>local</strong> окажется неопределенной, ведь код в котором определяется <strong>local</strong> выходит из области видимости, как только обработчик события готовности DOM заканчивает свою работу.</p>
<p>Тем не менее этот код прекрасно работает, благодаря замыканию, созданному при объявлении функции и включающему в себя переменную <strong>local</strong>. Замыкание остается в области видимости функции на протяжении всего жизненного цикла.</p>
<p>При работе с jQuery (особенно при использовании возможностей ajax) Вы будете довольно часто сталкиваться с замыканиями. Поэтому необходимо обратить внимание на еще одну <strong>важную особенность замыканий</strong> &#8211; <em>контекст функции никогда не является частью замыкания.</em> Опять же на примере будет гораздо понятнее.</p>
<p>Посмотрите такой код:</p>
<pre class="brush: jscript;">this.id = 'someID';
$('*').each(function(){
  alert(this.id);
});</pre>
<p>Мы могли бы ожидать, что в окне предупреждения для каждого элемента будет раз за разом отображаться значение <strong>someID</strong>, однако это совсем не так. Мы увидим окно предупреждений столько раз, сколько элементов будет отобрано в объект jQuery и каждый раз будет отображаться значение атрибута <strong>id</strong> следующего элемента (или пустое окно предупреждения, если такого атрибута нет). Это происходит потому, что у каждого вызова функции собственный контекст, и в данном случае контекстом является элемент из объекта jQuery.</p>
<p>Давайте немного исправим пример:</p>
<pre class="brush: jscript;">this.id = 'someID';
var someVar = this;
$('*').each(function(){
  alert(someVar.id);
});</pre>
<p>Переменная <strong>someVar</strong> становится частью замыкания и будет доступна внутри функции обратного вызова. Такой код будет раз за разом выдавать в окне предупреждения одно и тоже значение &#8211; <strong>someID</strong>.</p>
<p>Ну, вот вроде бы и все. Осталось сказать, что если твердо усвоить все эти понятия, то создавать эффектные и эффективные сценарии на JavaScript с использованием jQuery будет гораздо проще&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.linkexchanger.su/2009/90.html/feed</wfw:commentRss>
		<slash:comments>50</slash:comments>
		</item>
		<item>
		<title>Что такое Canvas</title>
		<link>http://www.linkexchanger.su/2009/86.html</link>
		<comments>http://www.linkexchanger.su/2009/86.html#comments</comments>
		<pubDate>Tue, 14 Apr 2009 05:49:17 +0000</pubDate>
		<dc:creator>Gennady</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[canvas]]></category>

		<guid isPermaLink="false">http://www.linkexchanger.su/2009/86.html</guid>
		<description><![CDATA[К будущему надо готовиться, потому что оно наступает быстрее, чем мы его ждем. Поэтому сегодня расскажу о canvas — элементе спецификации Web Applications 1.0, которая со временем вероятно воплотится в язык HTML5. Сама спецификация подготовлена рабочей группой WHAT-WG (Web Hypertext Application Technology Working Group) и добавляет ряд нововведений в HTML и DOM.
Однако начнем с примера [...]]]></description>
			<content:encoded><![CDATA[<p>К будущему надо готовиться, потому что оно наступает быстрее, чем мы его ждем. Поэтому сегодня расскажу о canvas — элементе спецификации Web Applications 1.0, которая со временем вероятно воплотится в язык HTML5. Сама спецификация подготовлена рабочей группой WHAT-WG (Web Hypertext Application Technology Working Group) и добавляет ряд нововведений в HTML и DOM.<br />
Однако начнем с примера использования <strong>canvas</strong>&#8230;<span id="more-86"></span><br />
<iframe src="http://www.linkexchanger.su/examples_2009/canvas/canvas.html" style="border: medium none " width="420" height="180"></iframe><br />
Не знаю как кого, а меня пример впечатлил&#8230;</p>
<p>Итак, элемент Canvas предназначен для создания bitmap изображения при помощи JavaScript, т.е. мы получаем возможность создавать графические формы, рисовать линии, вращать изображения.</p>
<p>Такие возможности подстегнули производителей браузеров к включению API canvas в последние версии своих продуктов &#8211; FireFox, Opera, Chrome, Safari поддерживают тэг canvas. Как всегда неприятным исключением оказался горячо нелюбимый всеми Internet Explorer &#8211; не то что в 6 и 7 версиях, даже в 8 версии поддержка тэга canvas не планируется.</p>
<p>Однако не все так безнадежно как могло бы показаться &#8211; на помощь пришла компания Google, реализовав для IE полноценный API Canvas. По сути это небольшой js-файл, подключая который для браузеров IE можно заставить их &laquo;понимать&raquo; тэг canvas. Найти этот файл можно тут:<br />
<a href="http://code.google.com/p/explorercanvas/" target="_blank">http://code.google.com/p/explorercanvas/</a></p>
<p>Но вернемся к нашему примеру. Для того, чтобы изобразить такие часики на своей страничке понадобится подключить в разделе HEAD файл excanvas.js &#8211; это для ого, чтобы заставить браузеры IE понимать canvas:</p>
<pre class="brush: jscript;">&lt;!--[if IE]&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;excanvas.js&quot;&gt;&lt;/script&gt;
&lt; ![endif]--&gt;</pre>
<p>В body добавим следующую разметку:</p>
<pre class="brush: xml;">&lt;canvas id=&quot;canvas&quot; height=&quot;150&quot; width=&quot;150&quot;&gt;&lt;/canvas&gt;</pre>
<p>И самое главное &#8211; JS-код, который и рисует сами часики:</p>
<pre class="brush: jscript;">
// ожидаем загрузку
window.onload = function(){
  // рисуем часы
  clock();
  // через каждую секунду
  // часы перерисовываются
  setInterval(clock, 1000);
}
//
function clock() {
  // получаем текущие дату и время
  var now = new Date();
  var sec = now.getSeconds();
  var min = now.getMinutes();
  var hr = now.getHours();

  // получаем контекст canvas
  var ctx = document
  .getElementById(&quot;canvas&quot;)
  .getContext(&quot;2d&quot;);

  // сохраняем состояние
  ctx.save();
  // инициализируем холст
  ctx.clearRect(0,0,150,150);
  // рисуя в точке 0,0 фактически
  // рисуем в точке 75,75
  ctx.translate(75,75);
  // при рисовании линии в 100px
  // фактически рисуем линию в 40px
  ctx.scale(0.4,0.4);
  // начинаем вращать с 12:00
  ctx.rotate(-Math.PI/2);

  // инициализируем свойства рисунка
  // контуры рисуем черным
  ctx.strokeStyle = &quot;black&quot;;
  // заливка тоже черная
  ctx.fillStyle = &quot;black&quot;;
  // ширина линии 8px
  ctx.lineWidth = 8;
  // будем рисовать по кругу
  ctx.lineCap = &quot;round&quot;;

  // начинаем рисовать часовые метки
  // сохраняем предыдущее состояние
  ctx.save();
  ctx.beginPath();
  // для каждого часа
  for(var i = 0; i &lt; 12; i++) {
  	// поворачиваем на 1/12
    ctx.rotate(Math.PI/6);
    // перемещаем курсор
    ctx.moveTo(100,0);
    // рисуем черточку 20px
    ctx.lineTo(120,0);
  }
  ctx.stroke();
  ctx.restore();

  // сохраняем состояние
  ctx.save();
  // ставим ширину линии 5px
  ctx.lineWidth = 5;
  ctx.beginPath();
  // рисуем минутные метки
  // для каждой минуты
  for(var i = 0; i &lt; 60; i++) {
  	// кроме тех, что совпадут
  	// с часами
    if(i%5 != 0) {
      // перемещаем курсор
      ctx.moveTo(117,0);
      // рисуем черточку 3px
      ctx.lineTo(120,0);
    }
    // вращаем холст на 1/60
    ctx.rotate(Math.PI/30);
  }
  ctx.stroke();
  ctx.restore();

  // сохраняем состояние
  ctx.save();
  // начинаем рисовать часовую стрелку
  // вращаем холст на текущую позицию
  ctx.rotate((Math.PI/6)*hr +
             (Math.PI/360)*min +
             (Math.PI/21600)*sec);
  // устанавливаем ширину линии 14px
  ctx.lineWidth = 14;

  ctx.beginPath();
  // сдвигаем курсор несколько назад
  // стобы было похоже на стрелку
  ctx.moveTo(-20,0);
  // рисуем линию почти до часовых меток
  ctx.lineTo(80,0);
  ctx.stroke();
  ctx.restore();

  // сохраняем состояние
  ctx.save();
  // начинаем рисовать минутную стрелку
  // вращаем холст на текущую позицию
  ctx.rotate((Math.PI/30)*min +
             (Math.PI/1800)*sec);
  // ширина линии 10px
  ctx.lineWidth = 10;
  ctx.beginPath();
  // двигаем курсор
  ctx.moveTo(-28,0);
  // рисуем линию
  ctx.lineTo(112,0);
  ctx.stroke();
  ctx.restore();

  // сохраняем состояние
  ctx.save();
  // начинаем рисовать секундную стрелку
  // вращаем холст на текущую позицию
  ctx.rotate(sec * Math.PI/30);
  // контур и заливка красного цвета
  ctx.strokeStyle = &quot;#D40000&quot;;
  ctx.fillStyle = &quot;#D40000&quot;;
  // ширина линии 6px
  ctx.lineWidth = 6;
  ctx.beginPath();
  // двигаем курсор
  ctx.moveTo(-30,0);
  // рисуем линию
  ctx.lineTo(83,0);
  ctx.stroke();
  ctx.restore();

  // сохраняем состояние
  ctx.save();
  // рисуем внешнюю окружность
  // шириной 14px
  ctx.lineWidth = 14;
  // синим цветом
  ctx.strokeStyle = &quot;#325FA2&quot;;
  ctx.beginPath();
  // рисуем окружность, отступающую
  // от центра на 142px
  ctx.arc(0,0,142,0,Math.PI*2,true);
  ctx.stroke();
  ctx.restore();

  ctx.restore();
}</pre>
<blockquote><p>Вы можете <a href="http://www.linkexchanger.su/examples_2009/canvas/canvas.zip">скачать файлы</a> этого примера. Можно <a href="http://www.linkexchanger.su/examples_2009/canvas/canvas.html" target="_blank">открыть пример</a> в новом окне и посмотреть исходный код.</p></blockquote>
<p>В заключение я приведу несколько очень полезных ссылок, для тех, кто заинтересовался.<br />
<a href="https://developer.mozilla.org/En/Canvas_tutorial">Canvas Tutorial</a> &#8211; туториал (на английском конечно), но там Вы найдете еще впечатляющие примеры.<br />
<a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#the-canvas-element">The canvas element</a> &#8211; подраздел спецификации HTML5, касающийся элемента canvas (и тоже ес-но на английском).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.linkexchanger.su/2009/86.html/feed</wfw:commentRss>
		<slash:comments>30</slash:comments>
		</item>
	</channel>
</rss>

