<?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>SimpleCoding.org &#187; HTML</title>
	<atom:link href="http://www.simplecoding.org/category/ht/feed" rel="self" type="application/rss+xml" />
	<link>http://www.simplecoding.org</link>
	<description>Блог о программировании</description>
	<lastBuildDate>Fri, 27 Jan 2012 18:27:45 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>jQuery: обработка параметров URL</title>
		<link>http://www.simplecoding.org/jquery-obrabotka-parametrov-url.html</link>
		<comments>http://www.simplecoding.org/jquery-obrabotka-parametrov-url.html#comments</comments>
		<pubDate>Fri, 19 Aug 2011 07:45:55 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[Ajax]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Web разработка]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=1225</guid>
		<description><![CDATA[Приветствую всех! Сегодня хочу показать небольшой пример использования библиотеки jQuery для работы с параметрами ссылок. Предположим на нашей странице есть ссылка, клик по которой отправляет запрос на выполнение некоторой операции. Пускай это будет удаление какого-нибудь объекта. HTML разметка такой ссылки может выглядеть следующим образом. &#60;a class="delete" href="http://www.simplecoding.org/script.php?action=delete_object&#38;object_id=1"&#62;Удалить&#60;/a&#62; Как видите, ссылка содержит два параметра (action и [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_1226" class="wp-caption alignnone" style="width: 299px"><img src="http://www.simplecoding.org/wp-content/uploads/2011/08/jquery_parsequery.png" alt="jquery parsequery" title="jquery parsequery" width="289" height="152" class="size-full wp-image-1226" style="float:left" /><p class="wp-caption-text"> </p></div>
<p><strong>Приветствую всех!</strong></p>
<p>Сегодня хочу показать небольшой пример использования библиотеки <strong>jQuery</strong> для работы с параметрами ссылок.</p>
<p>Предположим на нашей странице есть ссылка, клик по которой отправляет запрос на выполнение некоторой операции. Пускай это будет удаление какого-нибудь объекта.</p>
<p><strong>HTML разметка</strong> такой ссылки может выглядеть следующим образом.</p>
<pre class="brush: html">&lt;a class="delete" href="http://www.simplecoding.org/script.php?action=delete_object&amp;object_id=1"&gt;Удалить&lt;/a&gt;</pre>
<p>Как видите, ссылка содержит два параметра (<code>action</code> и <code>object_id</code>), значения которых PHP скрипт сможет получить из массива <code>$_GET</code>.</p>
<p>Теперь, мы хотим выполнить удаление объекта с помощью <strong>AJAX запроса</strong>. Изменять ради него ссылку нет никакой необходимости. Просто назначаем обработчик для события <code>click</code>.<br />
<span id="more-1225"></span></p>
<pre class="brush: javascript">$('a.delete').click(function() {
  return false;
});</pre>
<p>Этот код блокирует отправку обычного запроса при клике по ссылке. Нам нужно <strong>получить параметры и отправить AJAX запрос</strong>.</p>
<p>В обработчике события <strong>click</strong> получить значение атрибута <strong>href</strong> ссылки можно следующим образом.</p>
<pre class="brush: javascript">$(this).attr('href')</pre>
<p>Затем нужно найти в этой строке параметры. Тут есть <strong>два варианта</strong>.</p>
<p>1) Если вам достаточно параметров, указанных в атрибуте <strong>href</strong> и вы не хотите их изменять, то просто передать методам <code>$.ajax</code> (или <code>$.post</code>, или <code>$.get</code>) строку с параметрами запроса.</p>
<p>Т.е. код будет выглядеть примерно так</p>
<pre class="brush: javascript">var params = $(this).attr('href').split('?');
$.post('ajax_delete.php', params[1], function(response) {
    console.log(response);
} );</pre>
<p>Здесь мы с помощью метода <code>split</code> разбили запрос на две части (по знаку вопроса), и передали методу <code>$.post</code> второй элемент массива <code>params</code>. Для данного примера он выглядит так<br />
<code>action=delete_object&amp;object_id=1</code></p>
<p>2) Если перед отправкой AJAX запроса нужно изменить/удалить/добавить какие-то параметры, то удобнее всего преобразовать строку с параметрами в хеш.</p>
<p>Для этих целей существует специальный плагин – <a href="http://plugins.jquery.com/project/parseQuery">parseQuery</a></p>
<p>Использовать его можно так.</p>
<pre class="brush: javascript">var params = $.parseQuery($( this ).attr( 'href' ).split('?'));</pre>
<p>В результате вы получите хеш</p>
<pre class="brush: javascript">{
	action: delete_object,
	object_id: 1
}</pre>
<p>Код отправки AJAX запроса при этом не изменяется. Точно также передаёте переменную <code>params</code> во втором параметре метода <code>$.post</code>.</p>
<p>В заключение посмотрите код обработчика целиком.</p>
<pre class="brush: javascript">$(document).ready(function() {
	$('a.delete').click( function() {
		var params = $(this).attr('href').split('?');
		$.post('ajax_delete.php', params[1], function(response) {
			console.log(response);
		});
		return false;
	});
});</pre>
<p>Как видите, задача решается с помощью минимального количества кода. И если у посетителя будет отключен JavaScript, то ничего особенного не произойдет. При кликах по ссылкам будут отправляться обычные запросы.</p>
<p>Если есть вопросы или замечания, пишите.</p>
<p><strong>Успехов!</strong></p>
<p><em>Интересно почитать</em></p>
<p>Платежный модуль <a href="http://www.rugento.ru/robokassa-payment-module.html" target="_blank">Robokassa для Magento</a> с поддержкой.</p>
<p>Нужна фотокнига? В наличие <a href="http://printfotobook.ru/primery_fotoknig">фотокниги образцы</a>, множество видов дизайна и верстки</p>
]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/jquery-obrabotka-parametrov-url.html/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>HTML5: загрузка файлов с помощью Drag &amp; Drop</title>
		<link>http://www.simplecoding.org/html5-zagruzka-fajlov-s-pomoshhyu-drag-drop.html</link>
		<comments>http://www.simplecoding.org/html5-zagruzka-fajlov-s-pomoshhyu-drag-drop.html#comments</comments>
		<pubDate>Thu, 21 Jul 2011 13:13:41 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[Ajax]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web разработка]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=1222</guid>
		<description><![CDATA[Приветствую всех! В этой статье хочу рассказать о нескольких своих экспериментах с HTML5. Начну издалека. Всем нам периодически приходится работать с различными web интерфейсами и часто возникает ощущение, что эта работа могла бы быть организована более эффективно. Возможно, в каких-то случаях виноваты разработчики сервиса, но часто проблема заключается в ограничениях, которые накладывают браузеры. Рассмотрим загрузку [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_1223" class="wp-caption alignnone" style="width: 310px"><img src="http://www.simplecoding.org/wp-content/uploads/2011/07/html5_drag_drop_upload.png" alt="html5 drag&amp;drop upload" title="html5 drag&amp;drop upload" width="300" height="186" class="size-full wp-image-1223" style="float:left" /><p class="wp-caption-text"> </p></div>
<p><strong>Приветствую всех!</strong></p>
<p>В этой статье хочу рассказать о нескольких своих экспериментах с HTML5. Начну издалека. Всем нам периодически приходится работать с различными web интерфейсами и часто возникает ощущение, что эта работа могла бы быть организована более эффективно.</p>
<p>Возможно, в каких-то случаях виноваты разработчики сервиса, но часто проблема заключается в ограничениях, которые накладывают браузеры. Рассмотрим загрузку файлов на сервер. В большинстве случаев вам предложат стандартное поле с кнопкой выбора файла с вашего компьютера и/или поле, в котором можно указать URL файла, размещенного где-нибудь в Сети.</p>
<p>Загрузку файлов с локального компьютера трогать пока не будем, я планирую опубликовать отдельный пост на эту тему, разберем загрузку с удалённого сервера.</p>
<p>Проблемы начинаются с первого же шага. Даже если вы четко понимаете, где искать URL и хорошо умеете пользоваться инструментами вроде <strong>firebug</strong>, то всё равно потребуется несколько кликов мышкой чтобы получить нужный адрес. Было бы гораздо удобнее просто перетянуть нужную картинку из одного окна браузера в другое.<br />
<span id="more-1222"></span><br />
Пример реализации такого интерфейса я покажу в этой статье. Если хотите, можете посмотреть, как он работает на демонстрационной страничке или скачать архив с исходниками.</p>
<p><a href="http://demosites.simplecoding.org/images-upload/"><img src="http://www.simplecoding.org/wp-content/themes/three_cols/images/demo_btn_green.png" alt="демонстрационный пример" /></a><a href='http://www.simplecoding.org/wp-content/uploads/2011/07/images-upload.zip'><img src="http://www.simplecoding.org/wp-content/themes/three_cols/images/download_btn_blue.png" alt="архив с исходным кодом" /></a></p>
<p><strong>Обратите внимание!</strong> Данный пример работает только в браузере <strong>Google Chrome</strong>. По-идее, поддержка всех необходимых технологий есть в <strong>Firefox</strong> и <strong>Safari</strong>, но с ними я пока не разбирался.<br />
В качестве объектов для «перетягивания» я брал в основном картинки с википедии. Было замечено несколько проблем связанных с не латинскими символами в URL картинок, но чтобы не перегружать пример проверками и преобразованиями я их оставил как есть.</p>
<h2>Принцип работы</h2>
<p>Стандарт HTML5 предусматривает поддержку «перетягивания» объектов страницы (Drag and Drop). Кстати, пример простейшей реализации D&#038;D я уже показывал – <a href="http://www.simplecoding.org/drag-drop-s-ispolzovaniem-html5.html">Drag &#038; Drop с использованием HTML5</a>. И, кроме того, есть довольно много JavaScript библиотек, реализующих поддержку D&#038;D.</p>
<p>Но тут важно понимать, что если необходимо «перетягивать» картинки со сторонних ресурсов, то использовать библиотеки не получится. Т.к. вы не сможете добавить свой JS код на чужую страницу. А для того, чтобы загрузить картинку, нам нужно получить её URL, т.е. браузер должен вместе с перетягиваемым объектом передавать и его параметры (например, атрибут src картинки или весь тег img).</p>
<p>В этом случае мы можем создать на своей странице «приёмник» картинок. Это будет обычный <code>div</code> которому назначен обработчик события <code>drop</code>. Если пользователь «сбросит» картинку над этим div&#039;ом, то будет вызван обработчик и в первом параметре он получит объект, содержащий информацию о перетягиваемой картинке.</p>
<p>Дальше всё достаточно просто. Если мы получили нужный URL, то можно отправить AJAX-запрос серверному скрипту, который выполнит загрузку файла.</p>
<h2>Реализация</h2>
<p>Начнём со страницы нашего приложения.</p>
<pre class="brush: html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
    &lt;head&gt;
        &lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"&gt;
        &lt;title&gt;Images Upload&lt;/title&gt;
		&lt;link rel="stylesheet" type="text/css" href="styles.css" /&gt;
    &lt;/head&gt;
    &lt;body&gt;
		&lt;div id="images"&gt;&lt;/div&gt;
		&lt;div id="img_target"&gt;&lt;/div&gt;
		&lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"&gt;&lt;/script&gt;
		&lt;script src="main.js"&gt;&lt;/script&gt;
    &lt;/body&gt;
&lt;/html&gt;</pre>
<p>На ней размещены два блока: <code>images</code> – здесь будем показывать загруженные изображения и <code>img_target</code> – на этот блок нужно перетягивать картинки.</p>
<p>Внизу страницы подключаем библиотеку jQuery и скрипт main.js, который будет отправлять информацию о перетянутых изображениях на сервер.</p>
<p><strong>Рассмотрим main.js</strong></p>
<pre class="brush: javascript">$(function() {
    $('#img_target')
        .bind('dragenter', function(event) {
            $(this).addClass('drop_here');
            return false;
        })
        .bind('dragleave', function(event) {
            $(this).removeClass('drop_here');
            return false;
        })
        .bind('dragover', function(event) {
            return false;
        })
        .bind('drop', function(event) {
            $(this).removeClass('drop_here');
			var srcRegex = /src=\"([^\s]+)\"/ig;
            var data = event.originalEvent.dataTransfer.getData('text/html');
			var img_data = srcRegex.exec(data);
			$.post('upload.php', {'file_url':img_data[1]}, function(res) {
				var response = eval('(' + res + ')');
				$('#images').append($('&lt;img src="' + response.file_url + '" /&gt;'));
			});
            return true;
        });
});</pre>
<p>Здесь мы назначаем обработчики событиям <code>dragenter</code>, <code>dragleave</code> и <code>dragover</code>. Все они должны просто возвращать false и, чтобы как-то проинформировать пользователя о том, что можно «сбрасывать» картинку, в обработчике <code>dragenter</code> устанавливаем CSS класс <code>drop_here</code> для блока-приёмника.</p>
<p>Основная часть работы выполняется в обработчике события <code>drop</code>. При возникновении этого события мы читаем информацию о «сброшенном» объекте и «вырезаем» значение атрибута <code>src</code>, т.е. URL картинки (строки 16-18). Информация передается в объекте event.originalEvent.dataTransfer (строка 17).</p>
<p>Затем <strong>формируем обычный AJAX запрос</strong> и в качестве параметра передаём ему найденный URL.</p>
<p>Серверный скрипт (upload.php) получит URL изображения на удалённом сервере и загрузит его. А в ответе на AJAX запрос он отправит новый URL загруженной картинки.</p>
<p>В свою очередь, обработчик AJAX-запроса создаст тег <code>img</code> и вставит его в блок <code>images</code>. Таким образом, загруженные картинки будут появляться над полем загрузки.</p>
<p><strong>Рассмотрим upload.php</strong></p>
<pre class="brush: php">&lt;?php

define('BASE_URL', 'http://localhost/tests/images-upload/');

function upload_from_url($file_url) {
	$url_segments = explode('/', $file_url);
	$file_name = urldecode(end($url_segments));
	if (false !== $file_name) {
		$file_name_parts = explode('.', $file_name);
		if (in_array(strtolower(end($file_name_parts)), array('jpeg','jpg','png','gif'))) {
			$destination=fopen("upload/".$file_name,"w");
			$source=fopen($file_url,"r");
			$maxsize=300*1024;
			$length=0;
			while (($a=fread($source,1024))&#038;&#038;($length&lt;$maxsize)) {
				$length=$length+1024;
				fwrite($destination,$a);
			}
			fclose($source);
			fclose($destination);
		}
	}
	$new_file_url = BASE_URL.'upload/'.$file_name;
	return $new_file_url;
}

$res = array('err' =&gt; 'Не указан URL файла');

if (isset($_POST['file_url'])) {
	$new_url = upload_from_url($_POST['file_url']);
	$res = array('file_url' =&gt; $new_url);
}

echo json_encode($res);</pre>
<p>Принцип работы следующий. Читаем URL картинки и пытаемся её загрузить (строки 29-32).</p>
<p>Если картинка загружена, сохраняем её в папку <code>upload</code>. Получение картинки с удалённого сервера осуществляется с помощью функций <code>fread</code>. Файл читаем блоками по 1кБ (строки 15-18). Такой подход позволяет прервать загрузку файла, если его размер превышает заданный предел (в данном случае 300кБ).</p>
<p>После загрузки файла формируем для него URL и отправляем браузеру в формате <strong>JSON</strong>.</p>
<p>Как видите, реализовать такой загрузчик несложно. И пользоваться им достаточно удобно. Естественно, основным недостатком является поддержка HTML5 браузерами, точнее её отсутствие <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Тем не менее, если вы создаёте интерфейс для сотрудников какой-нибудь компании, и можете оговорить тип браузера, то HTML5 вполне можно использовать.</p>
<p><strong>Успехов!</strong></p>
<p><em>Интересно почитать.</em></p>
<p>Фотокнига — фантастический <a href="http://imagebook.ru/sjurpriz_ljubimomu_muzhchine">сюрприз для любимого мужчины</a>. Попробуйте сами!</p>
<p>Правильно подготовим <a href="http://online-nalogi.ru/3_ndfl_pokupka_kvartiry">3-ндфл при покупке квартиры за 2011 год</a>, дадим инструкции для получения вычета</p>
<p>Нужно распарсить сайт? Интересный пример как написан <a href="http://www.sergunik.name/?p=140" title="php parser">парсер на php</a>. Можно даже скачать скрипт парсера.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/html5-zagruzka-fajlov-s-pomoshhyu-drag-drop.html/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Как показать на Google Maps объекты, находящиеся в заданной области</title>
		<link>http://www.simplecoding.org/kak-pokazat-na-google-maps-obekty-naxodyashhiesya-v-zadannoj-oblasti.html</link>
		<comments>http://www.simplecoding.org/kak-pokazat-na-google-maps-obekty-naxodyashhiesya-v-zadannoj-oblasti.html#comments</comments>
		<pubDate>Tue, 28 Jun 2011 09:48:03 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Web разработка]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=1214</guid>
		<description><![CDATA[Показать пример решения такой задачи меня попросили в комментариях к одной из предыдущих статей о Google Maps. С выполнением этой просьбы я довольно сильно затянул, но, надеюсь, эта статья кому-нибудь пригодится Начнём с постановки задачи Предположим, у нас есть данные о группе объектов (их названия и координаты). Необходимо отметить их на карте с помощью маркеров. [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_1215" class="wp-caption alignnone" style="width: 310px"><img src="http://www.simplecoding.org/wp-content/uploads/2011/06/google_maps.png" alt="google maps" title="google maps" width="300" height="197" style="float:left" class="size-full wp-image-1215" /><p class="wp-caption-text"> </p></div>
<p>Показать пример решения такой задачи меня попросили в комментариях к одной из предыдущих статей о <strong>Google Maps</strong>. С выполнением этой просьбы я довольно сильно затянул, но, надеюсь, эта статья кому-нибудь пригодится <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><strong>Начнём с постановки задачи</strong></p>
<p>Предположим, у нас есть данные о группе объектов (их названия и координаты). Необходимо отметить их на карте с помощью маркеров. При этом, показать нужно не все объекты, а только те, которые находятся внутри заданной области.</p>
<p>Будем считать, что заданная область представляет собой окружность, т.е. мы знаем координаты её центра и радиус. А координаты объектов находятся в KML файле (это XML формат, разработанный для описания объектов на Google maps).<br />
<span id="more-1214"></span><br />
Таким образом, <strong>алгоритм расстановки объектов</strong> получается довольно простым.</p>
<p>1) Читаем координаты объекта из KML файла.<br />
2) Рассчитываем расстоянием между центром окружности и текущим объектом.<br />
3) Если это расстояние меньше радиуса окружности, ставим маркер, если больше – пропускаем объект.</p>
<p>Переходим к решению.</p>
<p>Посмотреть, как работает этот пример, можно на демонстрационной страничке или установив скрипты на своем сервере.</p>
<p><a href="http://demosites.simplecoding.org/google-maps/"><img src="http://www.simplecoding.org/wp-content/themes/three_cols/images/demo_btn_green.png" alt="демонстрационный пример" /></a> <a href='http://www.simplecoding.org/wp-content/uploads/2011/06/google_maps.zip'><img src="http://www.simplecoding.org/wp-content/themes/three_cols/images/download_btn_blue.png" alt="архив с исходным кодом" /></a></p>
<h2>Серверная часть</h2>
<p>Начнем с серверного скрипта, который формирует страницу с картой (index.php).</p>
<pre class="brush: php">&lt;?php
$organizations = simplexml_load_file('doc.kml');

$organizations_data = array();

foreach ($organizations-&gt;Folder-&gt;Placemark as $organisation) {
    $organizations_data[] = array(
        'name' =&gt; (string)$organisation-&gt;name,
        'coordinates' =&gt; (string)$organisation-&gt;Point-&gt;coordinates,
    );
}
?&gt;

&lt;!DOCTYPE html&gt;

&lt;html&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8" /&gt;
    &lt;title&gt;Объекты на Google Maps&lt;/title&gt;
    &lt;script&gt;
&lt;?php
    echo 'var organizations = '.json_encode($organizations_data).';';
?&gt;
    &lt;/script&gt;
&lt;/head&gt;

&lt;body&gt;

&lt;h1&gt;Google Maps: отображение объектов, которые находятся в заданной области&lt;/h1&gt;

&lt;div id="my_map" style="width:600px;height:400px"&gt;&lt;/div&gt;

&lt;script src="main.js"&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Прежде всего, загружаем данные из KML файла (строка 2). Т.к. это обычный XML файл, то мы можем использовать любую библиотеку для работы с этим форматом. В данном случае – <a href="http://php.net/manual/en/book.simplexml.php">SimpleXML</a>.</p>
<p>Затем, необходимо обеспечить доступ к этим данным на клиентской стороне, т.к. настройка Google Maps выполняется с помощью <strong>JavaScript</strong>.</p>
<p>Для этого мы формируем массив с необходимыми данными (строки 6-11), преобразовываем его в <strong>JSON</strong> формат (строка 22) и присваиваем переменной <code>organizations</code> (строка 22) в теге <code>script</code>. Таким образом, мы получаем <strong>JavaScript массив</strong> с координатами всех объектов из KML файла.</p>
<p>Тут я хочу сделать небольшое отступление. В принципе, работать с KML файлом можно и на стороне браузера, это несложно. Но в общем случае, этот файл не обязательно будет находиться на вашем сервере, а кросс-доменные (XSS) запросы запрещены политикой безопасности браузеров. Т.е. придётся искать какой-нибудь обходной путь. Подробнее на эту тему можно почитать <a href="http://www.simplecoding.org/kak-obojti-zapret-na-xss.html">здесь</a>, <a href="http://www.simplecoding.org/xss-i-same-origin-policy.html">здесь</a>, <a href="http://www.simplecoding.org/xss-s-ispolzovaniem-jsonp-i-jquery.html">здесь</a> и <a href="http://www.simplecoding.org/javascript-xss-poluchenie-dannyx-ot-facebook-i-vkontakte.html">здесь</a>.</p>
<p>Подробно разбирать работу с <strong>SimpleXML</strong>, думаю, смысла не имеет. Для данного примера достаточно понимать, что после загрузки файла вы получите объект, имеющий такую же структуру как и xml-документ.</p>
<p>Т.е. вызов <code>$organizations-&gt;Folder-&gt;Placemark</code> вернет вам содержимое тега <code>&lt;Placemark&gt;</code> в документе с такой структурой</p>
<pre class="brush: xml">&lt;kml xmlns="…" xmlns:kml="…" xmlns:atom="…"&gt;
&lt;Folder&gt;
	&lt;Placemark&gt;
	…
	&lt;/Placemark&gt;
&lt;/Folder&gt;
&lt;/kml&gt;</pre>
<p><em>Обратите внимание!</em> Библиотека чувствительна к регистру тегов в xml-файле.</p>
<p>На самой странице мы создаём блок для карты (<code>my_map</code>).</p>
<p>И подключаем файл main.js, который и будет выполнять настройку карты.</p>
<h2>Клиентская часть</h2>
<p>Сразу посмотрим на весь скрипт целиком.</p>
<pre class="brush: javascript">var map, circle, circleOptions, setCenter, marker, organizations_markers;

function initialize() {
    var centerPoint = new google.maps.LatLng(48.67, 44.47); //Волгоград
    var myOptions = {
        zoom: 12,
        center: centerPoint,
        mapTypeId: google.maps.MapTypeId.HYBRID
    }
    map = new google.maps.Map(document.getElementById("my_map"), myOptions);

    //радиус окружности - 5 км
    var radius = 5;

    circleOptions = {
        center: centerPoint,
        fillColor: "#00AAFF",
        fillOpacity: 0.5,
        strokeColor: "#FFAA00",
        strokeOpacity: 0.8,
        strokeWeight: 2,
        clickable: false,
        radius: radius*1000
    }

    //рисуем окружность
    circle = new google.maps.Circle(circleOptions);
    circle.setMap(map);

    //устанавливаем маркеры организаций
    organizations_markers = [];
    for (var i = 0; i &lt; organizations.length; i++) {
        var ll = organizations[i].coordinates.split(',');
        var latlng = new google.maps.LatLng(ll[1], ll[0]);
        if (distHaversine(latlng, centerPoint) &lt; radius) {
            organizations_markers[i] = new google.maps.Marker({
                    position:latlng,
                    clickable:true
                });
            organizations_markers[i].setMap(map);
        }
    }
}

function loadScript() {
    var script = document.createElement("script");
    script.src = "http://maps.google.com/maps/api/js?sensor=false&#038;callback=initialize";
    document.body.appendChild(script);
}

rad = function(x) {return x*Math.PI/180;}

//эта функция используются для определения расстояния между точками на
//поверхности Земли, заданных с помощью географических координат
//результат возвращается в км
distHaversine = function(p1, p2) {
    var R = 6371; // earth's mean radius in km
    var dLat  = rad(p2.lat() - p1.lat());
    var dLong = rad(p2.lng() - p1.lng());

    var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
            Math.cos(rad(p1.lat())) * Math.cos(rad(p2.lat())) * Math.sin(dLong/2) * Math.sin(dLong/2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    var d = R * c;

    return d.toFixed(3);
}

window.onload = loadScript;</pre>
<p>В первую очередь мы создаём карту и устанавливаем её основные параметры (координаты центра, приближение). Для этого, назначаем обработчик событию <code>window.onload</code> (строка 69). Этот обработчик добавляет на страницу тег <code>script</code> в параметре <code>src</code> которого передается адрес имя метода, который будет вызван после загрузки Google Maps (в данном случае &#8211; <code>initialize</code>). Таким образом, все наши настройки выполняются в этом методе.</p>
<p>Выполняем установку параметров карты (строки 4-10). Мы указали: центральную точку (<code>centerPoint</code>), приближение (<code>zoom</code>) и тип карты (<code>mapTypeId</code>).</p>
<p>Теперь рисуем окружность (строки 13-28). Её центр совпадает с центром карты, а радиус равен 5 км. В настройках окружности указываем толщину и цвет линии, цвет и прозрачность фона и другие параметры.</p>
<p>После этого <strong>расставляем маркеры объектов</strong>.</p>
<p>Напомню, что координаты этих объектов находятся в массиве organizations, который был сформирован серверным скриптом.</p>
<p>Т.е. нам нужно пройтись по всем элементам этого массива и рассчитать расстояние от центра окружности до текущего объекта (строки 31-42).</p>
<p>Расчет расстояний для точек на поверхности Земли выполняется с помощью функции гаверсинусов (<code>distHaversine</code>). Её реализацию на JavaScript я взял <a href="http://stackoverflow.com/questions/1502590/calculate-distance-between-two-points-in-google-maps-v3">здесь</a>.</p>
<p>Если это расстояние меньше заданного, создаём маркер и показываем его на карте (строки 36-40). В противном случае – переходим к следующему объекту.</p>
<p>Как видите, алгоритм достаточно простой. Если немного усовершенствовать скрипт, можно сделать окружность перемещаемой и с переменным радиусом. Таким образом, имея хорошую базу объектов для какого-нибудь города, можно получить довольно удобный инструмент определения ближайших к заданной точке объектов.</p>
<p>Если есть вопросы или замечания, пишите, постараюсь ответить в комментариях <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><strong>Успехов!</strong></p>
<p><em>Интересно почитать</em></p>
<p>Хотите создать свой сайт? <a href="http://template-cms.ru/">Template CMS &#8211; быстрая и маленькая CMS!</a> Поможет решить эту задачу с минимальными затратами времени и ресурсов.</p>
<p>В раздумьях, <a href="http://imagebook.ru/podarok_k_svadbe">что подарить на свадьбу друзьям</a>? Попробуйте свадебную фотокнигу.</p>
<p>Заполним <a href="http://online-nalogi.ru"> 3-ндфл за 2011</a> год за 1 день, от 500 рублей!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/kak-pokazat-na-google-maps-obekty-naxodyashhiesya-v-zadannoj-oblasti.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>JavaScript XSS: получение данных от facebook и вконтакте</title>
		<link>http://www.simplecoding.org/javascript-xss-poluchenie-dannyx-ot-facebook-i-vkontakte.html</link>
		<comments>http://www.simplecoding.org/javascript-xss-poluchenie-dannyx-ot-facebook-i-vkontakte.html#comments</comments>
		<pubDate>Sun, 22 May 2011 11:02:21 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Web разработка]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=1211</guid>
		<description><![CDATA[О виджетах популярных социальных сетей знают практически все web мастера. Использовать их достаточно просто. В большинстве случаев нужно вставить блок с JavaScript кодом в шаблон страницы. Но что мы получаем в результате? Стандартную кнопку, позволяющую посетителю быстро опубликовать ссылку на текущую страницу в социальной сети и обычно счетчик таких публикаций. При этом, внешний вид такого [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_1212" class="wp-caption alignnone" style="width: 221px"><img src="http://www.simplecoding.org/wp-content/uploads/2011/05/facebook_vkontakte.png" alt="facebook vkontakte" title="facebook vkontakte" width="211" height="141" class="size-full wp-image-1212" style="float:left" /><p class="wp-caption-text"> </p></div>
<p>О <strong>виджетах популярных социальных сетей</strong> знают практически все web мастера. Использовать их достаточно просто. В большинстве случаев нужно вставить блок с <strong>JavaScript</strong> кодом в шаблон страницы.</p>
<p>Но что мы получаем в результате? Стандартную кнопку, позволяющую посетителю быстро опубликовать ссылку на текущую страницу в социальной сети и обычно счетчик таких публикаций.</p>
<p>При этом, внешний вид такого виджета полностью определяется разработчиком и изменить его довольно проблематично, т.к. он находится внутри <code>iframe</code>, который загружен с другого домена. То есть ваши стили не будут применяться к этому iframe&#039;у.</p>
<p>Безусловно, такие виджеты выглядят очень не плохо и, самое главное, они узнаваемы. Большинство посетителей прекрасно понимает как ими пользоваться безо всяких дополнительных подсказок.</p>
<p>Тем не менее, бывают ситуации когда нужно изменить внешний вид виджета, да и грузить JavaScript код социальных сетей не очень хочется.</p>
<p>В этом случае придется <strong>создать свой виджет</strong> и обеспечить правильную его работу с социальными сетями.</p>
<p>Именно о таком решении я хочу рассказать в этой статье. В качестве примера возьмем <strong>facebook</strong> и <strong>вконтакте</strong>. Выбор этот сделан не случайно, разница между API этих сервисов довольно ощутимая. Чуть ниже вы поймете почему.<br />
<span id="more-1211"></span><br />
Условно, виджет можно разбить на две части.</p>
<p>1) Кнопка публикации.<br />
2) Счетчик публикаций.</p>
<p>Рассмотрим их подробнее.</p>
<h2>Кнопка публикаций</h2>
<p>Здесь все предельно просто. В обоих случаях информация передаётся в параметрах GET запроса. Т.е. достаточно сформировать ссылки следующего вида.</p>
<p>Для facebook:</p>
<pre class="brush: html">&lt;a href="http://www.facebook.com/sharer.php?u=url&#038;t=text" target="_blank"&gt;facebook&lt;/a&gt;</pre>
<p>Для вконтакте:</p>
<pre class="brush: html">&lt;a href="http://vkontakte.ru/share.php?url=url" target="_blank"&gt;вконтакте&lt;/a&gt;';</pre>
<p>Вместо <code>url</code> и <code>text</code> нужно подставить адрес и описание страницы, соответственно.</p>
<h2>Счетчик публикаций</h2>
<p>Здесь код будет немного сложнее. В обоих случаях для получения значений счетчика нужно отправить запрос серверу социальной сети. И тут начинаются варианты.</p>
<p>В большинстве источников, которые я видел в Сети, предлагают отправлять такой запрос со своего сервера (с помощью PHP) и затем кэшировать результат. Мне этот подход не нравится по нескольким причинам.</p>
<p>1) Любой запрос занимает какое-то время, которое прибавляется к общему времени формирования страницы. Кэширование в какой-то степени решает эту проблему (запросы будут отправляться не при каждом просмотре страницы), но не полностью.</p>
<p>2) При большом количестве запросов, социальная сеть может заблокировать ваш IP (зависит от политики социальной сети).</p>
<p>3) Создаётся дополнительная нагрузка на ваш сервер.</p>
<p>Второй вариант – <strong>отправлять запросы со стороны клиента, с помощью JavaScript</strong>.</p>
<p>В этом случае запрос уйдет из браузера посетителя и, по крайней мере, IP адреса таких запросов будут отличаться. Кроме того, запрос можно отправить после полной загрузки страницы и работа вашего сайта ни коим образом не будет зависеть от доступности социальной сети.</p>
<p>Но, при реализации такого подхода, возникают две <strong>проблемы</strong>.</p>
<p><strong>1) Встроенная защита браузеров от кросс-доменных запросов.</strong></p>
<p>Т.е. вы не можете отправить AJAX запрос на другой домен, но можно вставить в страницу тег <code>script</code> и в его атрибуте <code>src</code> указать адрес нужного скрипта на другом домене. В результате браузер загрузит нужный вам скрипт и выполнит код, находящийся в нём.</p>
<p>При использовании jQuery задача решается с минимумом усилий. Например, так:</p>
<pre class="brush: javascript">$.getJSON('http://vkontakte.ru/share.php?act=count&#038;index=1&#038;url=page_url&#038;callback=?', function(response) {
	…
});</pre>
<p>Обратите внимание на параметр <code>callback=?</code>. Если он указан, то jQuery вставит тег <code>script</code> внутрь страницы. Вообще параметр <code>callback</code> разработан для поддержки <strong>JSONP</strong> и указывает серверу, что ответ в JSON формате нужно передать в качестве параметра указанной функции. Имя этой функции jQuery формирует автоматически и подставляет вместо знака вопроса.</p>
<p>Естественно, JSONP должен поддерживаться на стороне сервера. И сейчас мы разберем какие ответы мы получим от социальных сетей на практике.</p>
<p><strong>2) Формат ответа социальной сети.</strong></p>
<p>С facebook всё отлично. Эта социальная сеть поддерживает JSONP и если мы отправим запрос вида.</p>
<pre class="brush: javascript">$.getJSON('http://graph.facebook.com/' + encodeURI(page_url)
		+ '&#038;callback=?', function(response) {
	if (response.shares !== undefined) {
		fb_counter = response.shares;
	}
	$('#facebook_count').html(response.shares);
});
<pre>

То получим следующий ответ.
<pre class="brush: javascript">jQuery16105957901661749929_1306057803097({
   "id": "http://www.smashingmagazine.com/",
   "shares": 5454
});</pre>
<p><code>jQuery16105957901661749929_1306057803097</code> – имя функции, которое сгенерировала jQuery.<br />
В первом параметре этой функции передаётся строка в JSON формате с адресом страницы и количеством публикаций.<br />
В результате, в обработчик запроса будет передан JS объект с нужными данными. В этом примере он называется <code>response</code>, т.е. получить количество публикаций ссылки можно с помощью вызова <code>response.shares</code>.</p>
<p>В случае с вконтаке всё сложнее. Эта социальная сеть JSONP не поддерживает и на запрос</p>
<pre class="brush: javascript">$.getJSON('http://vkontakte.ru/share.php?act=count&#038;index=1&#038;url='
	+ encodeURI(page_url) + '&#038;callback=?', function(response) {});</pre>
<p>отвечает следующей строкой:</p>
<pre class="brush: javascript">VK.Share.count(1, 9);</pre>
<p>Естественно, это приводит к возникновению ошибки</p>
<p><code>VK is not defined</code></p>
<p>Вообще ответ сервера вконтакте – это обычный вызов метода count, присвоенного параметру <code>Share</code> объекта <code>VK</code>. Откуда берется этот объект? Его создаёт скрипт, который нужно подключить при использовании стандартного виджета. Но этот скрипт нам не нужен, т.к. виджет мы не используем, а количество публикаций ссылки нужно вставить в заранее подготовленный блок о котором стандартный скрипт ничего не знает.</p>
<p>Т.е. нам нужен собственный объект VK с соответствующими параметрами. Создать его совсем не сложно.</p>
<pre class="brush: javascript">var VK = {
    Share: {
        count: function(value, count) {
            $('#vkontakte_count').html(count);
        }
    }
}</pre>
<p>Теперь, после получения ответа от сервера вконтакте, будет вызвана анонимная функция, установленная для параметра <code>count</code>. Во втором параметре она получит количество публикаций страницы.</p>
<p>Обратите внимание – этот код должен находится в глобальной области видимости.</p>
<p>Привожу весь код целиком.</p>
<p>Страницы со счетчиками</p>
<pre class="brush: html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;Счетчики&lt;/title&gt;
    &lt;meta charset="utf-8" /&gt;
&lt;/head&gt;

&lt;body&gt;
    &lt;div&gt;Facebook &lt;span id="facebook_count"&gt;&lt;/span&gt;&lt;/div&gt;
    &lt;div&gt;ВКонтакте &lt;span id="vkontakte_count"&gt;&lt;/span&gt;&lt;/div&gt;

    &lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"&gt;&lt;/script&gt;
    &lt;script src="social_counters.js"&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Скрипт social_counters.js</p>
<pre class="brush: javascript">jQuery(document).ready(function($) {
    var fb_counter = 0;
    var vk_counter = 0;
    var page_url = 'http://www.smashingmagazine.com/';

	$.getJSON('http://vkontakte.ru/share.php?act=count&#038;index=1&#038;url='
		+ encodeURI(page_url) + '&#038;callback=?', function(response) {});

	$.getJSON('http://graph.facebook.com/' + encodeURI(page_url)
			+ '&#038;callback=?', function(response) {
		if (response.shares !== undefined) {
			fb_counter = response.shares;
		}
		$('#facebook_count').html(response.shares);
	});
});

var VK = {
    Share: {
        count: function(value, count) {
            $('#vkontakte_count').html(count);
        }
    }
}</pre>
<h2>В заключение пара замечаний</h2>
<p>1) Поддержка JSONP значительно упрощает жизнь разработчикам и в конечном итоге способствует популяризации социальной сети или сервиса.</p>
<p>2) Отсутствие этой поддержки не означает, что вы не сможете интегрировать ваш сайт с данной социальной сетью. Главное, чтобы была возможность получить нужные данные в какой-нибудь форме. Естественно, при этом придётся написать какое-то количество дополнительного кода.</p>
<p>Если вы заметили ошибку или знаете более удачное решение данной проблемы, пишите, будет интересно обсудить.<br />
<strong>Успехов!</strong></p>
<p><strong>Интересно почитать</strong></p>
<p>Не знаете, <a href="http://imagebook.ru/chto_podarit_podruge">что подарить подруге на день рождения</a>? Фотоальбом с ее лучшими снимками!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/javascript-xss-poluchenie-dannyx-ot-facebook-i-vkontakte.html/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>JavaScript виджет: бесконечная загрузка твитов</title>
		<link>http://www.simplecoding.org/javascript-vidzhet-beskonechnaya-zagruzka-tvitov.html</link>
		<comments>http://www.simplecoding.org/javascript-vidzhet-beskonechnaya-zagruzka-tvitov.html#comments</comments>
		<pubDate>Tue, 05 Apr 2011 18:59:36 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Web разработка]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=1200</guid>
		<description><![CDATA[В последнее время я часто замечаю на различных сайтах виджеты, которые подгружают контент при определённых действиях посетителя. Такой подход позволяет с одной стороны, сократить количество данных на странице, а с другой – при необходимости показывать практически неограниченный объем информации. Рассмотрим небольшой практический пример. Допустим, мы хотим показать в сайдбаре виджет с твитами из какой-нибудь ленты [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_1201" class="wp-caption alignnone" style="width: 310px"><img src="http://www.simplecoding.org/wp-content/uploads/2011/04/load_on_scroll.png" alt="load on scroll" title="load on scroll" width="300" height="243" style="float:left" class="size-full wp-image-1201" /><p class="wp-caption-text"> </p></div>
<p>В последнее время я часто замечаю на различных сайтах виджеты, которые подгружают контент при определённых действиях посетителя. Такой подход позволяет с одной стороны, сократить количество данных на странице, а с другой – при необходимости показывать практически неограниченный объем информации.</p>
<p>Рассмотрим небольшой практический пример.</p>
<p>Допустим, мы хотим показать в сайдбаре <em>виджет с твитами</em> из какой-нибудь ленты (естественно, существует множество готовых решений, но сейчас не о них речь, кроме того, данное решение можно использовать для загрузки любого контента).</p>
<p>На первый взгляд всё предельно просто, twitter предоставляет <a href="http://dev.twitter.com/doc/get/statuses/user_timeline">API</a>, с помощью которого можно получить твиты любого пользователя (если они открыты). Вставить их сайдбар тоже не проблема.</p>
<p>Но на практике возникает <strong>несколько интересных моментов</strong>.<br />
<span id="more-1200"></span><br />
1) Информация от <strong>twitter</strong> не является основным контентом сайта и не должна влиять на скорость загрузки страницы. Кроме того, доступность сервиса также не должна влиять на работу сайта.</p>
<p>2) Твиты могут появляться довольно быстро, поэтому чтобы информация в виджете была всегда актуальной от кеширования придётся отказаться.</p>
<p>3) Т.к. твиты не являются основным содержимым страницы, то посетитель скорее всего не заметит если они появятся через некоторое время после загрузки основной части страницы.</p>
<p>4) Не ясно, сколько именно твитов нужно выводить. Части посетителей эта информация будет не интересна вообще, но пользователи этого сервиса, возможно, захотят прочитать несколько десятков сообщений.</p>
<p>5) Количество места, выделенного под виджет, обычно ограничено. И необходимо чтобы загрузка новых твитов не «ломала» дизайн.</p>
<p>Таким образом, нам нужно загружать твиты после загрузки страницы и желательно, чтобы от посетителя требовался минимум действий для загрузки новых твитов.</p>
<p><strong>Теперь рассмотрим сам виджет.</strong></p>
<p>Начнём с алгоритма.</p>
<p>1) Создаём на странице область с фиксированной высотой и вертикальным полосой прокрутки.</p>
<p>2) После загрузки страницы подгружаем в эту область твиты с помощью JavaScript.</p>
<p>3) Если пользователь переместит ползунок скролла в крайнее нижнее положение – загружаем следующую «порцию» твитов.</p>
<p>Посмотреть как работает такой виджет можно на демонстрационной страничке. И сразу же даю ссылку на архив с этим примером.</p>
<p><a href="http://demosites.simplecoding.org/infinite-scroll/"><img src="http://www.simplecoding.org/wp-content/themes/three_cols/images/demo_btn_green.png" alt="демонстрационный пример" /></a> <a href='http://www.simplecoding.org/wp-content/uploads/2011/04/infinite_scroll.zip'><img src="http://www.simplecoding.org/wp-content/themes/three_cols/images/download_btn_blue.png" alt="архив с исходным кодом" /></a></p>
<p>Разметка виджета с твитами может выглядеть следующим образом.</p>
<pre class="brush: html">&lt;div id="tweets"&gt;
    &lt;div class="loader hidden"&gt;&lt;/div&gt;
&lt;/div&gt;</pre>
<p>Как видите, после первоначальной загрузки внутри виджета будет находится только один элемент – картинка с изображением загрузчика. Стили для неё мы установим таким образом, чтобы она всегда находилась в центре виджета.</p>
<pre class="brush: css">.loader {
    background-image: url('ajax-loader.gif');
    width: 400px;
    height: 300px;
    background-repeat: no-repeat;
    background-position: center center;
    position: fixed;
}</pre>
<p>Значения <code>width</code> и <code>height</code> должны совпадать с соответствующими значениями, установленными для виджета (div#tweets).</p>
<pre class="brush: css">#tweets {
    height: 300px;
    width: 400px;
    overflow: auto;
    position: relative;
    border: solid 1px #999;
    margin: 3em auto 0 auto;
}</pre>
<p><strong>Переходим к загрузке твитов</strong></p>
<p>Основная сложность заключается в том, что нам нужно с помощью JavaScript выполнить кросс-доменный запрос к серверу twitter’а. Такие запросы запрещены политикой безопасности браузеров, поэтому использовать обычный AJAX запрос не получится.</p>
<p>Тем не менее, благодаря тому, что <strong>Twitter API</strong> поддерживает <strong>JSONP</strong> задача решается достаточно просто.</p>
<pre class="brush: javascript">$(function() {
    //параметры для получения твитов
    var user_id = '24147920';
    var tweets_url = 'http://api.twitter.com/1/statuses/user_timeline.json';
    var page = 1;
    var tweets_num = 10;

    //список твитов и картинка загрузчика
    var container = $('#tweets');
    var loader = $('.loader');

    //шаблон для поиска ссылок в твитах (упрощенный)
    var pattern = /(http\S+)/gi;

    //загружаем первую страницу твитов
    get_tweets(page);

    //обработчик события scroll
    container.scroll(function() {
        //это условие выполняется когда ползунок находится в крайнем нижнем положении
        if  (container[0].scrollTop == container[0].scrollHeight - container[0].clientHeight){
            //показываем загрузчик
            loader.removeClass('hidden');
            //загружаем очередную страницу твитов
            page = page + 1;
            get_tweets(page);
        }
    });

    //эта функция загружает твиты, ищет ссылки и ставит для них
    //соответствующий тег &lt;a href="..."&gt;, вставляет твиты в список
    function get_tweets(page) {
        $.getJSON(
            //формируем запрос на получение твитов (используется JSONP)
            tweets_url + '?user_id=' + user_id + '&#038;page=' + page + '&#038;count=' + tweets_num + '&#038;callback=?',
            function(data) {
                $(data).each(function(i, tweet) {
                    //формируем ссылки
                    var text = tweet.text.replace(pattern, '&lt;a href="$1" target="_blank"&gt;$1&lt;/a&gt;');
                    //вставляем твит в список
                    container.append('&lt;div class="tweet"&gt;' + text + '&lt;/div&gt;');
                });
                //прячем загрузчик
                loader.addClass('hidden');
            }
        );
    }
});</pre>
<p>Прежде всего, мы подготавливаем данные, которые нужны для работы с Twitter API (строки 3-6). Для данного примера я использовал свою собственную ленту твитов, но вы можете вывести любую другую. Также не принципиально сколько твитов загружать за раз, главное, чтобы после первоначальной загрузки появилась полоса прокрутки.</p>
<p>Для получения твитов используем метод <code>getJSON</code> (строки 33-46, библиотека jQuery).</p>
<p>В первом её параметре передаём запрос на получение твитов. В него мы включаем:<br />
- id пользователя (<code>'?user_id=' + user_id</code>);<br />
- номер страницы (<code>'&#038;page=' + page</code>);<br />
- количество твитов на странице (<code>'&#038;count=' + tweets_num</code>);<br />
- имя функции, которая будет вызвана после получения данных (<code>'&#038;callback=?'</code>) – его jQuery формирует автоматически и подставляет вместо знака вопроса.</p>
<p>После получения твитов нам остается только добавить их в список (строки 36-42). При этом, мы ищем ссылки в тексте твитов и обрамляем их тегом <code>&lt;a&gt;</code>.</p>
<p>Завершающий этап – установка обработчика для события <code>scroll</code> (строки 19-28).</p>
<p>Здесь нужно только проверить достигнут конец списка или нет. Если достигнут, показываем загрузчик (убираем класс <code>hidden</code>) и вызываем функцию <code>get_tweets</code>, которой передаём номер нужно страницы. В противном случае, не делаем ничего.</p>
<p>Всё. Можно считать, что виджет в рабочем состоянии. Конечно, перед размещением на рабочем сайте нужно будет его немного доработать, например, добавить вывод сообщение об ошибке при отсутствии доступа к twitter&#039;у. Но, думаю, с этой задачей вы легко справитесь сами <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><strong>Успехов!</strong></p>
<p><em>Интересное</em></p>
<p>Глянцевая и матовая <a href="http://imagebook.ru/">печать фотокниг</a> и свадебных фотоальбомов</p>
<p>Любителям страйкбола будет интересно почитать про <a href="http://battleteam.ru/viewtopic.php?t=74">камуфляж Горка</a> его расцветки и разновидности.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/javascript-vidzhet-beskonechnaya-zagruzka-tvitov.html/feed</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Небольшой эксперимент с использованием data: URL</title>
		<link>http://www.simplecoding.org/nebolshoj-eksperiment-s-ispolzovaniem-data-url.html</link>
		<comments>http://www.simplecoding.org/nebolshoj-eksperiment-s-ispolzovaniem-data-url.html#comments</comments>
		<pubDate>Mon, 21 Mar 2011 08:52:15 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[Web разработка]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=1196</guid>
		<description><![CDATA[В последнее время всё больше внимания уделяется клиентской оптимизации сайтов. Я не могу сказать, что раньше ею никто не занимался, скорее, наоборот, с появлением широкополосного доступа к Internet часть проблем решилась сама собой. Но появление новых технологий, предоставляет новые возможности, которыми имеет смысл пользоваться. К сожалению, не всегда есть возможность проигнорировать устаревшие браузеры (главным образом [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_1197" class="wp-caption alignnone" style="width: 300px"><img src="http://www.simplecoding.org/wp-content/uploads/2011/03/data_uri.png" alt="data uri" title="data uri" width="290" height="255" class="size-full wp-image-1197" style="float:left" /><p class="wp-caption-text"> </p></div>
<p>В последнее время всё больше внимания уделяется <strong>клиентской оптимизации сайтов</strong>. Я не могу сказать, что раньше ею никто не занимался, скорее, наоборот, с появлением широкополосного доступа к Internet часть проблем решилась сама собой. Но появление новых технологий, предоставляет новые возможности, которыми имеет смысл пользоваться.</p>
<p>К сожалению, не всегда есть возможность проигнорировать устаревшие браузеры (главным образом речь идет о IE6 и 7). И это сильно замедляет использование новых стандартов.</p>
<p>Ситуация довольно сложная. Большинство владельцев ресурсов не согласятся потерять часть аудитории (пусть даже небольшую) только потому, что разработчик решил внедрить новую технологию. Но не все понимают, что использование устаревших технологий делает менее комфортной работу посетителей с нормальными браузерами. В частности, время загрузки страницы для них окажется больше, чем могло бы быть.</p>
<p>Поэтому оптимальным решением было бы автоматическое переключение технологий в зависимости от возможностей браузера.</p>
<p>Об одной из таких технологий и пойдёт речь в этой статье. Называется она <strong>data: URL</strong>.<br />
<span id="more-1196"></span></p>
<p><a href="http://ru.wikipedia.org/wiki/Data:_URL">data:URL</a> представляет собой схему, позволяющую включать произвольные данные непосредственно в строку URL. Т.е. можно разместить небольшие картинки, которые используются для оформления страницы, прямо в файл стилей и, тем самым, уменьшить количество запросов к серверу.</p>
<p>Для себя задачу я ставил достаточно просто. Проверить, насколько сложно будет обеспечить одинаковый вид страницы во всех браузерах, начиная с IE6.</p>
<p>Сразу выкладываю ссылку на архив с примером, который я использовал для экспериментов.</p>
<p><a href='http://www.simplecoding.org/wp-content/uploads/2011/03/data_url.zip'><img src="http://www.simplecoding.org/wp-content/themes/three_cols/images/download_btn_blue.png" alt="архив с исходным кодом" /></a></p>
<h2>Рассмотрим тестовую страницу</h2>
<pre class="brush: html">&lt;!DOCTYPE html&gt;

&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;CSS clip&lt;/title&gt;
    &lt;meta charset="utf-8" /&gt;
&lt;/head&gt;

&lt;body&gt;

&lt;div id="social_icons"&gt;
    &lt;a href="#" class="twitter icon"&gt;&lt;/a&gt;
    &lt;a href="#" class="facebook icon"&gt;&lt;/a&gt;
    &lt;a href="#" class="bobrdobr icon"&gt;&lt;/a&gt;
    &lt;a href="#" class="memori icon"&gt;&lt;/a&gt;
    &lt;a href="#" class="delicious icon"&gt;&lt;/a&gt;
    &lt;a href="#" class="stumbleupon icon"&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Она содержит шесть ссылок, которые нужно показать в виде иконок на социальные сервисы.</p>
<p>Делается это достаточно просто. Для каждой ссылки задаётся ширина, высота и фоновое изображение (иконка).</p>
<p>При этом браузер загрузит каждый файл, который будет указан в свойстве <code>background-image</code>. Т.е. если у нас шесть иконок, то будет отправлено шесть запросов серверу. Учитывая, что размеры иконок редко превышают несколько кБ, загружать их по одной не выгодно.</p>
<p>Наиболее распространённым методом оптимизации в таких случаях является использование <strong>CSS спрайтов</strong>. При этом все картинки объединяются в одну, а нужный фрагмент показывают с помощью свойства <code>background-position</code>.</p>
<p>Именно этот вариант я решил использовать для браузеров IE6 и 7, а для новых – передать иконки с помощью <code>data: URL</code>.</p>
<h2>Подготовка данных для использования в data: URL</h2>
<p>Тут всё достаточно просто. Нужно закодировать содержимое файла с картинкой с помощью base64 и вставить полученную строку в CSS файл.</p>
<p>В моем случае, исходное изображение выглядит следующим образом.</p>
<div id="attachment_1198" class="wp-caption alignnone" style="width: 74px"><img src="http://www.simplecoding.org/wp-content/uploads/2011/03/icons_sprites.png" alt="icons sprites" title="icons sprites" width="64" height="384" class="size-full wp-image-1198" /><p class="wp-caption-text"> </p></div>
<p><em>Примечание</em>. Я использовал коллекцию бесплатных иконок от <a href="http://www.wpzoom.com/wpzoom/500-free-icons-wpzoom-social-networking-icon-set/">wpzoom</a>.</p>
<p>На практике можно воспользоваться одним из сервисов, выполняющих эту операцию. Например, <a href="http://duris.ru/">duris.ru</a> или <a href="http://www.dopiaza.org/tools/datauri/">dopiaza.org</a>.</p>
<p>В результате у меня получилась такая таблица стилей.</p>
<pre class="brush: css">@charset 'utf-8';

.icon {
	width: 64px;
	height: 64px;
	display: block;
	float: left;
	margin: 10px;
}

div#social_icons a {
	background-image: url("data:image/png;base64,iVBORw......");
	background-repeat:no-repeat;
}
.twitter {
	background-position: 0 0;
}
.facebook {
	background-position: 0 -64px;
}
.bobrdobr {
	background-position: 0 -128px;
}
.memori {
	background-position: 0 -192px;
}
.delicious {
	background-position: 0 -256px;
}
.stumbleupon {
	background-position: 0 -322px;
}</pre>
<p><em>Обратите внимание</em>. Здесь не важно кодируете вы один файл со всеми иконками или каждую отдельно. Все данные будут переданы внутри CSS файла.</p>
<p><em>Рассмотрим стили подробнее</em>.</p>
<p>Для каждой ссылки мы указываем высоту (<code>width</code>) и ширину (<code>height</code>). При этом, нужно сделать ссылку блоковым элементом (<code>display: block</code>), иначе длина и высота применятся не будут. Чтобы расположить иконки в один ряд, используем обтекание (<code>float: left</code>).</p>
<p>Далее каждой ссылке устанавливаем фоновое изображение (<code>background-image</code>). В качестве значения <code>url</code> вставляем результат преобразования картинки. Я его сократил, т.к. он занимает около 19 кБ.</p>
<p>Затем с помощью <code>background-position</code> показываем нужный фрагмент картинки. В данном случае все иконки имеют размер 64х64 px и расположены вертикально, поэтому просто изменяем вертикальную координату на 64 px.</p>
<p>Остаётся подключить файл стилей к странице.</p>
<pre class="brush: html">&lt;link rel="stylesheet" type="text/css" href="styles.css" /&gt;</pre>
<p>Всё. В современных браузерах иконки отображаются правильно.</p>
<p>Для формирования страницы браузер выполняет <strong>два</strong> запроса к серверу. Первый – получение самой страницы, второй – получения файла стилей. При этом, файл стилей занимает 19,1 кБ (если его сжать, получится 14,4 кБ).</p>
<h2>Поддержка IE6 и 7</h2>
<p>Есть несколько вариантов решения этой задачи. Подробно они рассмотрены в статье <a href="http://webo.in/articles/habrahabr/46-cross-browser-data-url/">Кроссбраузерное использование data:URL</a>.</p>
<p>Я покажу один из самых простых вариантов, с заменой файла стилей.</p>
<p>Идея предельно простая. С помощью условных комментариев, браузерам IE6 и 7 указываем свой собственный CSS файл.</p>
<p>Выглядит это следующим образом.</p>
<pre class="brush: html">&lt;!--[if lt IE 8]&gt;&lt;link rel="stylesheet" type="text/css" href="ie_6_7_styles.css" /&gt;&lt;![endif]--&gt;
&lt;!--[if gte IE 8]&gt;&lt;link rel="stylesheet" type="text/css" href="styles.css" /&gt;&lt;![endif]--&gt;
&lt;!--[if !IE]&gt;--&gt;&lt;link rel="stylesheet" type="text/css" href="styles.css" /&gt;&lt;!--&lt;![endif]--&gt;</pre>
<p>В результате, современные браузеры загрузят файл <code>styles.css</code>, а шестая и седьмая версии IE – <code>ie_6_7_styles.css</code>.</p>
<p>В этих стилях отличается только свойство <code>background-image</code>. Вместо <code>data:URL</code> указываем файл с иконками.</p>
<pre class="brush: css">div#social_icons a {
    background-image: url("icons/icons_sprites.png");
    background-repeat:no-repeat;
}</pre>
<p>Теперь во всех браузерах иконки отображаются одинаково.</p>
<h2>Результаты</h2>
<p>Должен отметить, что в данном случае, результаты получились не очень впечатляющие.</p>
<p>Безусловно, при использовании <code>data: URL</code> количество запросов уменьшилось (на один), но объём передаваемых данных увеличился практически на 5 кБ (исходный файл <code>icons_sprites.png</code> «весит» 13,9 кБ, а после base64 преобразования он занимает около 19 кБ).</p>
<p>Т.е. получается, что если фоновые изображения хорошо укладываются в CSS спрайты, то эффект от применения <code>data: URL</code> будет минимальным. Точнее, в некоторых случаях можно получить полностью противоположный эффект, т.к. время загрузки файла со стилями увеличится, и посетитель будет какое-то время смотреть на страницу без стилей вообще.</p>
<p>Кроме того, усложняется процесс обновления картинок, т.к. они будут кешироваться вместе с CSS файлом. (Эта проблема решаемая, но выходит за рамки данной статьи).</p>
<p>С другой стороны, в этой статье рассмотрен очень простой пример. Для сложного сайта файлов со спрайтами может получиться довольно много и в этом случае эффект от использования data: URL будет выше за счёт уменьшения количества запросов.</p>
<p>К тому же, если бы не нужна была поддержка IE6, 7, то можно было бы вообще не заниматься созданием файла со спрайтами и установкой <code>background-position</code>, а просто передавать изображения в <code>background-image</code> для соответствующих элементов.</p>
<p>В целом, я не уверен, что в ближайшее время начнется массовое использование <code>data: URL</code>. Тем не менее, технология очень интересная.</p>
<p><strong>Успехов!</strong></p>
<p><strong>Интересно почитать</strong></p>
<p>Хотите сделать карьеру в IT? <a href="http://it-centre.net">Курсы программистов</a> будут хорошей стартовой точкой.</p>
<p>Нужна декларация <a href="http://online-nalogi.ru/3_ndfl_prodazha_kvartiry"> 3-ндфл «продажа квартиры»</a>? Заполним за сутки и вышлем на емейл.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/nebolshoj-eksperiment-s-ispolzovaniem-data-url.html/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Galleria &#8211; плагин для создания галерей с картинками</title>
		<link>http://www.simplecoding.org/galleria-plagin-dlya-sozdaniya-galerej-s-kartinkami.html</link>
		<comments>http://www.simplecoding.org/galleria-plagin-dlya-sozdaniya-galerej-s-kartinkami.html#comments</comments>
		<pubDate>Mon, 07 Mar 2011 21:09:17 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Web разработка]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=1188</guid>
		<description><![CDATA[Количество различных JavaScript плагинов для просмотра картинок на сегодняшний день просто огромно. И если вы начнете читать их обзоры, то на выбор подходящего решения может уйти гораздо больше времени чем на подключение и настройку самого плагина. Кроме того, несмотря на все разнообразие, часто не удаётся найти идеально подходящего варианта. В каких-то случаях ограничены возможности оформления [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_1189" class="wp-caption alignnone" style="width: 245px"><img src="http://www.simplecoding.org/wp-content/uploads/2011/03/galleria.jpg" alt="galleria" title="galleria" width="235" height="149" class="size-full wp-image-1189" style="float:left" /><p class="wp-caption-text"> </p></div>
<p>Количество различных <strong>JavaScript плагинов для просмотра картинок</strong> на сегодняшний день просто огромно. И если вы начнете читать их обзоры, то на выбор подходящего решения может уйти гораздо больше времени чем на подключение и настройку самого плагина.</p>
<p>Кроме того, несмотря на все разнообразие, часто не удаётся найти <em>идеально</em> подходящего варианта. В каких-то случаях ограничены возможности оформления (нельзя изменить разметку), в каких-то нет подходящих опций или нет возможности вывести вместе с рисунком дополнительную информацию. В общем, подогнать галерею под конкретный сайт бывает непросто.</p>
<p>Можно, конечно, написать собственную реализацию такого плагина, но это процесс трудоемкий (если делать качественно) и, скорее всего, код процентов на 90 будет повторять то, что есть в других плагинах.</p>
<p>В таких случаях гораздо предпочтительнее использовать фреймворки. Об одном из них и пойдет речь в этой статье.<br />
<span id="more-1188"></span><br />
Фреймворк называется <a href="http://galleria.aino.se/">Galleria</a> и представляет собой плагин для библиотеки <strong>jQuery</strong>.</p>
<p>Его основными преимуществами являются <strong>поддержка тем оформления</strong>, <strong>собственный API</strong> и <strong>большое количество настроек</strong>.</p>
<p>Подключить <strong>Galleria</strong> не сложнее чем любой другой плагин, но внешний вид галереи будет зависеть от используемой темы.</p>
<p>Чтобы получить более полное представление о фреймворке рассмотрим небольшой пример, который включает создание собственной темы и использование нескольких очень полезных возможностей Galleria.</p>
<p><em>Примечание</em>. Эта статья ни в коем случае не заменяет <a href="http://galleria.aino.se/docs/1.2/">официальную документацию</a> и не содержит описание всех возможностей фреймворка. С другой стороны, некоторые вопросы интеграции фреймворка со страницей здесь рассмотрены более подробно.</p>
<h2>Постановка задачи</h2>
<p>Допустим, у нас есть сайт на котором мы хотим показывать галерею. При этом, в галерее необходимо показать рисунки для которых нет миниатюр на страницах (возможно, мы хотим разместить ссылку на галерею в сайдбаре и показывать какую-то заранее определенную группу картинок). Кроме того, для каждого рисунка есть несколько блоков дополнительной информации, которую необходимо показать рядом с рисунком.</p>
<p>Т.е. должно получиться примерно следующий результат.</p>
<p><a href="http://demosites.simplecoding.org/galleria/"><img src="http://www.simplecoding.org/wp-content/themes/three_cols/images/demo_btn_green.png" alt="демонстрационный пример" /></a></p>
<p>Если интересно, можете скачать архив с этим примером.</p>
<p><a href='http://www.simplecoding.org/wp-content/uploads/2011/03/galleria.zip'><img src="http://www.simplecoding.org/wp-content/themes/three_cols/images/download_btn_blue.png" alt="архив с исходным кодом" /></a></p>
<p>Теперь рассмотрим как решается эта задача с помощью Galleria.</p>
<h2>Подключаем фреймворк.</h2>
<p>На страницу добавляем блок для галереи и ссылку с помощью которой будем эту галерею открывать.</p>
<pre class="brush: html">&lt;div id="content"&gt;
    &lt;a href="#" id="openGallery"&gt;Открыть галерею&lt;/a&gt;
    &lt;div id="gallery"&gt;&lt;/div&gt;
&lt;/div&gt;</pre>
<p>После этого распаковываем архив с фреймворком в папку galleria и подключаем 3 JS-файла.</p>
<pre class="brush: html">&lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"&gt;&lt;/script&gt;
&lt;script src="galleria/galleria-1.2.2.min.js"&gt;&lt;/script&gt;
&lt;script src="init.js"&gt;&lt;/script&gt;</pre>
<p>Здесь все как обычно. Сначала загружаем jQuery, затем плагин Galleria и скрипт init.js (он выполняет подключение и настройку галереи).</p>
<h2>Подготовка данных для галереи</h2>
<p>В нашем случае миниатюр картинок на странице нет, поэтому фреймворку необходимо каким-то образом передать информацию о них. Для этого создадим JS объект с их данными.</p>
<pre class="brush: javascript">
    var images = [
        {
            image: 'images/spring_1.jpg',
            thumb: 'images/spring_1t.jpg',
            title: 'Первая картинка',
            description: 'Описание первой картинки',
            size: '450x338',
            link: 'images/spring_1.jpg'
        },
        {
            image: 'images/spring_2.jpg',
            thumb: 'images/spring_2t.jpg',
            title: 'Вторая картинка',
            description: 'Описание второй картинки',
            size: '450x360',
            link: 'images/spring_2.jpg'
        },
...
    ];
</pre>
<p>Думаю, несложно догадаться почему разработчиками выбран именно такой вариант передачи данных. Если вы получаете данные от сервера в <strong>JSON</strong> формате, то получить такой объект можно с помощью одного вызова функции <code>eval</code>.</p>
<p><em>Обратите внимание!</em> Не все поля в этой структуре обязательные, вы можете добавлять сколько угодно своих собственных полей с данными. В минимальном варианте для работы плагина необходимо поле <code>image</code> и, если вы хотите показать слайдер с миниатюрами картинок – <code>thumb</code>.</p>
<p>Теперь подключаем галерею</p>
<pre class="brush: javascript">
    var gallery = $("#gallery");

    Galleria.loadTheme('galleria/themes/simplecoding/galleria.simplecoding.js');

    $('#openGallery').click(function() {
        $("#gallery").galleria({
            data_source: images,
            width: 800,
            height: 500,
            clicknext: true
        });
        return false;
    });
</pre>
<p>Перед подключением галереи необходимо загрузить тему. Её создание мы рассмотрим чуть ниже, сейчас только отметим, что для загрузки необходимо указать основной JS-файл темы.</p>
<p>Т.к. нам нужно чтобы галерея открывалась по клику на ссылке, устанавливаем соответствующий обработчик, и в нём вызываем метод <code>galleria</code> для блока в котором будет находится галерея (строка 6).</p>
<p>В параметрах этого метода передаём настройки галереи. Здесь:</p>
<p><code>data_source</code> – имя переменной в которой находятся данные рисунков;<br />
<code>width</code> и <code>height</code> – длина и ширина галереи;<br />
<code>clicknext</code> – если этот параметр равен <code>true</code>, то клик по картинке будет показывать следующую картинку (дублирует кнопку Next).</p>
<p>Вообще параметров довольно много, их полный список можно посмотреть <a href="http://galleria.aino.se/docs/1.2/options/">здесь</a>.</p>
<h2>Оформление галереи (создание собственной темы)</h2>
<p>Создать тему не сложно. В папке <code>galleria/themes/</code> создаёте папку с названием вашей темы (в данном случае &#8211; <code>simplecoding</code>). В этой папке должен находится основной файл темы &#8211; <code>galleria.simplecoding.js</code>.</p>
<p>Практически наверняка вы захотите добавить файл стилей и различные картинки и иконки для оформления галереи.</p>
<p>В качестве основы для данного примера я взял код из <a href="http://galleria.aino.se/docs/1.2/themes/creating_a_theme/">официальной документации</a>, а также картинки и стили из темы <code>classic</code>, которая поставляется вместе с плагином (стили, естественно, пришлось немного изменить и дополнить).</p>
<p>Рассмотрим основной скрипт &#8211; galleria.simplecoding.js</p>
<pre class="brush: javascript">(function($) {
Galleria.addTheme({
    name: 'simplecoding',
    author: 'Statsenko Vladimir, http://www.simplecoding.org',
    version: 1,
    css: 'galleria.simplecoding.css',
    defaults: {
        transition: 'fade',
        imagecrop: true,
        _my_color: 'black'
    },
    init: function(options) {

        //добавляем заголовок
		this.addElement('title');
		this.prependChild('container', 'title');

		//добавляем кнопку "Закрыть"
		this.addElement('close');
		this.prependChild('container', 'close');
		this.$('close').html('&lt;a href="#"&gt;&nbsp;&lt;/a&gt;');

        //добавляем поле для описания и размера картинки
		this.addElement('desc');
		this.appendChild('stage', 'desc');

        var overlay = $('&lt;div id="overlay"&gt;&lt;/div&gt;');
        overlay.add('.galleria-close').click(this.proxy(function(e) {
            this.$('container').toggleClass('hidden');
            overlay.toggleClass('hidden');
            e.stopPropagation();
            return false;
        }));

        this.$('container')
            .css('background-color', options._my_color)
            .parent().parent().append(overlay);

        // bind a loader animation:
        this.bind(Galleria.LOADSTART, function(e) {
            if (!e.cached) {
                this.$('loader').show();
            }
        });
        this.bind(Galleria.LOADFINISH, function(e) {
            this.$('loader').hide();
            var imageData = this.getData();
			this.$('title').html(imageData.title);
			this.$('desc').html(imageData.description + ' ' + imageData.size);
        });
    }
});
}(jQuery));</pre>
<p>Как видите, для создание темы используется метод <code>addTheme</code> (строка 2) в параметрах которого мы указываем её название, имя автора, имя файла стилей (строка 6), различные параметры и метод инициализации (параметр <code>init</code>, строка 12).</p>
<p>Именно в этом методе выполняется изменение разметки галереи, назначаются обработчики событий и т.п.</p>
<p>Рассмотрим этот метод подробнее.</p>
<p>Прежде всего, взгляните на <a href="http://galleria.aino.se/docs/1.2/references/dom/">разметку галереи</a>, которая создаётся по-умолчанию.</p>
<p>В нашем случае необходимо добавить название картинки и кнопку «Закрыть» над картинкой и текст с подробным описанием – под ней.</p>
<p>Поэтому мы добавляем 3 поля – <code>title</code>, <code>close</code> и <code>desc</code> (строки 14-25). При этом используются методы <code>addElement</code> (создает новый элемент), <code>prependChild</code> (вставляет новый элемент перед указанным элементом) и <code>appendChild</code> (вставляет новый элемент после указанного объекта).</p>
<p>В первом параметре методов <code>prependChild</code> и <code>appendChild</code> необходимо указать имя блока перед (после) которого нужно вставить новый элемент. При этом учтите, что плагин добавляет ко всем названиям блоков приставку <code>galleria-</code> . Т.е. если вы посмотрите на разметку с помощью firebug, то блоки будут выглядеть примерно так.</p>
<pre class="brush: html">&lt;div class="galleria-title"&gt;Пятая картинка&lt;/div&gt;</pre>
<p>Теперь рассмотрим код, позволяющий <strong>закрыть галерею</strong> (строки 27-38).</p>
<p>В данном случае мы используем немного нестандартное решение. У нас есть кнопка «Закрыть», которую мы поместили в правый верхний угол галереи. В дополнение к этой кнопке создадим полупрозрачный слой (<code>overlay</code>), который с одной стороны будет затенять страницу, а с другой – закрывать галерею при клике по нему.</p>
<p>Для создания слоя используем функцию <code>$</code> библиотеки <strong>jQuery</strong>. Затем назначаем ему и кнопке «Закрыть» обработчик события <code>click</code>.</p>
<p>Обратите внимание, при создании этого обработчика мы используем метод <code>proxy</code> объекта <code>Galleria</code> (строка 28). Этот метод позволяет обращаться к текущему экземпляру объекта <code>Galleria</code> внутри обработчика клика с помощью <code>this</code>. Если не использовать <code>proxy</code>, то <code>this</code> внутри обработчика клика будет указывать либо на кнопку «Закрыть», либо на <code>overlay</code>.</p>
<p>Также отметьте, как выполняется обращение к элементам галереи. Например, переключение класса hidden у контейнера.</p>
<pre class="brush: javascript">this.$('container').toggleClass('hidden');</pre>
<p>Здесь вызывается метод <code>$</code> плагина, а не функция <code>$</code> библиотеки <strong>jQuery</strong>. Но, также как и стандартная функция, этот метод возвращает объект <code>jQuery</code>, т.е. вы сможете использовать весь функционал этой библиотеки.</p>
<p><strong>Теперь добавляем обработчики ещё для двух событий.</strong></p>
<p>При возникновении события <code>Galleria.LOADSTART</code> (начало загрузки изображения) показываем анимированный загрузчик (строки 40-44).</p>
<p>А после загрузки изображения (событие <code>Galleria.LOADFINISH</code>) устанавливаем заголовок и описание текущей картинки (строки 45-50).</p>
<p>Информацию, связанную с текущей картинкой (мы её указали при в файле <code>init.js</code>), можно получить с помощью метода <code>this.getData()</code>. После этого можно обращаться к любым полям структуры, например, так <code>imageData.title</code>.</p>
<h2>CSS стили</h2>
<p>Я не буду подробно описывать все стили, которые здесь используются. Большинство из них взято из темы classic. Приведу те, которые использовались для оформления новых элементов.</p>
<pre class="brush: css">#overlay {
    width: 100%;
    height: 100%;
    z-index: 9;
    background-color: #000;
    opacity: 0.3;
    position: absolute;
    top: 0;
    left: 0;
}

.hidden {
    display: none;
}

.galleria-close {
	background-image: url(classic-map.png);
	background-position: -753px -11px;
	width: 9px;
	height: 9px;
	margin: 0.5em;
	float: right;
}

.galleria-close a {
	display: block;
	text-decoration: none;
}

.galleria-title, .galleria-desc {
	color: #fff;
	font-family: Verdana, sans-serif;
	text-align: center;
	padding: 3px;
}</pre>
<p>Как видите, никаких особых хитростей здесь нет.</p>
<p>Для полупрозрачного слоя используем абсолютное позиционирование и 100% длину и ширину, чтобы он закрыл всё окно. С помощью <code>z-index</code> размещаем его под галереей.</p>
<p>Блок с галереей делаем невидимым с помощью класса <code>hidden</code>.</p>
<p>Для кнопки «Закрыть» указываем фоновое изображение и соответствующий размер.</p>
<p>А для дополнительных надписей устанавливаем параметры шрифтов и отступы.</p>
<h2>Заключение</h2>
<p>Возможно, после прочтения этой статьи у вас возник вопрос: «Зачем так заморачиваться?». Действительно, большинство плагинов для создания галерей можно просто подключить и они будут работать. При этом никаких тем создавать не нужно.</p>
<p>Но это простота кажущаяся. Как только вы захотите что-нибудь изменить в таком «простом» плагине, сразу столкнетесь с необходимостью править его исходники, а это занятие гораздо более трудоёмкое чем создание темы для Galleria.</p>
<p>К тому же, у вас появляется возможность создать действительно оригинальное решение для работы с картинками и сделать ваш ресурс действительно запоминающимся!</p>
<p><strong>Всех читательниц поздравляю с Праздником весны!<br />
Удачи и хорошего настроения!</strong></p>
<p><em>Интересно почитать</em></p>
<p><a href="http://it-centre.net">Обучение программированию</a> поможет стать настоящим IT специалистом.</p>
<p>Заполнение <a href="http://online-nalogi.ru/3_ndfl_prodazha_avtomobilja"> 3-ндфл 2011 на продажу автомобиля</a> плюс инструкции «Как отчитаться в налоговой»</p>
]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/galleria-plagin-dlya-sozdaniya-galerej-s-kartinkami.html/feed</wfw:commentRss>
		<slash:comments>24</slash:comments>
		</item>
		<item>
		<title>JavaScript и jQuery: перемещение блоков</title>
		<link>http://www.simplecoding.org/javascript-i-jquery-peremeshhenie-blokov.html</link>
		<comments>http://www.simplecoding.org/javascript-i-jquery-peremeshhenie-blokov.html#comments</comments>
		<pubDate>Sat, 08 Jan 2011 09:08:51 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Web разработка]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=1167</guid>
		<description><![CDATA[В этот раз я покажу пример небольшого скрипта, позволяющего перемещать HTML блоки на странице. Когда возникает подобная задача, первое что приходит в голову (по крайней мере мне ) – использовать готовые плагины. Например, jQuery Sortable. Что ни говори, решение довольно удобное, от пользователя требуется только перетащить объект с помощью мышки. Но тут есть один недостаток. [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_1168" class="wp-caption alignnone" style="width: 310px"><img src="http://www.simplecoding.org/wp-content/uploads/2011/01/jquery_blocks_movement.png" alt="jquery blocks movement" title="jquery blocks movement" width="300" height="209" class="size-full wp-image-1168" style="float:left" /><p class="wp-caption-text"> </p></div>
<p>В этот раз я покажу пример небольшого скрипта, позволяющего <strong>перемещать HTML блоки на странице</strong>.</p>
<p>Когда возникает подобная задача, первое что приходит в голову (по крайней мере мне <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ) – использовать готовые плагины. Например, <a href="http://www.simplecoding.org/jquery-plaginy-sortirovka-i-redaktirovanie-spiska-chast-vtoraya.html">jQuery Sortable</a>. Что ни говори, решение довольно удобное, от пользователя требуется только перетащить объект с помощью мышки.</p>
<p>Но тут есть один недостаток. Если размеры блоков, которые нужно перемещать достаточно большие (например, больше половины высоты окна браузера), то пользоваться такими плагинами становится не удобно.</p>
<p>В такой ситуации, на мой взгляд, лучше добавить к каждому блоку ссылки «Вверх» и «Вниз» с помощью которых и будет выполняться перемещение блоков.</p>
<p>Именно такой вариант мы рассмотрим в этой статье.</p>
<p>Посмотреть результат можно на демонстрационной страничке<br />
<span id="more-1167"></span><br />
<a href="http://demosites.simplecoding.org/jquery_blocks_movement/"><img src="http://www.simplecoding.org/wp-content/themes/three_cols/images/demo_btn_green.png" alt="демонстрационный пример" /></a></p>
<p>И, если есть желание, можете скачать архив с исходниками.</p>
<p><a href='http://www.simplecoding.org/wp-content/uploads/2011/01/jquery_blocks_movement.zip'><img src="http://www.simplecoding.org/wp-content/themes/three_cols/images/download_btn_blue.png" alt="архив с исходным кодом" /></a></p>
<h2>Начнём с разметки страницы</h2>
<p>Чтобы сделать блоки достаточно большими я просто разместил в них картинки, точнее в данном случае каждая картинка представляет собой отдельный блок.</p>
<pre class="brush: html">&lt;!DOCTYPE html&gt;

&lt;html&gt;
&lt;head&gt;
    &lt;meta charset="utf-8" /&gt;
    &lt;title&gt;Перемещение блоков с помощью JS&lt;/title&gt;
    &lt;link rel="stylesheet" type="text/css" href="styles.css" /&gt;
&lt;/head&gt;

&lt;body&gt;
    &lt;div id="images"&gt;
        &lt;img src="images/1t.jpg" alt="картинка 1" /&gt;
        &lt;img src="images/2t.jpg" alt="картинка 2" /&gt;
        &lt;img src="images/3t.jpg" alt="картинка 3" /&gt;
    &lt;/div&gt;

    &lt;script src="http://yandex.st/jquery/1.4.4/jquery.js"&gt;&lt;/script&gt;
    &lt;script src="main.js"&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Как видите, разметка предельно простая. На странице находятся три картинки и подключены два JS файла (библиотека <code>jQuery</code> и наш скрипт <code>main.js</code>, с кодом для перемещения блоков).</p>
<p>Обратите внимание, я не вставлял ссылки «Вверх», «Вниз» на страницу. Перемещение блоков выполняется с помощью JavaScript, поэтому если у пользователя отключена поддержка JS, то и ссылки видеть ему не нужно.</p>
<h2>Теперь рассмотрим перемещение блоков</h2>
<p>Скрипт main.js.</p>
<pre class="brush: javascript">$(function() {
    var images = $('img');
    images.wrap('&lt;div class="controls" /&gt;');
    $('&lt;a class="down" href="#"&gt;Вниз&lt;/a&gt;').insertAfter(images);
    $('&lt;a class="up" href="#"&gt;Вверх&lt;/a&gt;').insertAfter(images);

    $('.up').click(function() {
        var currentImgBlock = $(this).parent();
        var prevImgBlock = currentImgBlock.prev();
        swap(currentImgBlock, prevImgBlock);
        return false;
    });

    $('.down').click(function() {
        var currentImgBlock = $(this).parent();
        var nextImgBlock = currentImgBlock.next();
        swap(nextImgBlock, currentImgBlock);
        return false;
    });
});

function swap(a, b) {
    if (a.size() &gt; 0 &#038;&#038; b.size() &gt; 0) {
        a.insertBefore(b);
    }
}</pre>
<p>Прежде всего, необходимо добавить ссылки. И, чтобы было удобнее выполнять перемещение, вокруг каждого изображения создадим <code>div</code> и ссылки будем добавлять в него.</p>
<p>Все эти операции выполняются с помощью четырёх строк кода (строки 2-5). В результате для каждого получим такую разметку.</p>
<pre class="brush: html">&lt;div class="controls"&gt;
    &lt;img alt="картинка 1" src="images/1t.jpg"&gt;
    &lt;a href="#" class="up"&gt;Вверх&lt;/a&gt;
    &lt;a href="#" class="down"&gt;Вниз&lt;/a&gt;
&lt;/div&gt;</pre>
<p>Теперь назначаем обработчики для ссылок «Вверх» и «Вниз».</p>
<p>Код этих обработчиков практически одинаков, за исключением того, что при клике по ссылке «Вверх» мы должны получить текущий блок (в котором находится ссылка) и предыдущий, а при клике по ссылке «Вниз» &#8211; текущий и следующий.</p>
<p>После этого, передаём эти блоки функции swap, которая и выполняет их перемещение. Обратите внимание, что порядок в котором передаются блоки важен. Функция использует метод <code>insertBefore</code>, поэтому первым необходимо передавать блок, который должен оказаться выше.</p>
<p>Как видите, ничего сложного. Наверное, имеет смысл при клике по ссылке запускать какую-нибудь анимацию, чтобы было видно направление перемещения, но это тема отдельной статьи.</p>
<p>Если есть вопросы, замечания или советы, пишите. Буду рад обсудить!</p>
<p><strong>Успехов!</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/javascript-i-jquery-peremeshhenie-blokov.html/feed</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Google Maps: выделение областей на карте</title>
		<link>http://www.simplecoding.org/google-maps-vydelenie-oblastej-na-karte.html</link>
		<comments>http://www.simplecoding.org/google-maps-vydelenie-oblastej-na-karte.html#comments</comments>
		<pubDate>Mon, 27 Dec 2010 08:20:47 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Web разработка]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=1164</guid>
		<description><![CDATA[О сервисах Google Maps и Яндекс.Карты слышали, наверное, практически все пользователи интернета. Но если для рядового пользователя их возможности ограничиваются стандартным интерфейсом, то для разработчиков всё гораздо интереснее. Оба сервиса предоставляют API, который позволяет получить дополнительную информацию, изменить внешний вид и работу карт. Сегодня я хочу показать небольшой пример, позволяющий посетителю выделить область на карте [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_1165" class="wp-caption alignnone" style="width: 292px"><img src="http://www.simplecoding.org/wp-content/uploads/2010/12/google_maps_circle_logo.jpg" alt="google maps circle logo" title="google maps circle logo" width="282" height="202" class="size-full wp-image-1165" style="float:left" /><p class="wp-caption-text"> </p></div>
<p>О сервисах <a href="http://code.google.com/intl/ru/apis/maps/documentation/javascript/">Google Maps</a> и <a href="http://api.yandex.ru/maps/">Яндекс.Карты</a> слышали, наверное, практически все пользователи интернета. Но если для рядового пользователя их возможности ограничиваются стандартным интерфейсом, то для разработчиков всё гораздо интереснее.</p>
<p>Оба сервиса предоставляют API, который позволяет получить дополнительную информацию, изменить внешний вид и работу карт.</p>
<p>Сегодня я хочу показать небольшой пример, позволяющий посетителю выделить область на карте (использоваться будут <strong>Google Maps</strong>). В дальнейшем, эту область можно сохранить в базе данных вашего сайта.</p>
<p>Прежде всего, сформулируем задачу.</p>
<p>Посетителю нужно каким-то образом указать какую область он хочет выделить. На мой взгляд, для этих целей удобно использовать многоугольники и окружности. Первые позволяют точнее выделить нужную область, вторые – требуют меньше действий от пользователя (достаточно указать центр и задать радиус).</p>
<p>Т.к. для обоих случаев API практически одинаков, рассмотрим вариант с окружностью.</p>
<p>Итак, <strong>принцип работы</strong> будет следующий.<br />
<span id="more-1164"></span><br />
1) Посетитель кликает по произвольной точке на карте, мы ставим на неё маркер (чтобы удобнее было ориентироваться) и считаем её центром области.</p>
<p>2) Посетитель кликает по любой точке на границе области. Мы рассчитываем расстояние от неё до центра (радиус) и строим окружность.</p>
<p>Если посетитель захочет изменить область, то ему будет достаточно снова сделать два клика. Мы убираем старую окружность и строим новую.</p>
<p>Поэкспериментировать с этим примером можно на демонстрационной страничке или, если хотите, качайте архив с исходными файлами.</p>
<p><a href="http://demosites.simplecoding.org/google_maps_circle/"><img src="http://www.simplecoding.org/wp-content/themes/three_cols/images/demo_btn_green.png" alt="демонстрационный пример" /></a> <a href='http://www.simplecoding.org/wp-content/uploads/2010/12/google_maps_circle.zip'><img src="http://www.simplecoding.org/wp-content/themes/three_cols/images/download_btn_blue.png" alt="архив с исходным кодом" /></a></p>
<h2>Переходим к реализации.</h2>
<p>Прежде всего, создадим страницу с картой.</p>
<pre class="brush: html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8" /&gt;
    &lt;title&gt;Окружности на Google Maps&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;div id="my_map" style="width:600px;height:400px"&gt;&lt;/div&gt;
    &lt;script src="main.js"&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Здесь всё предельно просто. Создаём блок для карты (my_map), указываем его размеры (600х400 px) и подключаем файл со скриптами (main.js), которые будут выполнять всю работу.</p>
<p>Рассмотрим подробнее main.js.</p>
<p>В первую очередь нам нужно подключить карту.</p>
<pre class="brush: javascript">var map, circle, circleOptions, setCenter, marker;

function initialize() {
    var myLatlng = new google.maps.LatLng(50.45127, 30.523368); //Kiev
    var myOptions = {
        zoom: 9,
        center: myLatlng,
        mapTypeId: google.maps.MapTypeId.HYBRID
    }
    map = new google.maps.Map(document.getElementById("my_map"), myOptions);
}

function loadScript() {
    var script = document.createElement("script");
    script.src = "http://maps.google.com/maps/api/js?sensor=false&#038;callback=initialize";
    document.body.appendChild(script);
}

window.onload = loadScript;</pre>
<p>Работает этот код следующим образом. При возникновении события <code>window.onload</code> (завершена загрузка страницы) будет вызвана функция <code>loadScript</code>, которая добавит в конец страницы тег <code>script</code>, подключающий Google Maps.</p>
<p>Обратите внимание на GET параметр <code>callback</code>. В нём передаётся название функции (<code>initialize</code>), которая будет вызвана сразу после загрузки скрипта.</p>
<p>В этой функции (<code>initialize</code>) мы указываем настройки (координаты центра, приближение, тип карты) и создаём карту (строка 10).</p>
<p>В результате внутри блока <code>my_map</code> появится обычная карта Google.</p>
<h2>Переходим к созданию окружности.</h2>
<p>Прежде всего, немного теории.</p>
<p>С точки зрения API Google Maps, окружность (также как и многоугольник) является оверлеем (overlay). Для её создания используется класс <a href="http://code.google.com/intl/ru/apis/maps/documentation/javascript/reference.html#Circle">google.maps.Circle</a>, а однозначно задать её размещение можно с помощью центральной точки &#8211; <code>center</code> (объект типа <code>LatLng</code> в котором хранится широта и долгота) и радиуса &#8211; <code>radius</code> (в метрах).</p>
<p>Кроме того, в большинстве случаев желательно указать цвет окружности, её заливку и прозрачность. Параметры – <code>fillColor</code>, <code>fillOpacity</code>, <code>strokeColor</code> и <code>strokeOpacity</code>.</p>
<p>В нашем случае посетитель строит окружность с помощью кликов по карте, значит, нужно установить обработчик события click и в нём выполнять настройку и создание окружности.</p>
<p>Обработчик события <code>click</code> получит параметр <code>event</code>, который содержит координаты точки, по которой кликнул посетитель.</p>
<p>После второго клика мы получим координаты второй точки и сможем рассчитать расстояние между ними, т.е. радиус окружности.</p>
<p>Теперь взгляните на код.</p>
<pre class="brush: javascript">function initialize() {
    ......
    setCenter = true;

    circleOptions = {
        fillColor:"#00AAFF",
        fillOpacity:0.5,
        strokeColor:"#FFAA00",
        strokeOpacity:0.8,
        strokeWeight:2,
        clickable:false
    }

    google.maps.event.addListener(map, 'click', function(event) {
        if (setCenter) {
            if (marker != undefined) {
                marker.setMap(null);
            }
			marker = new google.maps.Marker({
				position:event.latLng,
				clickable:false
			});
			marker.setMap(map);
            circleOptions.center = event.latLng;
            setCenter = false;
        }
        else {
            //рассчитываем расстояние между точками
            var radius = distHaversine(circleOptions.center, event.latLng)
            circleOptions.radius = radius*1000;
            if (circle != undefined) {
                circle.setMap(null);
            }
            circle = new google.maps.Circle(circleOptions);
            circle.setMap(map);
            setCenter = true;
        }
    });
}</pre>
<p>Нам нужно отличить первый клик от второго. Для этого используем переменную <code>setCenter</code>. Если она равна <code>true</code>, то в данный момент выполняется установка центра окружности.</p>
<p>В переменной <code>circleOptions</code> сохраняем хеш с начальными настройками окружности (цвет, прозрачность и т.п.).</p>
<p>После этого устанавливаем обработчик события <code>click</code> (строка 14).</p>
<p>Логика работы здесь следующая. Если <code>setCenter == true</code> (установка центра окружности), то мы убираем старый маркер (строки 16-18) и создаём новый в указанной точке (строки 19-23).</p>
<p>Затем, сохраняем центр окружности (параметр <code>circleOptions.center</code>) и присваиваем <code>setCenter</code> значение <code>false</code> (т.е. запоминаем, что следующий клик по карте укажет радиус окружности).</p>
<p>После второго клика мы рассчитываем расстояние (функция <code>distHaversine</code>, о ней чуть ниже) и устанавливаем параметр <code>circleOptions.radius</code>.</p>
<p>Затем убираем старую окружность (если она есть) и создаём новую (строки 31-35).</p>
<p>В результате <strong>на карте появится новая окружность</strong>.</p>
<p>Обратите внимание, что переменные <code>map</code>, <code>circle</code>, <code>circleOptions</code>, <code>setCenter</code> и <code>marker</code> объявлены в глобальной области видимости. Это необходимо, чтобы их значения сохранялись между вызовами обработчиков событий.</p>
<p>Теперь разберём функцию расчета расстояний между точками.</p>
<pre class="brush: javascript">rad = function(x) {return x*Math.PI/180;}

distHaversine = function(p1, p2) {
    var R = 6371; // earth's mean radius in km
    var dLat  = rad(p2.lat() - p1.lat());
    var dLong = rad(p2.lng() - p1.lng());

    var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
            Math.cos(rad(p1.lat())) * Math.cos(rad(p2.lat())) * Math.sin(dLong/2) * Math.sin(dLong/2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    var d = R * c;

    return d.toFixed(3);
}</pre>
<p>Это реализация формулы гавернсинусов на JavaScript. Взял я её <a href="http://stackoverflow.com/questions/1502590/calculate-distance-between-two-points-in-google-maps-v3">здесь</a>. Формула позволяет определить расстояние между двумя точками на поверхности сферы (длину дуги).</p>
<p>Если вас интересует эта тема, почитайте статью <a href="http://gis-lab.info/qa/great-circles.html">Вычисление расстояния и начального азимута между двумя точками на сфере</a>.</p>
<p>В нашем случае удобно, что приведённая функция правильно работает с объектом <a href="http://code.google.com/intl/ru/apis/maps/documentation/javascript/reference.html#LatLng">LatLng</a>.</p>
<p>И в заключение, <strong>пару замечаний о хранении данных</strong>.</p>
<p>После кликов посетителя координаты области будут находиться в объекте <code>circleOptions</code>. Их можно передать на сервер, например, с помощью AJAX запроса. Таким образом, при повторном входе посетителя на сайт, можно будет восстановить область.</p>
<p>Вообще, применений этих возможностей масса, главное творчески подойти к их использованию <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><strong>Успехов!</strong></p>
<p><strong>Интересно почитать</strong></p>
<p>Муляжи блюд &#8211; <a href="http://nippondom.com/reklama_kafe">реклама кафе</a>, которая убивает наповал.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/google-maps-vydelenie-oblastej-na-karte.html/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>jQuery и плагины: решения для просмотра больших изображений</title>
		<link>http://www.simplecoding.org/jquery-i-plaginy-resheniya-dlya-prosmotra-bolshix-izobrazhenij.html</link>
		<comments>http://www.simplecoding.org/jquery-i-plaginy-resheniya-dlya-prosmotra-bolshix-izobrazhenij.html#comments</comments>
		<pubDate>Sat, 25 Dec 2010 18:41:21 +0000</pubDate>
		<dc:creator>Владимир</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Web дизайн]]></category>
		<category><![CDATA[Web разработка]]></category>

		<guid isPermaLink="false">http://www.simplecoding.org/?p=1161</guid>
		<description><![CDATA[Приветствую всех! В этот раз речь пойдет о нескольких плагинах для jQuery, которые помогают организовать просмотр больших изображений на сайте. Думаю, с этой проблемой в какой-то момент сталкиваются все веб мастера. Представьте, у вас есть высококачественные изображения с высоким разрешением (фотографии, скриншоты и т.п.) и их нужно показать на сайте. Понятно, что вставить их, не [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_1162" class="wp-caption alignnone" style="width: 277px"><img src="http://www.simplecoding.org/wp-content/uploads/2010/12/jquery_img_zoom.jpg" alt="jquery img zoom" title="jquery img zoom" width="267" height="185" class="size-full wp-image-1162" style="float:left" /><p class="wp-caption-text"> </p></div>
<p><strong>Приветствую всех!</strong></p>
<p>В этот раз речь пойдет о нескольких плагинах для <strong>jQuery</strong>, которые помогают организовать просмотр больших изображений на сайте.</p>
<p>Думаю, с этой проблемой в какой-то момент сталкиваются все веб мастера.</p>
<p>Представьте, у вас есть высококачественные изображения с высоким разрешением (фотографии, скриншоты и т.п.) и их нужно показать на сайте. Понятно, что вставить их, не меняя размеры, не получится. Картинки просто «порвут» дизайн. Поэтому предварительно нужно их уменьшить, но и возможность просмотра полноразмерного изображения необходимо обеспечить.</p>
<p><strong>Классическое решение этой задачи</strong> – сделать каждую миниатюру ссылкой на полноразмерное изображение. Т.е. использовать разметку вида.</p>
<pre class="brush: html">&lt;a href="1.jpg"&gt;&lt;img src="1_thumb.jpg" /&gt;&lt;/a&gt;</pre>
<p>где <code>1_thumb.jpg</code> – уменьшенное изображение <code>1.jpg</code>.</p>
<p>Главный <em>недостаток</em> такого подхода – посетитель покидает страницу, а затем должен на неё вернуться с помощью кнопки «Назад».</p>
<p>На данный момент существует множество решений, которые позволяют получить более красивое решение этой задачи.</p>
<p>Для этого примера я решил остановиться на плагинах к библиотеке jQuery. Т.к. на данный момент она одна из самых популярных и, кроме того, аналоги можно найти для всех распространённых JS библиотек.</p>
<p>Хочу сразу отметить, что плагинов для работы с изображениями – сотни, и многие дублируют друг друга.</p>
<p>Я же хочу показать основные подходы с примерами для решения задачи и обсудить их достоинства и недостатки, а какой именно плагин использовать – решать вам.<br />
<span id="more-1161"></span><br />
Чтобы было нагляднее, все описанные здесь примеры я разместил на демонстрационной страничке</p>
<p><a href="http://demosites.simplecoding.org/img_zoom/"><img src="http://www.simplecoding.org/wp-content/themes/three_cols/images/demo_btn_green.png" alt="демонстрационный пример" /></a></p>
<h2>Вариант 1. Предпросмотр при наведении мышки на изображение.</h2>
<p>Есть несколько разновидностей таких плагинов, которые различаются в основном визуальными эффектами. В простейшем случае, для реализации подойдет любой плагин создания подсказок (tooltips). Например, <a href="http://cssglobe.com/post/1695/easiest-tooltip-and-image-preview-using-jquery">Image Preview</a>.</p>
<p>Использовать его не сложно. Размещаете на странице миниатюры со ссылками на полноразмерные изображения, подключаете jQuery и плагин, добавляете несколько CSS стилей и всё, можно пользоваться.</p>
<p>Рассмотрим пример.</p>
<p>Разметка страницы</p>
<pre class="brush: html">&lt;a href="images/1.jpg" class="preview"&gt;&lt;img src="images/1t.jpg" alt="image 1" /&gt;&lt;/a&gt;
&lt;a href="images/2.jpg" class="preview"&gt;&lt;img src="images/2t.jpg" alt="image 2" /&gt;&lt;/a&gt;
&lt;a href="images/3.jpg" class="preview"&gt;&lt;img src="images/3t.jpg" alt="image 3" /&gt;&lt;/a&gt;</pre>
<p>Здесь ссылкам добавлен класс <code>preview</code>, чтобы плагин мог выбрать только те изображения, которые нужно увеличить.</p>
<p>Подключение JS файлов:</p>
<pre class="brush: html">&lt;script type="text/javascript" src="jquery-1.4.4.min.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="tooltip.js"&gt;&lt;/script&gt;</pre>
<p>И CSS стили:</p>
<pre class="brush: css">a img {
    border: none;
}

#preview {
    background: none repeat scroll 0 0 #333333;
    border: 1px solid #CCCCCC;
    color: #FFFFFF;
    display: none;
    padding: 5px;
    position: absolute;
}</pre>
<p>Их вы можете поменять. Главное – сохраните абсолютное позиционирование для блока предпросмотра (position: absolute). Иначе полноразмерная картинка будет вставлена внутрь страницы и испортит дизайн.</p>
<p>Теперь <em>о достоинствах и недостатках</em>.</p>
<p>Взгляните на <a href="http://demosites.simplecoding.org/img_zoom/">демонстрационную страничку</a> (первый ряд изображений).</p>
<p>Я специально выбрал картинки с большим разрешением, чтобы был виден главный недостаток. Полноразмерное изображение не всегда полностью помещается на экране и его положение зависит от положения миниатюры на странице.</p>
<p>Второй недостаток в том, что посетитель не всегда ожидает такого поведения и может случайно навести мышку на миниатюру, в результате часть текста окажется закрытой картинкой, а это раздражает.</p>
<p>Достоинством такого подхода является <em>минимум действий со стороны пользователя</em>. Если миниатюр много, то удобно просматривать их просто перемещая мышку.</p>
<p>В общем, я не советую использовать этот подход, если размер оригинала отличается от размера миниатюры более чем в два раза (цифра, конечно, приблизительная, но, думаю, идея ясна).</p>
<h2>Вариант 2. Увеличение картинки на весь экран.</h2>
<p>Реализовать можно с помощью плагинов для создания галерей. Пример для этой статьи я сделал с помощью плагина <a href="http://www.dfc-e.com/metiers/multimedia/opensource/jquery-fancyzoom/">Fancy Zoom</a>.</p>
<p>В данном случае, при клике по миниатюре она увеличивается до размеров окна браузера (плагин контролирует эту величину), а остальная часть страницы затеняется.</p>
<p>Подключение и настройка плагина достаточно простые.</p>
<p>Разметка страницы должна позволять выбрать нужные изображения с помощью jQuery селекторов. Например, так:</p>
<pre class="brush: html">&lt;div id="fancy"&gt;
    &lt;a href="images/1.jpg"&gt;&lt;img src="images/1t.jpg" alt="image 1" /&gt;&lt;/a&gt;
    &lt;a href="images/2.jpg"&gt;&lt;img src="images/2t.jpg" alt="image 2" /&gt;&lt;/a&gt;
    &lt;a href="images/3.jpg"&gt;&lt;img src="images/3t.jpg" alt="image 3" /&gt;&lt;/a&gt;
&lt;/div&gt;</pre>
<p>После этого, нужно подключить JS скрипты и передать плагину ссылки на полноразмерные изображения.</p>
<pre class="brush: html">&lt;script type="text/javascript" src="jquery-1.4.4.min.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="jquery.shadow.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="jquery.ifixpng.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="jquery.fancyzoom.min.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;
	$(function() {
		$('#fancy a').fancyzoom();
	});
&lt;/script&gt;</pre>
<p>Плагины <code>shadow</code> и <code>ifixpng</code> используются для создания тени вокруг полноразмерного изображения и исправления проблем IE при работе с png изображениями, соответственно.</p>
<p>Fancy Zoom имеет несколько полезных настроек, на которых я останавливаться не хочу, т.к. они достаточно подробно описаны в документации.</p>
<p>Теперь о достоинствах и недостатках.</p>
<p>Кликните по любому изображению во втором ряду на <a href="http://demosites.simplecoding.org/img_zoom/">демонстрационной страничке</a>. Картинка плавно увеличится и в правом верхнем углу появится кнопка «Закрыть».</p>
<p>Безусловным преимуществом тут является то, что можно удобно просматривать довольно большие изображения <em>без использования скролла</em>.</p>
<p>Кроме того, ни о каких случайных срабатываниях тут речь не идёт. Картинка будет увеличена только в ответ на явное действие пользователя – клик мышкой.</p>
<p>Но читать текст на странице уже не получится. Т.е. посетитель может смотреть либо на картинку, либо – на содержимое страницы.</p>
<h2>Вариант 3. Увеличение картинки в отдельном блоке.</h2>
<p>Для демонстрации этого решения я выбрал плагин <a href="http://www.mind-projects.it/projects/jqzoom/">jqZoom</a>.</p>
<p>Посмотреть как он работает можно на <a href="http://demosites.simplecoding.org/img_zoom/">демонстрационной страничке</a> (последний ряд). Когда вы наводите указатель мыши на изображение на нём появляется полупрозрачный прямоугольник, показывающий какая именно область картинки сейчас увеличена. Справа появится блок с увеличенным фрагментом изображения. Естественно, плагин не растягивает миниатюру, а просто показывает фрагмент полноразмерной картинки.</p>
<p>Разметка страницы для использования этого плагина не отличается от предыдущих вариантов.</p>
<pre class="brush: html">&lt;a href="images/2.jpg" class="jqzoom" title="image 2"&gt;
	&lt;img src="images/2t.jpg" alt="image 2" /&gt;
&lt;/a&gt;</pre>
<p>Для использования плагина нужно подлкючить библиотеку jQuery, сам плагин, найти нужные изображения и вызвать для них метод <code>jqzoom()</code>.</p>
<pre class="brush: html">&lt;script type="text/javascript" src="jquery-1.4.4.min.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="jqzoom.pack.1.0.1.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;
	$(function() {
		$(".jqzoom").jqzoom();
	});
&lt;/script&gt;</pre>
<p>С помощью дополнительных параметров можно указать размеры области предпросмотра, её положение, масштаб и другие параметры. Подробнее читайте на официальном сайте.</p>
<p>Теперь подумаем, <em>что даёт использование такого плагина</em>.</p>
<p>На мой взгляд, его можно воспринимать как компромиссное решение между двумя первыми вариантами.</p>
<p>Возможность просмотра полноразмерного изображения сохраняется, требуется минимум действий от пользователя, и при этом не будет закрыт ни один элемент на странице.</p>
<p>Недостатком можно считать просмотр картинки по частям. Но, с другой стороны, если оригинал действительно большой, то просмотреть его в натуральную величину без скролла всё равно не получится.</p>
<p>И, конечно, использование этого плагина потребует изменения дизайна страницы. В нём должна быть предусмотрена область для просмотра увеличенной картинки. Предыдущие плагины можно просто подключить к любой странице, и они никак не повлияют на её дизайн.</p>
<p><strong>Обратите внимание</strong>. Все три решения используют стандартную разметку (картинка внутри ссылки). Такой подход гарантирует, что при отключённом JavaScript посетитель сможет просмотреть полноразмерное изображение.</p>
<p>В заключение, хочу отметить, что в этой статье рассмотрены далеко не все варианты решения задачи. Я выбрал те, которые считаю наиболее универсальными (подходят для большинства сайтов) и простые в использовании.</p>
<p>Если вам приходилось решать подобные задачи, и вы хотите о нём рассказать, пишите, буду рад обсудить <img src='http://www.simplecoding.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><strong>Интересно почитать</strong></p>
<p><a href="http://nippondom.com/kak_privlech_klientov_v_kafe">Как привлечь клиентов в кафе</a> и убедить их заказать больше чем обычно?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.simplecoding.org/jquery-i-plaginy-resheniya-dlya-prosmotra-bolshix-izobrazhenij.html/feed</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
	</channel>
</rss>

