<?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>JSToolbox - все о JavaScript &#187; JavascriptMVC</title>
	<atom:link href="http://www.jstoolbox.com/category/javascriptmvc/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.jstoolbox.com</link>
	<description>Блог о программировании вообще и о JavaScript в частности, уроки, статьи, заметки, база знаний.</description>
	<lastBuildDate>Wed, 28 Jul 2010 22:33:40 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Model-View-Controller для JavaScript</title>
		<link>http://www.jstoolbox.com/2008/05/05/model-view-controller-dlya-javascript/</link>
		<comments>http://www.jstoolbox.com/2008/05/05/model-view-controller-dlya-javascript/#comments</comments>
		<pubDate>Mon, 05 May 2008 21:30:07 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Design patterns]]></category>
		<category><![CDATA[JavascriptMVC]]></category>
		<category><![CDATA[MVC]]></category>

		<guid isPermaLink="false">http://www.jstoolbox.com/2008/05/05/model-view-controller-dlya-javascript/</guid>
		<description><![CDATA[Приветствую Вас дорогие читатели!
Для тех из вас, кто знаком с RubyOnRail, CodeIgniter, CakePHP, парадигма Model, View, Controller не является новинкой. Шаблон MVC позволяет разделить данные, представление и обработку действий пользователя на три отдельных компонента: модель (Model) для предоставления данных, представление (View) для отображения информации и контроллер (Controller) для интерпретации данных, введенных пользователем.
Если для таких языков [...]]]></description>
			<content:encoded><![CDATA[<p>Приветствую Вас дорогие читатели!</p>
<p>Для тех из вас, кто знаком с RubyOnRail, CodeIgniter, CakePHP, парадигма Model, View, Controller не является новинкой. Шаблон MVC позволяет разделить данные, представление и обработку действий пользователя на три отдельных компонента: модель (Model) для предоставления данных, представление (View) для отображения информации и контроллер (Controller) для интерпретации данных, введенных пользователем.</p>
<p>Если для таких языков программирования, как PHP, Ruby, Python, существует множество фреймворков, использующих MVC, то для JavaScript это пока диковинка. Совсем недавно появился именно такой фреймворк для JavaScript &#8211; <a href="http://javascriptmvc.com/index.html">JavaScriptMVC</a></p>
<div style="width:480px;margin:0 auto"><img src='http://www.jstoolbox.com/wp-content/uploads/2008/04/mvc.jpg' alt='JavascriptMVC' /></div>
<p>Разработка фреймворка пока еще в стадии &#8220;альфа&#8221;, но тем не менее, он уже сейчас обладает внушительными возможностями. Есть большой набор дополнительных плагинов для использования AJAX, тестирования, добавления объекта History, работы с массивами, строками и много другое. Также, что немаловажно, возможно использование <strong>JavascriptMVC</strong> с другими библиотеками &#8211; jQuery, Prototype и др.</p>
<p>Я решил попробовать библиотеку в действии и создать простое приложение. Вот что у меня получилось: <a href="/demo/jmvc/helloworld.html">demo</a>.</p>
<p><span id="more-117"></span></p>
<p>Теперь шаг за шагом о том, как я сделал его.</p>
<h4>Шаг 1: установка</h4>
<p><a href="http://javascriptmvc.googlecode.com/files/javascriptmvc-0.9.6.zip">Скачайте</a> дистрибутив и распакуйте его локально или на веб сервер.</p>
<h4>Шаг 2: HTML</h4>
<p>Создадим пустой HTML документ, в который добавим скрипт include.js с двумя параметрами &#8211; именем приложения и параметром, определяющим режим разработки: development, production, test, compress. Тип development удобен при разработке и отладке приложения, test при тестировании (автоматически появится pop-up окно с тестами), compress автоматически сожмет все скрипты, production &#8211; режим &#8220;готового&#8221; приложения.</p>
<pre class="prettyprint">
&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
&lt;html lang="en">
   &lt;head>&lt;/head>
   &lt;body>
      &lt;script type='text/javascript' src='jmvc/include.js?helloworld,development'>&lt;/script>
   &lt;/body>
&lt;/html>
</pre>
<p><br/></p>
<h4>Шаг 3: создание приложения.</h4>
<p>В параметре <strong>include.js</strong> мы указали название приложения &#8211; <strong>helloworld</strong>. Это значит, что скрипт <strong>include</strong> будет искать файл приложения <strong>helloworld.js</strong> в папке <strong>apps</strong>. Создадим его, и добавим туда несколько строк:</p>
<pre class="prettyprint">
// подключаем плагины view и controller
include.plugins('controller');
include.plugins('view');
include.plugins('model');

// подключаем контроллеры
include.controllers('main');
include.controllers('hello');
include.models('hello');
</pre>
<p>Здесь мы подключаем плагины <strong>view</strong>, <strong>controller</strong> и <strong>model</strong>, а затем подключаем контроллеры <strong>main</strong> и <strong>hello</strong>, которые будут управлять всеми событиями на странице. Контроллер <strong>main</strong> (MainController) &#8211; это специальный тип контроллера, который позволяет добавлять обработчики событий к объектам <strong>window</strong> и <strong>document</strong>. В последней строке мы добавляем модель <strong>hello</strong>, которая нужна для получения данных от сервера.</p>
<p><br/></p>
<h4>Шаг 4: Создание контроллеров.</h4>
<p>Контроллеры создаем в папке <strong>controllers</strong>, обязательно указывая для них постфикс <strong>_controllers.js</strong>. В файл <strong>main_controller.js</strong> пишем следующее:</p>
<pre class="prettyprint">
Controller('main',{
  // обработчик события onload для объекта window
  load: function(){

	var data = {
		header : new View({url: 'header.ejs'}).render({title:'My MVC page'}),
		footer : new View({url: 'footer.ejs'}).render({copyright:'Some rights reserved. My copyright notice'}),
		sidebar : new View({url: 'sidebar.ejs'}).render({aList : [{linkTitle:'Link1',linkHref:'#1'}, {linkTitle:'Link2',linkHref:'#2'}, {linkTitle:'Link3',linkHref:'#3'}]})
	}
	document.body.innerHTML = new View({url: 'layout.ejs'}).render(data);
  }
});
</pre>
<p>Здесь мы инициализируем новый контроллер и функцию <strong>load</strong>, которая будет выполняться при загрузке страницы. В файл <strong>hello_controller.js</strong> пишем следующее:</p>
<pre class="prettyprint">
Controller('links',{
  // обработчик события onclick для элементов с атрибутом class="link"
  click: function(params){
  	  var href = params.element.getAttribute('href');
  	  var id = href.replace(/^.*\#/,'');
  	  Hello.find(id, null, find_callback);
  	  params.event.preventDefault();
  }
});

// обрабатываем полученный от сервера результат
function find_callback(post){
	var elem = document.getElementById("content");
	elem.innerHTML = '&lt;h2>' + post.postTitle + '&lt;/h2>';
	elem.innerHTML += '&lt;p>' + post.postBody + '&lt;/p>';
}
</pre>
<p>В этом контроллере функция <strong>click</strong> будет выполняться для элементов с атрибутом class=&#8221;link&#8221;. Здесь следует упомянуть о правилах именования элементов, определяющих порядок присвоения контроллеров к элементам HTML:</p>
<ol>
<li>Если имя контроллера в множественном числе (множественное число в английском языке обозначается суффиксом -s в конце), например &#8216;employees&#8217;, то он соответствует всем элементам с именем класса в единственном числе, т.е. &#8216;employee&#8217;.</li>
<li>Если имя контроллера в единственном числе, например &#8216;item&#8217;, то он соответствует элементам с ID, равным имени контроллера, т.е. &#8216;item&#8217;.</li>
</ol>
<p>Что касается аргумента <strong>params</strong>, то это объект, который включает в себя переменные <strong>event</strong> (объект &#8220;событие&#8221;), <strong>element</strong> (ссылка на элемент, который вызвал событие) и <strong>action</strong> (например &#8220;click&#8221; &#8211; тип события). Далее я использую функцию <strong>preventDefault()</strong> объект <strong>event</strong> чтобы предотвратить действие ссылки по умолчанию (объект event кроссбраузерный, поэтому это будет работать и в IE).</p>
<p><br/></p>
<h4>Шаг 5: создание шаблонов (View)</h4>
<p>Шаблоны подключаются примерно следующим образом:</p>
<pre class="prettyprint">
var myView = new View({url: 'file_name.ejs'});
</pre>
<p>Здесь параметр <strong>url</strong> указывает имя файла шаблона, который должен находиться в папке <strong>view</strong>. Для отображения шаблона (или обработки его содержимого) используется функция <strong>render()</strong>, в которую нужно передать объект с переменными шаблона. Пример:</p>
<pre class="prettyprint">
var myView = new View({url: 'file_name.ejs'});
var someHTML = myView.render( { 'name' : 'value', 'nick' : 'dima' } );
</pre>
<p>В нашем примере я подключил черыре разных шаблона в контроллер <strong>main</strong>:</p>
<pre class="prettyprint">
	var data = {
		header : new View({url: 'header.ejs'}).render({title:'My MVC page'}),
		footer : new View({url: 'footer.ejs'}).render({copyright:'Some rights reserved. My copyright notice'}),
		sidebar : new View({url: 'sidebar.ejs'}).render({aList : [{linkTitle:'Link1',linkHref:'#1'}, {linkTitle:'Link2',linkHref:'#2'}, {linkTitle:'Link3',linkHref:'#3'}]})
	}
	document.body.innerHTML = new View({url: 'layout.ejs'}).render(data);
</pre>
<p>Самый главный шаблон здесь &#8211; <strong>layout.ejs</strong>, который определяет основную структуру документа, содержимое остальных трех передается в <strong>layout.ejs</strong> в качестве переменных шаблона. Содержимое этого шаблона запишем следующим образом:</p>
<pre class="prettyprint">
&lt;%= header %>

&lt;div id="page">
	&lt;%= sidebar %>
	&lt;div id="content">
	&lt;h4>Page content&lt;/h4>
	&lt;p>Some text&lt;/p>
	&lt;/div>
	&lt;div class="clr">&lt;/div>
&lt;/div>

&lt;%= footer %>
</pre>
<p>Как видите это просто HTML с добавлением переменных шаблона в тэгах <strong>&lt;%= &#8230; %&gt;</strong>. Если у нас в шаблоне, к примеру есть переменная <strong>&lt;%= header %&gt;</strong>, а в функцию <strong>render()</strong> был передан объект <strong>data</strong>, то переменная шаблона <strong>header</strong> будет заменена на содержимое переменной <strong>data.header</strong>.</p>
<p>Теперь создаем остальные шаблоны.</p>
<p><strong>header.ejs</strong> &#8211; &#8220;шапка&#8221; страницы:</p>
<pre class="prettyprint">
&lt;div id="header">
	&lt;h4 id="hello">&lt;%= title %>&lt;/h4>
&lt;/div>
</pre>
<p><strong>sidebar.ejs</strong> &#8211; сайдбар:</p>
<pre class="prettyprint">
&lt;div id="sidebar">
&lt;ul>
    &lt;% for(var i=0; i&lt;aList.length; i++) { %>
        &lt;li>
            &lt;a href='&lt;%= aList[i].linkHref %>' class="link">
                &lt;%= aList[i].linkTitle %>
            &lt;/a>
        &lt;/li>
    &lt;% } %>
&lt;/ul>
&lt;/div>
</pre>
<p>В этом шаблоне помимо обычных тэгов, используются тэги без знака &#8220;равно&#8221; <strong>&lt;% &#8230; %&gt;</strong>. Они не возвращают результат, а их содержимое просто выполняется интерпретатором. Я использую их здесь для организации цикла.</p>
<p><strong>footer.ejs</strong> &#8211; &#8220;подвал&#8221; страницы:</p>
<pre class="prettyprint">
&lt;div id="footer">&lt;%= copyright %>&lt;/div>

&lt;/body>
&lt;/html>
</pre>
<p><br/></p>
<h4>Шаг 6: создание моделей (Model)</h4>
<p>В серверных приложениях MVC, таких как Ruby On Rails, Codeigniter и др., модели выполняют роль связующего звена между контроллерами и базой данных. В JavascriptMVC для этой цели используются асинхронные запросы к серверу при помощи библиотеки <a href="http://jesterjs.com">Jester</a>, которая имитирует <strong>ActiveResource</strong> в приложениях <strong>Rails</strong>.</p>
<pre class="prettyprint">
Model('hello', {
	format: 'json',
	prefix: 'jmvc/resource',
	urls : { list: "/get.php", show: "/get.php?id=:id", create: "/create.php", update: "/update.php?id=:id" }
},
  null,
  null
);
</pre>
<p>Здесь мы просто создаем объект класса <strong>Model</strong>. Для его создания я использовал только два параметра &#8211; имя модели и опции. В опциях указаны формат сообщений (json или xml), <strong>prefix</strong> &#8211; путь к файлам обработчикам (в данном примере путь будет /jmvc/resource) и <strong>urls</strong> &#8211; файлы, которые будут возвращать результат при выборке данных (get.php) создании (create.php) и обновлении (update.php).</p>
<p>Для работы с данными в классе <strong>Model</strong> есть функции <strong>find()</strong> для выборки данных, <strong>create()</strong> &#8211; для добавления данных в БД, <strong>update()</strong> для обновления данных в БД и прочее.</p>
<p>В данном примере я использую только функцию <strong>find()</strong> для получения записи (смотрите выше в контроллере links).</p>
<pre class="prettyprint">
Hello.find(id, null, find_callback);
</pre>
<p>Здесь <strong>id</strong> &#8211; это параметр, который будет подставлен в URL (выше мы указали для запроса show: &#8220;get.php?id=:id&#8221;, т.е. если id=3, то получим запрос get.php?id=3). Последний параметр это callback для обработки полученных результатов.</p>
<p>На этом всё. Смотрите демо, если нужно скачивайте пример. Только устанавливать надо на веб сервер чтобы увидеть в работе работу модели.<br/><br />
До встречи!</p>
<p><br/></p>
<p><a href="/demo/jmvc/helloworld.html" class="demo">смотреть демо</a><a href="/download/jmvc.zip" style="margin-left:18px" class="download">загрузить пример</a></p>
<p><br/>Также можно скачать различные демо на <a href="http://code.google.com/p/javascriptmvc/">странице проекта в Google Code</a><br/></p>
]]></content:encoded>
			<wfw:commentRss>http://www.jstoolbox.com/2008/05/05/model-view-controller-dlya-javascript/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
	</channel>
</rss>
