<?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>Очередной блог фрилансера &#187; ajax</title>
	<atom:link href="http://dreamhelg.ru/tag/ajax/feed/" rel="self" type="application/rss+xml" />
	<link>http://dreamhelg.ru</link>
	<description>о моей работе в сети и не только</description>
	<lastBuildDate>Mon, 14 May 2012 19:53:02 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Простой, перетаскиваемый элемент на jQuery</title>
		<link>http://dreamhelg.ru/2009/11/simple-draggable-element-with-jquery/</link>
		<comments>http://dreamhelg.ru/2009/11/simple-draggable-element-with-jquery/#comments</comments>
		<pubDate>Mon, 23 Nov 2009 07:54:16 +0000</pubDate>
		<dc:creator>dreamhelg</dc:creator>
				<category><![CDATA[общая]]></category>
		<category><![CDATA[переводы]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://dreamhelg.ru/?p=1713</guid>
		<description><![CDATA[<p><img width="200" height="200" src="http://dreamhelg.ru/wp-content/uploads/2009/11/200x200.jpg" class="attachment-200x200 wp-post-image" alt="200x200" title="200x200" /></p>Бывают случаи, когда вам может понадобиться создать перетаскиваемый элемент внутри вашего веб-приложения. Это отличная функциональность, однако, возможно вы хотите, чтобы элемент оставался на новом месте, после перетаскивания.  В сегодняшней статье вы узнаете, как можно легко перетаскивать и закреплять в новом месте нужный элемент даже после перезагрузки страницы, с помощью захвата и хранения его X и Y координат.<span id="more-1713"></span>

<h3>Сценарий</h3>
Итак, у вас есть элемент на странице. Вы можете перетаскивать его туда-сюда. Но, когда страница перезагружается, элемент возвращается на исходную позицию.  И хотя нам нужно, чтобы элемент был перетаскиваемый, при этом нужно, чтобы наш элемент достаточно было перетащить один раз. Давайте рассмотрим простое решение, реализующее данную функциональность.

<h3>Начало</h3>
Для этого примера нам понадобится библиотека <a href="http://jquery.com/">jQuery</a>, <a href="http://jqueryui.com/">jQuery UI </a>и плагин JQuery-<a href="http://code.google.com/p/jquery-json/">JSON</a>. Кроме этого, мы также будем использовать PHP и базу данных MySQL для разбора и хранения наших данных. Если вы новичок в jQuery, не беспокойтесь. JQuery - это расширяемая, быстрая и легковесная JavaScript-библиотека, которую легко и весело использовать. Библиотека имеет хорошо структурированную документацию и огромное сообщество.

<a href="http://dreamhelg.ru/wp-content/uploads/2009/11/jquery.jpg"><img class="aligncenter size-full wp-image-1716" title="jquery" src="http://dreamhelg.ru/wp-content/uploads/2009/11/jquery.jpg" alt="jquery" width="500" height="200" /></a>

<h3>HTML и CSS</h3>
Начнем с HTML-разметки и стилей для нашего примера. Сначала CSS:

[css]
html, body {   
    background:#151515;   
    margin:0 0 0 0;   
    padding:0 0 0 0;   
}   
  
#glassbox {   
    background:#333;   
    border:1px solid #000;   
    height:400px;   
    margin:30px auto auto auto;   
    position:relative;   
    width:960px;   
    -moz-border-radius: 10px;   
    -webkit-border-radius: 10px;       
}   
  
#element {   
    background:#666;   
    border:1px #000 solid;   
    cursor:move;   
    height:143px;   
    padding:10px 10px 10px 10px;   
    width:202px;   
    -moz-border-radius: 10px;   
    -webkit-border-radius: 10px;   
}   
  
#respond{   
    color:#fff;   
    margin:0 auto 0 auto;   
    width:960px;       
}  
[/css]

CSS – очень простой. Мы назначаем html и body нулевые свойства, для чистки внешних и внутренних отступов, далее устанавливаем значения высоты, ширины и другие свойства для наших элементов. -<code>moz-border-radius</code> и <code>-webkit-border-radius</code> – это два свойства, позволяющие нам создать закругленные углы (работает пока только в Mozilla Firefox и Safari 3) для наших элементов. Теперь, давайте взглянем на HTML:

[html]
&lt;!DOCTYPE html&gt;   
&lt;html&gt;   
&lt;head&gt;   
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;   
&lt;title&gt;Simple Draggable Element Persistence with jQuery&lt;/title&gt;   
  
&lt;link rel=&quot;stylesheet&quot; href=&quot;style.css&quot; type=&quot;text/css&quot; /&gt;   
&lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery-1.3.2.min.js&quot;&gt;&lt;/script&gt;   
&lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery-ui-1.7.2.custom.min.js&quot;&gt;&lt;/script&gt;   
&lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery.json-2.2.min.js&quot;&gt;&lt;/script&gt;   
  
&lt;/head&gt;   
  
&lt;body&gt;   
  
    &lt;div id=&quot;glassbox&quot;&gt;   
        &lt;div id=&quot;element&quot;&gt;&lt;img src=&quot;nettuts.jpg&quot; alt=&quot;Nettuts+&quot; /&gt;Move the Box&lt;p&gt;&lt;/p&gt;&lt;/div&gt;   
    &lt;/div&gt;   
  
    &lt;div id=&quot;respond&quot;&gt;&lt;/div&gt;   
[/html]

Как видите, мы создали очень простую страницу, в которую подключили наш CSS, библиотеку JavaScript и плагины, кроме того, страница содержит элементы, к которым мы будем применять некоторые эффекты и события. Обратите внимание, что файл jquery-ui представляет собой специальную сборку, включающую в себя только ядро и функции перетаскивания элементов.

<a href="http://dreamhelg.ru/wp-content/uploads/2009/11/general.jpg"><img class="aligncenter size-full wp-image-1717" title="general" src="http://dreamhelg.ru/wp-content/uploads/2009/11/general.jpg" alt="general" width="584" height="452" /></a>

<h3>JavaScript</h3>
Теперь самое интересное! Сначала давайте рассмотрим базовые функции, которые мы будем использовать для применения некоторых эффектов к нашим элементам. Разберем все до основания.

[javascript]
&lt;script type=&quot;text/javascript&quot;&gt;   
    $(document).ready(function() {   
        $(&quot;#element&quot;).draggable({    
                containment: '#glassbox',    
                scroll: false   
         })   
[/javascript]

Сначала мы говорим браузеру: «Эй, это код, который мы хотим запустить; это не HTML, это JavaScript». Затем, мы ждем пока документ полностью загрузится, после того как это случилось, вызываем функцию для получения нашего блока <code>#element</code>, и добавляем к нему обработчик перетаскивания с базовыми настройками. Опция <code>containment</code> содержит наш элемент внутри родительского блока, и мы устанавливаем значение <code>scroll</code> в <code>false</code>, потому что, нам не нужен скролл.

Двигаемся дальше:

[javascript]
.mousemove(function(){   
    var coord = $(this).position();   
    $(&quot;p:last&quot;).text( &quot;left: &quot; + coord.left + &quot;, top: &quot; + coord.top );   
})   
[/javascript]

Внутри этого фрагмента, мы вызываем, обработчик события mousemove и говорим ему: «Когда мышь передвигается, установить переменную <code>coord</code> равной значению текущей позиции нашего блока #element» Затем мы получаем последний параграф в блоке <code>#(“p: last”) </code>и печатаем текст, выводящий значения свойств <code>left(x) </code>и <code>top(y)</code> нашего элемента, относительно родительского объекта (которым является блок <code>#glassbox</code>).

[javascript]
.mouseup(function(){    
            var coords=[];   
            var coord = $(this).position();   
            var item={ coordTop:  coord.left, coordLeft: coord.top  };   
            coords.push(item);   
            var order = { coords: coords };   
            $.post('updatecoords.php', 'data='+$.toJSON(order), function(response){   
                    if(response==&quot;success&quot;)   
                        $(&quot;#respond&quot;).html('&lt;div class=&quot;success&quot;&gt;X and Y Coordinates Saved!&lt;/div&gt;').hide().fadeIn(1000);   
                        setTimeout(function(){ $('#respond').fadeOut(1000); }, 2000);   
                    });    
            });   
                       
});   
lt;/script&gt;   
[/javascript]

Ну да, здесь уже сложнее. В этом фрагменте мы собираемся сделать кучу вещей. Сначала, мы устанавливаем пустой массив, а затем получаем некоторые значения для его наполнения. С помощью вызова обработчика событий <code>.mouseup()</code> мы велим браузеру отслеживать событие, когда вы отпускаете кнопку мыши. Мы указываем, что переменная <code>coords</code> – это пустой массив и снова устанавливаем ее значение равной позиции нашего блока <code>#element</code>.

Затем, нам нужно создать список из двух строчек, которыми будут <code>coordTop:</code> и <code>coordLeft:</code>, соответствующие позициям <code>left</code> и <code>top</code>, нашего блока. С помощью строки <code>coords.push(item)</code>, мы заполним наш список массивом из координат. Затем задаем переменную <code>order</code> как новый список, в котором ключ <code>coords</code> будет соответствовать нашему массиву <code>coords</code>. Теперь немного аякса.

<a href="http://dreamhelg.ru/wp-content/uploads/2009/11/dragged.jpg"><img class="aligncenter size-full wp-image-1718" title="dragged" src="http://dreamhelg.ru/wp-content/uploads/2009/11/dragged.jpg" alt="dragged" width="528" height="458" /></a>

<code>$.post</code> – это обработчик запроса AJAX, который загружает удаленную страницу, с помощью метода <code>HTTP POST</code>. Эта функция принимает следующие параметры: url, дата, ответ и тип данных для возврата. В этом примере, мы укажем файле updatecoords.php в качестве нашего URL, потому что, именно этому файлы мы хотим отправить наши данные. Затем, мы опишем тип данных, с помощью включения функции <code>$.toJSON</code>, определенной в плагине JSON и назначим переменную <code>order</code>, в качестве данных, которые должен вернуть <code>.toJSON</code>.

Далее, мы создаем ответ, который проверяет возвращение успешного ответа от нашего PHP-файла. В случае получения успешного ответа, мы отображаем сообщение об успешном сохранении координат, используя метод <code>.fadeIn()</code> и скорость 1000 миллисекунд, затем задаем таймер на 2000 миллисекунд, и снова медленно прячем это сообщение, с помощью метода <code>.fadeOut()</code>. Вот так будет выглядеть наш JavaScript в целом виде:

[javascript]
&lt;script type=&quot;text/javascript&quot;&gt;   
    $(document).ready(function() {   
        $(&quot;#element&quot;).draggable({    
                containment: '#glassbox',    
                scroll: false   
         }).mousemove(function(){   
                var coord = $(this).position();   
                $(&quot;p:last&quot;).text( &quot;left: &quot; + coord.left + &quot;, top: &quot; + coord.top );   
         }).mouseup(function(){    
                var coords=[];   
                var coord = $(this).position();   
                var item={ coordTop:  coord.left, coordLeft: coord.top  };   
                coords.push(item);   
                var order = { coords: coords };   
                $.post('updatecoords.php', 'data='+$.toJSON(order), function(response){   
                        if(response==&quot;success&quot;)   
                            $(&quot;#respond&quot;).html('&lt;div class=&quot;success&quot;&gt;X and Y Coordinates Saved!&lt;/div&gt;').hide().fadeIn(1000);   
                            setTimeout(function(){ $('#respond').fadeOut(1000); }, 2000);   
                        });    
                });   
                           
        });   
&lt;/script&gt;   
[/javascript]

Поместите этот код ниже HTML, сразу после закрывающего тега body.
<h3>PHP</h3>
Хорошо, давайте сделаем что-нибудь с данными, которые приходят от нашего JQuery. Сначала нужно создать простую базу данных, для хранения наших координат, которые мы впоследствии будем использовать для определения позиции нашего элемента. Затем, нам понадобится файл config.php, в котором будут записаны параметры подключения к базе данных, а затем мы перейдем к updatecords.php.

<strong>SQL</strong>

[sql]
Database: 'xycoords'   
  
CREATE TABLE IF NOT EXISTS `coords` (   
  `id` int(11) NOT NULL AUTO_INCREMENT,   
  `x_pos` int(4) NOT NULL,   
  `y_pos` int(4) NOT NULL,   
  PRIMARY KEY (`id`)   
) ENGINE=MyISAM  DEFAULT CHARSET=latin1; 
[/sql]

<strong>Config.php</strong>

[php]
&lt;?php   
/*Database Settings*/   
  
$db_host =&quot;localhost&quot;; //this will likely stay the same   
$db_name = &quot;xycoords&quot;; //name of the database we will be using   
$db_usr = &quot;database_username&quot;; //db username   
$db_pass = &quot;database_password&quot;; //db password   
  
//Connect to the database   
$link = mysqli_connect($db_host, $db_usr, $db_pass) or die(&quot;MySQL Error: &quot; . mysqli_error());   
//Select our database   
mysqli_select_db($link, $db_name) or die(&quot;MySQL Error: &quot; . mysqli_error());   
?&gt;   
[/php]

<strong>updatecoords.php</strong>

[php]
&lt;?php   
if(!$_POST[&quot;data&quot;]){   
    echo &quot;Nothing Sent&quot;;   
    exit;   
}   
  
include ('config.php');   
  
//decode JSON data received from AJAX POST request   
$data = json_decode($_POST[&quot;data&quot;]);   
  
foreach($data-&gt;coords as $item) {   
    //Extract X number for panel   
    $coord_X = preg_replace('/[^\d\s]/', '', $item-&gt;coordTop);   
    //Extract Y number for panel   
    $coord_Y = preg_replace('/[^\d\s]/', '', $item-&gt;coordLeft);   
    //escape our values - as good practice   
    $x_coord = mysqli_real_escape_string($link, $coord_X);   
    $y_coord = mysqli_real_escape_string($link, $coord_Y);   
       
    //Setup our Query   
    $sql = &quot;UPDATE coords SET x_pos = '$x_coord', y_pos = '$y_coord'&quot;;   
       
    //Execute our Query   
    mysqli_query($link, $sql) or die(&quot;Error updating Coords :&quot;.mysqli_error());    
}   
  
//Return Success   
echo &quot;success&quot;;   
  
?&gt;
[/php]

Здесь все довольно просто. Первое, что мы делаем – это проверяем, были ли переданы данные в файл. Если это произошло, мы включаем наш файл с настройками config.php и назначаем переменной <code>$data</code> значение <code>json_decode(passed post variable);</code> <a href="http://us.php.net/manual/en/function.json-decode.php">json_decode</a> – это PHP-функция, представленная в PHP 5.2.0, которая позволяет декодировать строку JSON.

Поскольку наша переменная <code>$data</code> содержит массив данных, нам нужно разобрать его на части, чтобы получить нужные значения. Для этого мы пройдемся по массиву <code>$data-&gt;coords () </code>(который был получен из переменной <code>order</code> в JavaScript) и обработаем каждый элемент. В результате, из каждой пары ключ – значение будет создан объект списка, который мы в дальнейшем укажем и создадим переменную для его вывода. При этом мы будем использовать функцию <code>preg_replace</code>, для исключения ненужных символов. Кроме того, мы подготовим наши значения для вставки в базу данных, путем экранирования кавычек, и апострофов, с помощью функции <code>mysqli_real_escape_string</code>. Если все прошло хорошо, нам нужно будет вернуть успешный результат JavaScript.

<a href="http://dreamhelg.ru/wp-content/uploads/2009/11/response.jpg"><img class="aligncenter size-full wp-image-1719" title="response" src="http://dreamhelg.ru/wp-content/uploads/2009/11/response.jpg" alt="response" width="558" height="466" /></a>
<h3>В заключение</h3>
Теперь, когда у нас уже все готово, для того чтобы получить координаты элемента и передать их в PHP для записи, нам понадобится изменить нашу HTML-разметку для отображения позиции элемента. Для этого, мы удалим простую HTML-разметку и создадим ее с помощью PHP:

[php]
&lt;div id=&quot;glassbox&quot;&gt;   
&lt;?php   
        //Create a query to fetch our values from the database     
        $get_coords = mysqli_query($link, &quot;SELECT * FROM coords&quot;);   
        //We then set variables from the * array that is fetched from the database   
        while($row = mysqli_fetch_array($get_coords)) {   
            $x = $row['x_pos'];   
            $y = $row['y_pos'];   
            //then echo our div element with CSS properties to set the left(x) and top(y) values of the element   
            echo '&lt;div id=&quot;element&quot; style=&quot;left:'.$x.'px; top:'.$y.'px;&quot;&gt;&lt;img src=&quot;nettuts.jpg&quot; alt=&quot;Nettuts+&quot; /&gt;Move the Box&lt;p&gt;&lt;/p&gt;&lt;/div&gt;';   
        }              
?&gt;   
&lt;/div&gt;   
&lt;div id=&quot;respond&quot;&gt;&lt;/div&gt;   
[/php]

Здесь мы исполняем простой запрос к базе данных для выбора всех строк из таблицы coords. Затем мы вызываем цикл while, который определяет каждую выбранную нами строчку как <code>$row</code>. Теперь, мы можем назначить переменные равными каждой, индивидуальной строке, полученной из базы данных, и выводим их в соответствующем месте.

<a href="http://nettuts.s3.amazonaws.com/477_drag/source.zip">Скачать архив с примером</a>.

Перевод статьи «<a href="http://net.tutsplus.com/tutorials/javascript-ajax/simple-draggable-element-persistence-with-jquery/">Simple Draggable Element Persistence with jQuery</a>», автор <strong>Dustin Blake</strong>]]></description>
		<wfw:commentRss>http://dreamhelg.ru/2009/11/simple-draggable-element-with-jquery/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Красивая форма обратной связи на основе AJAX</title>
		<link>http://dreamhelg.ru/2009/11/fancy-ajax-contact-form/</link>
		<comments>http://dreamhelg.ru/2009/11/fancy-ajax-contact-form/#comments</comments>
		<pubDate>Fri, 13 Nov 2009 08:56:14 +0000</pubDate>
		<dc:creator>dreamhelg</dc:creator>
				<category><![CDATA[общая]]></category>
		<category><![CDATA[переводы]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://dreamhelg.ru/?p=1690</guid>
		<description><![CDATA[<p><img width="200" height="150" src="http://dreamhelg.ru/wp-content/uploads/2009/11/home.jpg" class="attachment-200x200 wp-post-image" alt="home" title="home" /></p>Предоставление посетителям сайта простого и надежного средства обратной связи –  это важнейшая часть любого веб-проекта. Наиболее простым и часто используемым каналом обратной связи - являются контактные формы. Посмотреть результат можно <a href="http://dreamhelg.ru/demo/contactform/demo.php">здесь</a>.<span id="more-1690"></span>

В сегодняшней статье, мы создадим <strong>форму обратной связи  на аяксе</strong>, с использованием современных техник веб-разработки.  Для этого мы будем использовать PHP, CSS и jQuery в виде нескольких плагинов. Плагин <a href="http://www.position-absolute.com/articles/jquery-form-validator-because-form-validation-is-a-mess/">formValidator</a> будем использовать для проверки введенных значений, а с помощью плагина <a href="http://www.dfc-e.com/metiers/multimedia/opensource/jqtransform/">jQTransform</a>, будем стилизовать текстовые поля и кнопки нашей формы. В дополнение, мы будем использовать класс <a href="http://sourceforge.net/projects/phpmailer/">PHPMailer</a> для отправки на почту введенных данных.

Кроме того, наша форма будет прекрасно работать даже с выключенным JS.

<em>*Для нормальной работы примера, вам понадобится <strong>PHP5</strong></em>
<h3>Шаг 1 – XHTML</h3>
Сначала нам понадобится XHTML-разметка для формы.

<strong>demo.php</strong>

[html]
&lt;div id=&quot;main-container&quot;&gt;	&lt;!-- The main container element --&gt;

&lt;div id=&quot;form-container&quot;&gt;	&lt;!-- The form container --&gt;

&lt;h1&gt;Fancy Contact Form&lt;/h1&gt;	&lt;!-- Headings --&gt;
&lt;h2&gt;Drop us a line and we will get back to you&lt;/h2&gt;

&lt;form id=&quot;contact-form&quot; name=&quot;contact-form&quot; method=&quot;post&quot; action=&quot;submit.php&quot;&gt;	&lt;!-- The form, sent to submit.php --&gt;

&lt;table width=&quot;100%&quot; border=&quot;0&quot; cellspacing=&quot;0&quot; cellpadding=&quot;5&quot;&gt;

&lt;tr&gt;
&lt;td width=&quot;18%&quot;&gt;&lt;label for=&quot;name&quot;&gt;Name&lt;/label&gt;&lt;/td&gt;	&lt;!-- Text label for the input field --&gt;
&lt;td width=&quot;45%&quot;&gt;&lt;input type=&quot;text&quot; class=&quot;validate[required,custom[onlyLetter]]&quot; name=&quot;name&quot; id=&quot;name&quot; value=&quot;&lt;?=$_SESSION['post']['name']?&gt;&quot; /&gt;&lt;/td&gt;
&lt;!-- We are using session to prevent losing data between page redirects --&gt;

&lt;td width=&quot;37%&quot; id=&quot;errOffset&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;label for=&quot;email&quot;&gt;Email&lt;/label&gt;&lt;/td&gt;
&lt;td&gt;&lt;input type=&quot;text&quot; class=&quot;validate[required,custom[email]]&quot; name=&quot;email&quot; id=&quot;email&quot; value=&quot;&lt;?=$_SESSION['post']['email']?&gt;&quot; /&gt;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;label for=&quot;subject&quot;&gt;Subject&lt;/label&gt;&lt;/td&gt;

&lt;!-- This select is being replaced entirely by the jqtransorm plugin --&gt;

&lt;td&gt;&lt;select name=&quot;subject&quot; id=&quot;subject&quot;&gt;
&lt;option value=&quot;&quot; selected=&quot;selected&quot;&gt; - Choose -&lt;/option&gt;
&lt;option value=&quot;Question&quot;&gt;Question&lt;/option&gt;
&lt;option value=&quot;Business proposal&quot;&gt;Business proposal&lt;/option&gt;
&lt;option value=&quot;Advertisement&quot;&gt;Advertising&lt;/option&gt;
&lt;option value=&quot;Complaint&quot;&gt;Complaint&lt;/option&gt;
&lt;/select&gt;          &lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&lt;label for=&quot;message&quot;&gt;Message&lt;/label&gt;&lt;/td&gt;
&lt;td&gt;&lt;textarea name=&quot;message&quot; id=&quot;message&quot; class=&quot;validate[required]&quot; cols=&quot;35&quot; rows=&quot;5&quot;&gt;&lt;?=$_SESSION['post']['message']?&gt;&lt;/textarea&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;label for=&quot;captcha&quot;&gt;&lt;?=$_SESSION['n1']?&gt; + &lt;?=$_SESSION['n2']?&gt; =&lt;/label&gt;&lt;/td&gt;

&lt;!-- A simple captcha math problem --&gt;

&lt;td&gt;&lt;input type=&quot;text&quot; class=&quot;validate[required,custom[onlyNumber]]&quot; name=&quot;captcha&quot; id=&quot;captcha&quot; /&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;!-- These input buttons are being replaced with button elements --&gt;
&lt;td colspan=&quot;2&quot;&gt;&lt;input type=&quot;submit&quot; name=&quot;button&quot; id=&quot;button&quot; value=&quot;Submit&quot; /&gt;
&lt;input type=&quot;reset&quot; name=&quot;button2&quot; id=&quot;button2&quot; value=&quot;Reset&quot; /&gt;
&lt;?=$str?&gt;

&lt;!-- $str contains the error string if the form is used with JS disabled --&gt;

&lt;img id=&quot;loading&quot; src=&quot;img/ajax-load.gif&quot; width=&quot;16&quot; height=&quot;16&quot; alt=&quot;loading&quot; /&gt;
&lt;!-- the rotating gif animation, hidden by default --&gt;
&lt;/td&gt;&lt;/tr&gt;

&lt;/table&gt;
&lt;/form&gt;

&lt;?=$success?&gt;
&lt;!-- The $success variable contains the message that is shown if JS is disabled and the form is submitted successfully --&gt;

&lt;/div&gt;
&lt;/div&gt;	&lt;!-- closing the containers --&gt;
[/html]

Как вы могли заметить в строке 8, обрабатывать нашу форму будет файл <strong>submit.php</strong>. Мы будем использовать этот файл в обоих случаях – как для обычной отправки формы (для посетителей с выключенным JS), так и для аяксовой отправки формы. Это позволит легко обновлять код, без необходимости объединять изменения между файлами.

Далее, мы можете видеть, что мы используем массив <strong>$_SESSION</strong> для заполнения текстовых полей значениями. Это делается для того, чтобы данные не потерялись во время перенаправления страницы, которое происходит во время отправки формы в <strong>submit.php</strong>.

Другой важный аспект – это классы, назначенный текстовым полям – <strong>classs=”validate[required,custom[onlyLetter]]”</strong>. Эти классы используются плагином валидации для определения правил проверки введенных значений для каждого текстового поля. В нашем примере, мы указываем, что поле обязательное, и разрешено вводить только буквы.

Существует множество доступных правил валидации, вы можете узнать о них на домашней странице плагина.

Теперь взгляните, как будет выглядеть наша форма, с применением плагина <strong>JQtransform</strong>.

<a href="http://dreamhelg.ru/wp-content/uploads/2009/11/1.jpg"><img class="aligncenter size-full wp-image-1694" title="1" src="http://dreamhelg.ru/wp-content/uploads/2009/11/1.jpg" alt="1" width="433" height="468" /></a>
<h3>Шаг 2 – jQuery</h3>
МЫ используем два плагина jQuery – <strong>jQtransform</strong> для стилизации элементов формы, и <strong>formValidator</strong> для проверки введенных значений на клиентской стороне.

Очень важно помнить, что кроме клиентской стороны, введенные данные всегда нужно проверять на серверной стороне.

Итак, для начала нам нужно подключить все необходимые библиотеки.

<strong>demo.php</strong>

[php]
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;jqtransformplugin/jqtransform.css&quot; /&gt;
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;formValidator/validationEngine.jquery.css&quot; /&gt;
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;demo.css&quot; /&gt;

&lt;?=$css?&gt; &lt;!-- Special CSS rules, created by PHP --&gt;

&lt;script type=&quot;text/javascript&quot; src=&quot;http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;jqtransformplugin/jquery.jqtransform.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;formValidator/jquery.validationEngine.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;script.js&quot;&gt;&lt;/script&gt;
[/php]

Указанный выше код расположен в секции <em>head</em>, файла <strong>demo.php</strong>. Сначала мы подключаем CSS-файлы, используемые обоими плагинами, а затем уже библиотеку JQuery и плагины. Возможно, вас заинтересовала строка 5 – это специальный набор CSS-правил, который мы создадим с помощью PHP, для отображения подтверждающего сообщения, как вы увидите в дальнейшем.

Теперь, давайте посмотрим на наш файл <strong>script.js</strong>.

<strong>script.js</strong>

[javascript]
$(document).ready(function(){
	/* after the page has finished loading */

	$('#contact-form').jqTransform();
	/* transform the form using the jqtransform plugin */

	$(&quot;button&quot;).click(function(){

		$(&quot;.formError&quot;).hide();
		/* hide all the error tooltips */
	});

	var use_ajax=true;
	$.validationEngine.settings={};
	/* initialize the settings object for the formValidation plugin */

	$(&quot;#contact-form&quot;).validationEngine({	/* create the form validation */
		inlineValidation: false,
		promptPosition: &quot;centerRight&quot;,
		success :  function(){use_ajax=true},	/* if everything is OK enable AJAX */
		failure : function(){use_ajax=false}	/* in case of validation failure disable AJAX */
	 })

	$(&quot;#contact-form&quot;).submit(function(e){

			if(!$('#subject').val().length)
			{
				$.validationEngine.buildPrompt(&quot;.jqTransformSelectWrapper&quot;,&quot;* This field is required&quot;,&quot;error&quot;)
				/* a custom validation tooltip, using the buildPrompt method */

				return false;
			}

			if(use_ajax)
			{
				$('#loading').css('visibility','visible');
				/* show the rotating gif */

				$.post('submit.php',$(this).serialize()+'&amp;ajax=1',
				/* using jQuery's post method to send data */

				function(data){
					if(parseInt(data)==-1)
						$.validationEngine.buildPrompt(&quot;#captcha&quot;,&quot;* Wrong verification number!&quot;,&quot;error&quot;);
						/* if there is an error, build a custom error tooltip for the captcha */
					else
					{
						$(&quot;#contact-form&quot;).hide('slow').after('&lt;h1&gt;Thank you!&lt;/h1&gt;');
						/* show the confirmation message */
					}

					$('#loading').css('visibility','hidden');
					/* hide the rotating gif */
				});
			}

e.preventDefault();	/* stop the default form submit */
})

});
[/javascript]

Весь блок скрипта выполняется внутри метода <strong>$(document).ready</strong>, который гарантирует нам, свое исполнение, только после окончания загрузки страницы.

Далее, мы используем метод <strong>jqTransform()</strong>, который определен в плагине <strong>jqtransform</strong>. Он переделывает и стилизует все элементы формы (тестовые поля, кнопки и др.)

Элемент <em>select</em> заменяется набором дивов и ссылок. Это выглядит здорово, однако влечет за собой некоторые проблемы с плагином валидации, в связи с чем, тултип для селекта нам придется сделать вручную.

После этого, в строке 7, вешаем обработчик событий на нажатие кнопки в нижней части формы, с одной строкой кода, которая прячет отображаемые тултипы с сообщениями об ошибках. Это для того, чтобы страница правильно обновлялась, и подсказки не оставались на странице, если пользователь ввел правильные данные.

Далее, мы инициализируем  плагин <strong>formValidation</strong>, с помощью метода <strong>validationEngine() </strong>и в строке 24 описываем событие формы <strong>onsubmit</strong>. Пара моментов, на которые стоит обратить внимание здесь – отдельный тултип в строке 28, и дополнительный параметр <strong>ajax=1</strong>, в строке 39. Этот параметр использует файл <strong>submit.php</strong>, для того чтобы определить, передан ли запрос с помощью аякса или получен непосредственно через отправку формы.

Также, обратите внимание, что мы используем специальную переменную <strong>use_ajax</strong>, для предотвращения работы аякса, если форма не прошла проверку.

<a href="http://dreamhelg.ru/wp-content/uploads/2009/11/2.png"><img class="aligncenter size-full wp-image-1695" title="2" src="http://dreamhelg.ru/wp-content/uploads/2009/11/2.png" alt="2" width="600" height="460" /></a>
<h3>Шаг 3 – CSS</h3>
Все наши CSS-правила описаны в файле <strong>demo.css</strong>

<strong>demo.css</strong>

[css]
body,h1,h2,h3,p,quote,small,form,input,ul,li,ol,label{
	/* reset some of the page elements */
	margin:0px;
	padding:0px;
}

body{
	color:#555555;
	font-size:13px;
	background: url(img/dark_wood_texture.jpg) #282828;
	font-family:Arial, Helvetica, sans-serif;
}

.clear{
	clear:both;
}

#main-container{
	width:400px;
	margin:30px auto;
}

#form-container{
	background-color:#f5f5f5;
	padding:15px;

	/* rounded corners */
	-moz-border-radius:12px;
	-khtml-border-radius: 12px;
	-webkit-border-radius: 12px;
	border-radius:12px;
}

td{
	/* prevent multiline text */
	white-space:nowrap;
}

a, a:visited {
	color:#00BBFF;
	text-decoration:none;
	outline:none;
}

a:hover{
	text-decoration:underline;
}

h1{
	color:#777777;
	font-size:22px;
	font-weight:normal;
	text-transform:uppercase;
	margin-bottom:5px;
}

h2{
	font-weight:normal;
	font-size:10px;

	text-transform:uppercase;

	color:#aaaaaa;
	margin-bottom:15px;

	border-bottom:1px solid #eeeeee;
	margin-bottom:15px;
	padding-bottom:10px;
}

label{
	text-transform:uppercase;
	font-size:10px;
	font-family:Tahoma,Arial,Sans-serif;
}

textarea{
	color:#404040;
	font-family:Arial,Helvetica,sans-serif;
	font-size:12px;
}

td &gt; button{
	/* A special CSS selector that targets non-IE6 browsers */
	text-indent:8px;
}

.error{
	/* this class is used if JS is disabled */
	background-color:#AB0000;
	color:white;
	font-size:10px;
	font-weight:bold;
	margin-top:10px;
	padding:10px;
	text-transform:uppercase;
	width:300px;
}

#loading{
	/* the loading gif is hidden on page load */
	position:relative;
	bottom:9px;
	visibility:hidden;
}

.tutorial-info{
	color:white;
	text-align:center;
	padding:10px;
	margin-top:10px;
}
[/css]

Обратите внимание на строку 85. Это правило делает кнопки шире, но, к сожалению это плохо выглядит в IE6. Поэтому мы используем специальный CSS-селектор, который игнорируется IE6, но отлично понимают остальные браузеры.

Теперь, все что нам осталось – это PHP.

<a href="http://dreamhelg.ru/wp-content/uploads/2009/11/3.jpg"><img class="aligncenter size-full wp-image-1696" title="3" src="http://dreamhelg.ru/wp-content/uploads/2009/11/3.jpg" alt="3" width="555" height="319" /></a>
<h3>Шаг 4 – PHP</h3>
Сначала давайте рассмотрим код в начале файла <strong>demo.php</strong>

<strong>demo.php</strong>

[php]
session_name(&quot;fancyform&quot;);
session_start();

$_SESSION['n1'] = rand(1,20);	/* generate the first number */
$_SESSION['n2'] = rand(1,20);	/* then the second */
$_SESSION['expect'] = $_SESSION['n1']+$_SESSION['n2'];	/* the expected result */

/* the code below is used if JS has been disabled by the user */
$str='';
if($_SESSION['errStr'])	/* if submit.php returns an error string in the session array */
{
	$str='&lt;div class=&quot;error&quot;&gt;'.$_SESSION['errStr'].'&lt;/div&gt;';
	unset($_SESSION['errStr']);	/* will be shown only once */
}

$success='';
if($_SESSION['sent'])
{
	$success='&lt;h1&gt;Thank you!&lt;/h1&gt;';	/* the success message */

	$css='&lt;style type=&quot;text/css&quot;&gt;#contact-form{display:none;}&lt;/style&gt;';
	/* a special CSS rule that hides our form */

	unset($_SESSION['sent']);
}
[/php]

Как видите, мы используем массив <strong>$_SESSION</strong> для хранения двух случайных чисел и ожидаемого результата. Это будет использоваться в дальнейшем, файлом <strong>submit.php</strong>, для подтверждения того, что капча решена.

Другой интересный момент находится в строке 21, где мы описываем простой CSS-класс. Фактически здесь, мы скрываем форму, и отображаем сообщение об успешной отправке, если у пользователя отключен JS.

<strong>submit.php</strong>

[php]
require &quot;phpmailer/class.phpmailer.php&quot;;

session_name(&quot;fancyform&quot;);	/* starting the session */
session_start();

foreach($_POST as $k=&gt;$v)
{
	/* if magic_quotes is enabled, strip the post array */
	if(ini_get('magic_quotes_gpc'))
	$_POST[$k]=stripslashes($_POST[$k]);

	$_POST[$k]=htmlspecialchars(strip_tags($_POST[$k]));
	/* escape the special chars */
}

$err = array();

/* some error checks */
if(!checkLen('name'))
	$err[]='The name field is too short or empty!';

if(!checkLen('email'))
	$err[]='The email field is too short or empty!';
else if(!checkEmail($_POST['email']))
	$err[]='Your email is not valid!';

if(!checkLen('subject'))
	$err[]='You have not selected a subject!';

if(!checkLen('message'))
	$err[]='The message field is too short or empty!';

/* compare the received captcha code to the one in the session array */
if((int)$_POST['captcha'] != $_SESSION['expect'])
	$err[]='The captcha code is wrong!';

/* if there are errors */
if(count($err))
{
	/* if the form was submitted via AJAX */
	if($_POST['ajax'])
	{
		echo '-1';
	}

	/* else fill the SESSION array and redirect back to the form */
	else if($_SERVER['HTTP_REFERER'])
	{
		$_SESSION['errStr'] = implode('&lt;br /&gt;',$err);
		$_SESSION['post']=$_POST;

		header('Location: '.$_SERVER['HTTP_REFERER']);
	}

	exit;
}

/* the email body */
$msg=
'Name:	'.$_POST['name'].'&lt;br /&gt;
Email:	'.$_POST['email'].'&lt;br /&gt;
IP:	'.$_SERVER['REMOTE_ADDR'].'&lt;br /&gt;&lt;br /&gt;

Message:&lt;br /&gt;&lt;br /&gt;

'.nl2br($_POST['message']).'

';

$mail = new PHPMailer();	/* using PHPMailer */
$mail-&gt;IsMail();

$mail-&gt;AddReplyTo($_POST['email'], $_POST['name']);
$mail-&gt;AddAddress($emailAddress);
$mail-&gt;SetFrom($_POST['email'], $_POST['name']);
$mail-&gt;Subject = &quot;A new &quot;.mb_strtolower($_POST['subject']).&quot; from &quot;.$_POST['name'].&quot; | contact form feedback&quot;;

$mail-&gt;MsgHTML($msg);

$mail-&gt;Send();

unset($_SESSION['post']);	/* unsetting */

/* the form was successfully sent */
if($_POST['ajax'])
{
	echo '1';
}
else
{
	$_SESSION['sent']=1;

	if($_SERVER['HTTP_REFERER'])
		header('Location: '.$_SERVER['HTTP_REFERER']);

	exit;
}

/* some helpful functions */
function checkLen($str,$len=2)
{
	return isset($_POST[$str]) &amp;&amp; mb_strlen(strip_tags($_POST[$str]),&quot;utf-8&quot;) &gt; $len;
}

function checkEmail($str)
{
	return preg_match(&quot;/^[\.A-z0-9_\-\+]+[@][A-z0-9_\-]+([.][A-z0-9_\-]+)+[A-z]{1,4}$/&quot;, $str);
}
[/php]

Обратите внимание как мы проверяем переменную <strong>$_POST[‘ajax’]</strong> на предмет установки и правильной работы. Как вы наверное помните, мы устанавливаем ее ранее, в файле <strong>script.js</strong>, для определения используется ли аякс для извлечения данных.

Две переменные массива <strong>$_SESSION</strong> <strong>errStr</strong> и <strong>post</strong> используются для совместного использования данных между формой и файлом <strong>submit.php</strong>, в случае выключенного JS. Здесь переменная <strong>post</strong> содержит отправленный нами массив <strong>$_POST</strong> и используется для заполнения полей формы, после того как пользователь перенаправляется обратно.

На этом работа над нашей формой обратной связи подошла к концу.

Пример рабочий, за исключением одного маленького недоразумения. Плагин formValidation, создан с целью проводить валидацию только английских символов, так что если вы попытаетесь написать имя по-русски, он выдаст ошибку о том, что нужно вводить только буквы. К счастью это решается путем замены регулярного выражения в файле <strong>jquery.validationEngine.js</strong>. Найдите строчки:

[javascript]
&quot;onlyLetter&quot;:{
	&quot;regex&quot;:&quot;/^[a-zA-Z\ \']+$/&quot;,
}	
[/javascript]

и замените на следующую:

[javascript]
&quot;onlyLetter&quot;:{
	&quot;regex&quot;:&quot;/^[a-zA-Zа-яА-Я' ]+$/&quot;,
}	
[/javascript]

После этого, скрипт перестанет игнорировать русские символы.

<a href="http://dreamhelg.ru/wp-content/uploads/2009/11/contactform.zip">Скачать архив с примером</a>.

<strong>В связи с бесконечными вопросами, специально, отдельно сообщаю: настройка адреса email на который производится отправка писем, находится в файле submit.php, в самом начале файла, выглядит вот так:
</strong>
[php]
/* config start */

$emailAddress = '';

/* config end */
[/php]

Перевод статьи "<a href="http://tutorialzine.com/2009/09/fancy-contact-form/">A Fancy AJAX Contact Form</a>", автор <strong>Martin</strong>]]></description>
		<wfw:commentRss>http://dreamhelg.ru/2009/11/fancy-ajax-contact-form/feed/</wfw:commentRss>
		<slash:comments>98</slash:comments>
		</item>
		<item>
		<title>Интерактивная корзина на основе AJAX, PHP и JQuery</title>
		<link>http://dreamhelg.ru/2009/09/ajax-based-shopping-cart-with-jquery-and-php/</link>
		<comments>http://dreamhelg.ru/2009/09/ajax-based-shopping-cart-with-jquery-and-php/#comments</comments>
		<pubDate>Thu, 24 Sep 2009 06:26:06 +0000</pubDate>
		<dc:creator>dreamhelg</dc:creator>
				<category><![CDATA[общая]]></category>
		<category><![CDATA[переводы]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://dreamhelg.ru/?p=1419</guid>
		<description><![CDATA[<p><img width="171" height="167" src="http://dreamhelg.ru/wp-content/uploads/2009/09/home1.jpg" class="attachment-200x200 wp-post-image" alt="home" title="home" /></p>"Какая корзина? И почему вдруг корзина?" - возможно удивитесь вы, прочитав заголовок. Так вот, корзина самая обычная - та, которую все мы используем, покупая что-нибудь в интернет-магазине. А опубликовать статью о ее создании, я решила по одной, единственной причине - не смогла устоять перед замечательным и красивым решением.

Не верите? можете посмотреть <a href="http://demo.tutorialzine.com/2009/09/shopping-cart-php-jquery/demo.php">результат</a>. А если вам интересно как это делается, читайте далее.<span id="more-1419"></span>

<h3>Вступление</h3>
В этой статье, мы собираемся создать корзину, работающую на основе технологии Ajax. Все товары будут записываться в базу данных MySQL, данные будут обрабатываться с помощью PHP.

JQuery, будет запускать <strong>Ajax</strong> на странице, кроме этого, плагин <strong><a href="http://craigsworks.com/projects/simpletip/">simpletip</a></strong>, добавит всему процессу интерактивности.

Итак, давайте начнем, скачайте демо-файлы, и начинайте чтение.

<h3>Шаг 1 – База данных MySQL</h3>
Если вы хотите получить рабочую демо-версию, вам понадобится выполнить следующий SQL-запрос в панели управления базой данных (то есть в phpMyAdmin). Этот запрос создаст таблицу, и внесет несколько продуктов. Этот код запроса, также доступен в файле table.sql, в демо-файлах.

<strong>table.sql</strong>

[sql]
CREATE TABLE IF NOT EXISTS `internet_shop` (
  `id` int(6) NOT NULL auto_increment,
  `img` varchar(32) collate utf8_unicode_ci NOT NULL default '',
  `name` varchar(64) collate utf8_unicode_ci NOT NULL default '',
  `description` text collate utf8_unicode_ci NOT NULL,
  `price` double NOT NULL default '0',
  PRIMARY KEY  (`id`),
  UNIQUE KEY `img` (`img`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=7 ;

INSERT INTO `internet_shop` VALUES(1, 'iPod.png', 'iPod', 'The original and popular iPod.', 200);
INSERT INTO `internet_shop` VALUES(2, 'iMac.png', 'iMac', 'The iMac computer.', 1200);
INSERT INTO `internet_shop` VALUES(3, 'iPhone.png', 'iPhone', 'This is the new iPhone.', 400);
INSERT INTO `internet_shop` VALUES(4, 'iPod-Shuffle.png', 'iPod Shuffle', 'The new iPod shuffle.', 49);
INSERT INTO `internet_shop` VALUES(5, 'iPod-Nano.png', 'iPod Nano', 'The new iPod Nano.', 99);
INSERT INTO `internet_shop` VALUES(6, 'Apple-TV.png', 'Apple TV', 'The new Apple TV. Buy it now!', 300);
[/sql]

После этого, вам нужно заполнить данные вашей учетной записи MySQL, в файле <strong>connect.php</strong>.

<h3>Шаг 2 – XHTML</h3>
Сначала мы создадим основную разметку.

<strong>demo.php</strong>

[html]
&lt;div id=&quot;main-container&quot;&gt; &lt;!-- основной контент --&gt;	
&lt;div class=&quot;tutorialzine&quot;&gt;	&lt;!-- заголовок --&gt;

&lt;h1&gt;Корзина&lt;/h1&gt;
&lt;h3&gt;Лучшие товары, по лучшим ценам&lt;/h3&gt;
&lt;/div&gt;

&lt;div class=&quot;container&quot;&gt;  &lt;!-- первая секция - товары --&gt;

&lt;span class=&quot;top-label&quot;&gt;
    &lt;span class=&quot;label-txt&quot;&gt;Товары&lt;/span&gt;  &lt;!-- название секции --&gt;
&lt;/span&gt;

&lt;div class=&quot;content-area&quot;&gt;

&lt;div class=&quot;content drag-desired&quot;&gt;

// php-код, который генерирует товары

&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;   &lt;!-- чистка потока --&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;bottom-container-border&quot;&gt;	&lt;!-- нижняя часть секции --&gt;
&lt;/div&gt;

&lt;/div&gt;	&lt;!-- окончание секции товаров --&gt;

&lt;div class=&quot;container&quot;&gt;	&lt;!-- вторая секция- корзина--&gt;

&lt;span class=&quot;top-label&quot;&gt;
   &lt;span class=&quot;label-txt&quot;&gt;Корзина&lt;/span&gt;	&lt;!-- название секции --&gt;
&lt;/span&gt;

&lt;div class=&quot;content-area&quot;&gt;
  &lt;div class=&quot;content drop-here&quot;&gt;
         &lt;div id=&quot;cart-icon&quot;&gt;
               &lt;img src=&quot;img/Shoppingcart_128x128.png&quot; alt=&quot;shopping cart&quot; class=&quot;pngfix&quot; width=&quot;128&quot; height=&quot;128&quot; /&gt;	&lt;!-- использование класса pngfix--&gt;

                &lt;img src=&quot;img/ajax_load_2.gif&quot; alt=&quot;loading..&quot; id=&quot;ajax-loader&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;	&lt;!-- прелоадер - спрятан по умолчанию, и отображается когда работает AJAX --&gt;
    &lt;/div&gt;

&lt;form name=&quot;checkoutForm&quot; method=&quot;post&quot; action=&quot;order.php&quot;&gt;	&lt;!-- форма --&gt;
    &lt;div id=&quot;item-list&quot;&gt;	&lt;!-- в этот блок мы вставим все товары корзины --&gt;

     &lt;/div&gt;
&lt;/form&gt;	&lt;!-- конец формы --&gt;

&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;	&lt;!-- чистка потока --&gt;

&lt;div id=&quot;total&quot;&gt;&lt;/div&gt;	&lt;!-- здесь расположена общая сумма --&gt;

&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;	&lt;!-- чистка потока --&gt;

&lt;a href=&quot;&quot; onclick=&quot;document.forms.checkoutForm.submit(); return false;&quot; class=&quot;button&quot;&gt;
	Оформить
&lt;/a&gt;	&lt;!-- кнопка отправки заказа, спрятана по умолчанию. обратите внимание на атрибут onclick --&gt;

&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;bottom-container-border&quot;&gt;	&lt;!-- нижняя часть секции --&gt;
&lt;/div&gt;

&lt;/div&gt;&lt;!-- конец основного контейнера --&gt;
[/html]

Как вы могли заметить, из вышеприведенного кода, мы расположили наш контент в двух основных секциях, полностью идентичных с точки зрения XHTML-разметки. В первой колонке мы отображаем все наши продукты, вторая колонка выступает в качестве корзины.

Ниже, вы можете увидеть детальное представление структуры нашей секции товаров.

<img class="aligncenter size-full wp-image-1433" title="scheme" src="http://dreamhelg.ru/wp-content/uploads/2009/09/scheme.jpg" alt="scheme" width="600" height="460" />

Товары, генерируются с помощью нашего PHP-кода, как можно увидеть в строке 18. Мы разберем это подробнее, через несколько минут. Теперь, давайте взглянем, как мы обработаем XHTML-разметку, для получения финального дизайна.
<h3>Шаг 3 – CSS</h3>
В этот раз, CSS-код получился очень длинный, поэтому я разделил его на две части.

<strong>demo.css</strong>

[css]
body,h1,h2,h3,p,td,quote,small,form,input,ul,li,ol,label{
/* сброс первоначальных стилей, для совместимости браузеров */
	margin:0px;
	padding:0px;
	font-family:Arial, Helvetica, sans-serif;
}

body{
	color:#555555;
	font-size:13px;
	background-color:#282828;
}

.clear{	/*  clear-fix хак для чистки потока от флоатов */
	clear:both;
}

#main-container{	/* это основной контейнер, содержащий две секции */
	width:700px;
	margin:20px auto;
}

.container{	/* основной контейнер для секций контента - товаров и корзины */
	margin-bottom:40px;
}

.top-label{	/* внешний span, включающий в себя название секции*/
	background: url(img/label_bg.png) no-repeat;	/* отображение левой части label_bg.png - широкого изображения с закругленными краями */
	display:inline-block;
	margin-left:20px;
	position:relative;
	margin-bottom:-15px;	/* название секции прилегает к верхнему краю секции товаров*/
}

.label-txt{	/* внутренний span - обведен красной рамкой, на рисунке выше*/
	background: url(img/label_bg.png) no-repeat top right;	/* отображение правой части изображения label_bg.png */
	display:inline-block;
	font-size:10px;
	height:36px;
	margin-left:10px;	/* слева оставлено пустое пространство, чтобы отображить фон внешнего span'а */
	padding:12px 15px 0 5px;
	text-transform:uppercase;
}

.content-area{	/* Верхняя часть изображения с закругленными краями, смотрите на рисунке выше */
	background:url(img/container_top.png) no-repeat #fcfcfc;
	padding:15px 20px 0 20px;
}

.content{	/* общий отступ для обеих секций */
	padding:10px;
}

.drag-desired{	/* индивидуально назначенные свойства */
	background:url(img/drag_desired_label.png) no-repeat top right;
	padding:20px;
}

.drop-here{	/* не предназначено для других секций */
	background:url(img/drop_here_label.png) no-repeat top right;
}

.bottom-container-border{	/* нижняя часть закругленной картинки, которая завершает секцию */
	background:url(img/container_bottom.png) no-repeat;
	height:14px;
}

.product{	/* стили для товаров */
	border:2px solid #F5F5F5;
	float:left;
	margin:15px;
	padding:10px;
}

.product img{
	cursor:move;
}

p.descr{
	padding:5px 0;
}

small{
	display:block;
	margin-top:4px;
}

.tooltip{	/* тултипы, которые создаются с помощью плагина simpletip */
	position: absolute;
	top: 0;
	left: 0;
	z-index: 3;
	display: none;

	background-color:#666666;
	border:1px solid #666666;
	color:#fcfcfc;

	padding:10px;

	-moz-border-radius:12px;	/* закругленные углы */
	-khtml-border-radius: 12px;
	-webkit-border-radius: 12px;
	border-radius:12px;
}
[/css]

Обратите внимание на класс tooltip. Он создается автоматически, <strong>плагином simpletip</strong>, но не имеет никаких стилей, по умолчанию. Вот почему, мы назначаем ему стиль здесь. Я использовал свойство <strong>border-radius</strong>, которое еще не поддерживается всеми браузерами, но не принесет сильного ущерба, тем, кто его не поддерживает.

Теперь, давайте взглянем на CSS-стили, для секции корзины.

[css]
#cart-icon{	/* div, который содержит иконку корзины */
	width:128px;
	float:left;
	position:relative;	/* устанавливаем относительное позиционирование, так, чтобы ajax-загрузчик позиционировался по отношению к div*/
}

#ajax-loader{
	position:absolute;	/* абсолютное позиционирование располагает элемент на странице, относительно его родительского элемента, которому назначено относительное позиционирование */
	top:0px;
	left:0px;
	visibility:hidden;
}

#item-list{	/* содержимое корзины будет расположено в этом блоке */
	float:left;
	width:490px;
	margin-left:20px;
	padding-top:15px;
}

a.remove,a.remove:visited{	/* Удаление ссылки */
	color:red;
	font-size:10px;
	text-transform:uppercase;
}

#total{	/* блок, с общей суммой */
	clear:both;
	float:right;
	font-size:10px;
	font-weight:bold;
	padding:10px 12px;
	text-transform:uppercase;
}

#item-list table{	/* каждый товар в корзине, позиционируется внутри блока item-list*/
	background-color:#F7F7F7;
	border:1px solid #EFEFEF;
	margin-top:5px;
	padding:4px;
}

a.button,a.button:visited{	/* Кнопка оформления заказа */
	display:none;

	height:29px;
	width:136px;

	padding-top:15px;
	margin:0 auto;
	overflow:hidden;

	color:white;
	font-size:12px;
	font-weight:bold;
	text-align:center;
	text-transform:uppercase;

	background:url(img/button.png) no-repeat center top;	/* отображаем только верхнюю часть фонового изображения */
}

a.button:hover{
	background-position:bottom;	/* при наведении, мы показываем нижнюю часть фоногового изображения */
	text-decoration:none;
}

/* Несколько менее интересных стилей */

a, a:visited {
	color:#00BBFF;
	text-decoration:none;
	outline:none;
}

a:hover{
	text-decoration:underline;
}

h1{
	font-size:28px;
	font-weight:bold;
	font-family:&quot;Trebuchet MS&quot;,Arial, Helvetica, sans-serif;
}

h2{
	font-weight:normal;
	font-size:20px;

	color:#666666;
	text-indent:30px;
	margin:20px 0;
}

.tutorialzine h1{
	color:white;
	margin-bottom:10px;
	font-size:48px;
}

.tutorialzine h3{
	color:#F5F5F5;
	font-size:10px;
	font-weight:bold;
	margin-bottom:30px;
	text-transform:uppercase;
}

.tutorial-info{
	color:white;
	text-align:center;
	padding:10px;
	margin-top:-20px;
}
[/css]

Любой разработчик скажет нам, что здесь мы кое-что упустили. Как вы, наверное, догадались – специальные процедуры лечения для IE6.

Лично я, планирую в скором времени прекратить поддержку IE6 во всех своих проектах – если бы не IE6, вышеприведенный код, был бы на четверть короче, и мне не пришлось бы тратить столько времени на его отладку.

Но, в любом случае, вот, что нам нужно, чтобы IE6 понимал, то, что мы от него хотим:

<strong>demo.php</strong>

[html]
&lt;!--[if lt IE 7]&gt;
&lt;style type=&quot;text/css&quot;&gt;
	.pngfix { behavior: url(pngfix/iepngfix.htc);}	/* this is a special htc file that fixes the IE6 transparency issues */
	.tooltip{width:200px;};	/* provide a default width for the tooltips */
&lt;/style&gt;
&lt;![endif]--&gt;
[/html]

Отлично. Теперь, давайте взглянем на окончательный вариант PHP.

<img class="aligncenter size-full wp-image-1434" title="cart" src="http://dreamhelg.ru/wp-content/uploads/2009/09/cart.jpg" alt="cart" width="588" height="262" />

<h3>Шаг 4 – PHP</h3>
Мы используем PHP несколькими способами и в разных местах. Для начала, давайте посмотрим, как формируется список товаров на главной странице.

<strong>demo.php</strong>

[php]
&lt;?php
	$result = mysql_query(&quot;SELECT * FROM internet_shop&quot;);	// выбираем все товары
		while($row=mysql_fetch_assoc($result))
		{
			echo '&lt;div class=&quot;product&quot;&gt;&lt;img src=&quot;img/products/'.$row['img'].'&quot; alt=&quot;'.htmlspecialchars($row['name']).'&quot; width=&quot;128&quot; height=&quot;128&quot; class=&quot;pngfix&quot; /&gt;&lt;/div&gt;';

?&gt;
[/php]

Далее, в файле tips.php, мы снова используем PHP, для того чтобы передать в качестве параметра имя файла картинки, проверяя какой товар ассоциируется с этим изображением, и выводим подсказку в виде HTML. Это позднее, будет использоваться плагином simpletip.

<strong>ajax/tips.php</strong>

[php]
&lt;?php
define('INCLUDE_CHECK',1);
require &quot;../connect.php&quot;;

if(!$_POST['img']) die(&quot;Нет таких товаров!&quot;);

$img=mysql_real_escape_string(end(explode('/',$_POST['img'])));

$row=mysql_fetch_assoc(mysql_query(&quot;SELECT * FROM internet_shop WHERE img='&quot;.$img.&quot;'&quot;));

if(!$row) die(&quot;Нет таких товаров!&quot;);

echo '&lt;strong&gt;'.$row['name'].'&lt;/strong&gt;
&lt;p class=&quot;descr&quot;&gt;'.$row['description'].'&lt;/p&gt;
&lt;strong&gt;price: $'.$row['price'].'&lt;/strong&gt;
&lt;small&gt;Для того, чтобы купить, просто перетащите его в коризну&lt;/small&gt;';

 ;?&gt;
[/php]

Кроме этого, мы используем PHP для получения данных, необходимых для добавления товаров в корзину. Разница в том, что в этот раз мы получаем данные в качестве JSON (javascript-объекта).

<strong>ajax/addtocart.php</strong>

[php]
&lt;?php
define('INCLUDE_CHECK',1);
require &quot;../connect.php&quot;;

if(!$_POST['img']) die(&quot;Нет таких товаров!&quot;);

$img=mysql_real_escape_string(end(explode('/',$_POST['img'])));
$row=mysql_fetch_assoc(mysql_query(&quot;SELECT * FROM internet_shop WHERE img='&quot;.$img.&quot;'&quot;));

echo '{status:1,id:'.$row['id'].',price:'.$row['price'].',txt:\'\
\
&lt;table width=&quot;100%&quot; id=&quot;table_'.$row['id'].'&quot;&gt;\
&lt;tr&gt;\
&lt;td width=&quot;60%&quot;&gt;'.$row['name'].'&lt;/td&gt;\
&lt;td width=&quot;10%&quot;&gt;$'.$row['price'].'&lt;/td&gt;\
&lt;td width=&quot;15%&quot;&gt;&lt;select name=&quot;'.$row['id'].'_cnt&quot; id=&quot;'.$row['id'].'_cnt&quot; onchange=&quot;change('.$row['id'].');&quot;&gt;\
&lt;option value=&quot;1&quot;&gt;1&lt;/option&gt;\
&lt;option value=&quot;2&quot;&gt;2&lt;/option&gt;\
&lt;option value=&quot;3&quot;&gt;3&lt;/option&gt;&lt;/slect&gt;\
\
&lt;/td&gt;\
&lt;td width=&quot;15%&quot;&gt;&lt;a href=&quot;#&quot; onclick=&quot;remove('.$row['id'].');return false;&quot; class=&quot;remove&quot;&gt;удалить&lt;/a&gt;&lt;/td&gt;\
&lt;/tr&gt;\
&lt;/table&gt;\'}';

?&gt;
[/php]

Полученный объект имеет свойства status, id, price и txt. Все они используются AJAX-функциями, как вы скоро убедитесь.

Обратите внимание на то, что я заканчиваю каждую строку обратным слешем. Это сделано потому, что JavaScript не поддерживает множественные строчки.

И последний файл, в котором мы используем PHP – это order.php, который используется для обработки заказа. Сейчас, он просто выводит ваш заказ. Мы можете изменить его, включив форму обратной связи, функции платежных систем, или что-нибудь еще, что позволит превратить этот пример в функциональный онлайн-магазин.

<strong>order.php</strong>

[php]
&lt;?php

define('INCLUDE_CHECK',1);
require &quot;connect.php&quot;;

if(!$_POST)	// если данные не были отправлены в форму
{
	if($_SERVER['HTTP_REFERER'])	// редирект
	header('Location : '.$_SERVER['HTTP_REFERER']);
	exit;	// и выход
}

?&gt;

&lt;!-- XHTML код.. --&gt;

&lt;?php		
$cnt = array();
$products = array();
$total = 0;
foreach($_POST as $key=&gt;$value)
{
	$key=(int)str_replace('_cnt','',$key);
	$products[]=$key;	// запись ID товара в массив
	$cnt[$key]=$value;	// создание пары ключ-значение, где для каждого ID товара есть соответствующее значение количества товаров
 }

$result = mysql_query(&quot;SELECT * FROM internet_shop WHERE id IN(&quot;.join($products,',').&quot;)&quot;);	// выбор всех товаров с помощью функции IN()

if(!mysql_num_rows($result))	// товары не найдены
{
	echo '&lt;h1&gt;При оформлении заказа возникла ошибка!&lt;/h1&gt;';
}
else
{
	echo '&lt;h1&gt;Ваш заказ:&lt;/h1&gt;';
	while($row=mysql_fetch_assoc($result))
	{
		echo '&lt;h2&gt;'.$cnt[$row['id']].' x '.$row['name'].'&lt;/h2&gt;';
		$total+=$cnt[$row['id']]*$row['price'];
	}

	echo '&lt;h1&gt;Всего: $'.$total.'&lt;/h1&gt;';
}

?&gt;

[/php]

На этом, часть PHP закончена. Все, что нам осталось сделать, это добавить немного магии jQuery.

<img class="aligncenter size-full wp-image-1435" title="checkout" src="http://dreamhelg.ru/wp-content/uploads/2009/09/checkout.jpg" alt="checkout" width="585" height="268" />
<h3>Шаг 5 – JQuery</h3>
Поскольку мы будем использовать jQuery в полном объеме, нам понадобится подключить библиотеку jQuery UI, так же, как и основную.

[html]
&lt;script type=&quot;text/javascript&quot; src=&quot;http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;simpletip/jquery.simpletip-1.3.1.pack.js&quot;&gt;&lt;/script&gt; &lt;!-- плагин к jQuery simpletip --&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;script.js&quot;&gt;&lt;/script&gt; &lt;!-- наш script.js --&gt;
[/html]

Теперь, мы можем продолжить с нашим скриптом.

<strong>script.js</strong>

[javascript]
var purchased=new Array();	//массив, содержащий все товары, которые мы приобрели
var totalprice=0;	//цена

$(document).ready(function(){

$('.product').simpletip({	//используем плагин simpletip

	offset:[40,0],
	content:'&lt;img style=&quot;margin:10px;&quot; src=&quot;img/ajax_load.gif&quot; alt=&quot;loading&quot; /&gt;',	// контент по умолчанию
	onShow: function(){

		var param = this.getParent().find('img').attr('src');
		// fix для IE6
		if($.browser.msie &amp;&amp; $.browser.version=='6.0')
		{
			param = this.getParent().find('img').attr('style').match(/src=\&quot;([^\&quot;]+)\&quot;/);
			param = param[1];
		}

		// после того как отображена подсказка, загружаем файл tips.php и передаем название изображения в качестве параметра
		this.load('ajax/tips.php',{img:param});
	} 

});

$(&quot;.product img&quot;).draggable({	// разрешаем перетаскивание картинок товаров

containment: 'document',
opacity: 0.6,
revert: 'invalid',
helper: 'clone',
zIndex: 100

});

$(&quot;div.content.drop-here&quot;).droppable({	// разрешаем выгружать товары в корзину

		drop:
			function(e, ui)
			{
				var param = $(ui.draggable).attr('src');
				// IE6 fix
				if($.browser.msie &amp;&amp; $.browser.version=='6.0')
				{
					param = $(ui.draggable).attr('style').match(/src=\&quot;([^\&quot;]+)\&quot;/);
					param = param[1];
				}

				addlist(param);	// специальная функция addlist - смотрите ниже
			}

});


});
[/javascript]

Основная идея в том, что мы используем атрибут изображения <strong>src</strong>, в качестве уникального ключа, который передается PHP. Каждый товар в базе данных имеет поле c именем файла, что позволяет нам найти нужный товар по его картинке.

Этот блок кода выполняется после того как страница полностью загрузилась, так, что мы уверены, что все элементы на странице инициализированы.

Ниже представлена вторая часть кода script.js.

[javascript]
function addlist(param)
{
	// функция addlist добавляет товар в корзину

	$.ajax({	// посылаем ajax-request в addtocart.php
	type: &quot;POST&quot;,
	url: &quot;ajax/addtocart.php&quot;,
	data: 'img='+encodeURIComponent(param),	// картинка товара в качестве параметра
	dataType: 'json',	// ждем json
	beforeSend: function(x){$('#ajax-loader').css('visibility','visible');},	// отображаем прелоадер
	success: function(msg){

		$('#ajax-loader').css('visibility','hidden');	// прячем прелоадер
		if(parseInt(msg.status)!=1)
		{
			return false;	// если обнаружена ошибка, возвращаем false
		}
		else
		{
			var check=false;
			var cnt = false;

			for(var i=0; i&lt;purchased.length;i++)
			{
				if(purchased[i].id==msg.id)	// ищем, не покупали ли мы этот товар ранее
				{
					check=true;
					cnt=purchased[i].cnt;

					break;
				}
			}

			if(!cnt)	// если еще не покупали, или удалили из покупок, то вставляем в корзину
				$('#item-list').append(msg.txt);

			if(!check)	// если еще не купили, вставляем в массив покупок
			{
				purchased.push({id:msg.id,cnt:1,price:msg.price});
			}

			else	// иначе, если купили
			{
				if(cnt&gt;=3) return false;	// больше 3 товаров

				purchased[i].cnt++;
				$('#'+msg.id+'_cnt').val(purchased[i].cnt);	// обновляем select box
			}

			totalprice+=msg.price;	// пересчитываем стоимость recalculate the price
			update_total();	// обновляем блок общей стоимости
		}

		$('.tooltip').hide();	// прячем подсказку (иногда она остается после перетаскивания)

	}
	});
}

function findpos(id)	// полезная функция, помогающая найти поизицию товара в массиве, возвращаяя ее
{
	for(var i=0; i&lt;purchased.length;i++)
	{
		if(purchased[i].id==id)
			return i;
	}

	return false;
}

function remove(id)	// удаляем товары из корзины
{
	var i=findpos(id);	// находим их позицию в массиве

	totalprice-=purchased[i].price*purchased[i].cnt;	// пересчитываем стоимость
	purchased[i].cnt = 0;	// сбрасываем счетчик

	$('#table_'+id).remove();	// удаляем их из таблицы
	update_total();	// обновляем счетчик общей стоимости на странице
}

function change(id)	// вызывается когда мы изменям количество товаров в селекте
{
	var i=findpos(id);

	totalprice+=(parseInt($('#'+id+'_cnt').val())-purchased[i].cnt)*purchased[i].price;

	purchased[i].cnt=parseInt($('#'+id+'_cnt').val());
	update_total();
}

function update_total()	// функция, которая обновляет блок с общей стоимостью на странице
{
	if(totalprice)
	{
		$('#total').html('всего: $'+totalprice); // Если мы купили что-нибудь, отобразить блок с общей стоимостью и кнопку оформления
		$('a.button').css('display','block');
	}
	else	// прячем их
	{
		$('#total').html('');
		$('a.button').hide();
	}
}
[/javascript]

В нескольких местах этого кода, мы используем <strong>id</strong> для указания товара. ID – это уникальный идентификатор, который создается базой данных MySQL один раз, когда мы вносим новую позицию.

Он передается AJAX-запросом, и нам необходимо перевести его в index-позицию нашего массива товаров для дальнейшего использования, все это осуществляет функция <strong>findpos()</strong>.

Теперь, наша интерактивная корзина готова.

<a href="http://dreamhelg.ru/wp-content/uploads/2009/09/cart.zip">Скачать архив с примером.</a>

Перевод статьи "<a href="http://tutorialzine.com/2009/09/shopping-cart-php-jquery/">An AJAX Based Shopping Cart with PHP, CSS &amp; jQuery</a>", автор <strong>Martin</strong>]]></description>
		<wfw:commentRss>http://dreamhelg.ru/2009/09/ajax-based-shopping-cart-with-jquery-and-php/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
	</channel>
</rss>

