AJAX. 2 – Подробнее об XMLHttpRequest

Автор: Вячеслав Гринин | веб-программирование | 30 Янв 2009 5:34 пп

В статье AJAX. 1 – Что это такое? я рассказал про то, в каких случаях можно использовать AJAX и привел тестовый пример использования AJAX в веб-разработке. Теперь я хочу немного углубиться в подробности работы с объектом XMLHttpRequest и расскажу про его основные свойства и методы. Итак…

Методы объекта XMLHttpRequest:

  • abort() – Прекращает исполнение текущего запроса. При этом объект XMLHttpRequest возвращет readyState=4 и status=0.
  • getAllResponseHeaders()- Возвращает HTTP-заголовки ответа в
    виде строки. Эта строка может выглядеть, например, так:
    Date: Fri, 30 Jan 2009 13:57:48 GMT Server: Apache/2.2.4 (Win32) mod_ssl/2.2.4 OpenSSL/0.9.8d PHP/5.2.4 X-Powered-By: PHP/5.2.4 Content-Length: 91 Keep-Alive: timeout=5, max=98 Connection: Keep-Alive Content-Type: text/xml
  • getResponseHeader(”header-name”) – Возвращает заголовок “header-name” ответа. Для случая getResponseHeader(’Content-Type’) она вернет
    text/xml
  • open(”method”, “URL”, async-flag, “user-name”, “password”) – Инициализирует параметры запроса. Если в качестве “method” используется строка “POST”, то метод send(’content’) в качестве параметра должен принимать данные, передаваемые методом POST. Если же “method”=”GET”, то параметры обработчику передаются в параметре “URL” метода open()
  • send(”content”) – Выполняет HTTP-запрос.
  • setRequestHeader(”header-name”, “header-value”) – Добавляет в запрос HTTP-заголовок.

Свойства объекта XMLHttpRequest::

  • onreadystatechange – Установка функции обратного вызова, которая будет обслуживать изменение состояния запроса.
  • readyState – Возвращает состояние запроса
    0 – не инициализирован
    1 – идет отправка запроса
    2 – запрос отправлен
    3 – идет обмен
    4 – обмен завершен
  • responseText – Содержит ответ сервера в виде строки
  • responseXML – Содержит ответ сервера в виде XML-документа
  • status – Возвращает код состояния запроса
  • statusText – Возвращает сообщение о состоянии запроса

Здесь расположен архив с исходными кодами тестового примера, который демонстрирует использование всех вышеприведенных свойств и методов.

Прочтите еще:

Трюк со ссылкой – показываем картинку.

Автор: веб-дизайнер | веб-дизайн | 27 Янв 2009 12:54 дп

Достаточно часто в процессе веб-разработки дизайнеру приходится сталкиваться с ситуацией, когда необходимо “оживить” ссылку, на которую наводится курсор. Тому, как это сделать без помощи флеша и джава-скриптов посвящен сегодняшний рассказ.

Для начала – ссылки на сайты (c-action, Шаг за горизонт), где подобный метод реализован достаточно хорошо. Безо всякого Flash и  Java Script мы легко можем сделать интерфейс сайта более динамичным.

Суть метода заключается в следующем:  мы добавляем в ссылку тег <span></span>, содержащий нужную нам графику. И, до поры, до времен прячем его. А при наведении курсора на ссылку делаем видимым. Абсолютное позиционирование контейнера позволяет нам перемещать графику в любое место пространства. Если проявить фантазию, поле для деятельности – безгранично.

Подробный листинг (на примере “Шага за горизонт”):

HTML:

&lt;span id=”item1″>&lt;img src=”d1.jpg” alt=”" />&lt;/span>

CSS:

a span {
display: none;
}

a:hover span {
display: inline;
position: absolute;
}

а позиционирование элементов назначается отдельно, по id:

#item1 {
left: 495px;
top: 100px;
}

Все достаточно просто, не правда ли?;-)

————————————-

Прочтите еще:

AJAX. 1 – Что это такое?

Автор: Вячеслав Гринин | веб-программирование | 23 Янв 2009 9:01 пп

Эта статья открывает целый цикл статей, посвященных загадочной и очень увлекательной теме AJAX. Я постараюсь донести до вас, дорогие читатели, что же это за зверь такой, и как это можно использовать в веб-разработке для создания веб-приложений, написанных на ASP.NET, PHP, а может и каких других языках и платформах.
Когда некий узкий круг лиц узнал про AJAX и начал его использовать в своих приложениях, вокруг него поднялась такая шумиха, что казалось, будто об этом говорят все вокруг, не исключая бабушек на лавочке у подъезда. Я сам впервые услышал этот термин, когда ехал на трамвае в универ. Рядом со мной стояла парочка, и молодой, но уже бородатый парнишка с всклокоченными волосами рассказывал своей подружке об аяксе. Использовал он при этом такие высокопарные выражения, что я бы не удивился, если б узнал, что он втихомолку по вечерам строчит нервною рукою в тетрадь с пожелтевшими страницами оды или, как минимум, сонеты. В общем, «погиб поэт, невольник чести… стал программистом он, увы».
Но лирическое вступление слишком затянулось.
Так что же такое AJAX? Расшифровывается это слово, как Asynchronous JavaScript and XML, то есть «Асинхронный JavaScript и XML». Отсюда можно понять, что для успешного использования этой технологии, никуда не деться, нужно хоть немного знать JavaScript и уметь на нем писать. А вот XML позволительно и не знать, ибо можно обойтись и без него.
Так вот AJAX – это технология, позволяющая веб-страницам на клиентской стороне, то есть прямиком из браузера пользователя, в фоновом режиме обращаться к серверу и получать от него некоторые необходимые данные. А это значит, что для обновления части страницы браузеру не нужно перезагружать всю страницу целиком. И обращение это может происходить незаметно для пользователя, не заставляя его дожидаться перезагрузки страницы. При грамотном применении эта технология позволит вам, как программисту, сэкономить время пользователя и его трафик. А мы знаем, что пользователи – жутко нервные и обидчивые создания. Не дай бог заставить юзера ждать обновления страницы слишком долго, и он тут же переметнется к вашим конкурентам. Причем это совсем не шутки.
Чтобы увидеть один из аспектов применения технологии AJAX, зайдите на http://www.yandex.ru/ или на http://www.google.ru/ , введите в строке поиска что-нибудь, например букву «п», и тут же под полем ввода откроется список наиболее популярных поисковых запросов, начинающихся с буквы «п». Откуда взялся этот список? В тот момент, когда вы отпустили клавишу «п», ваш веб-браузер в фоновом режиме отправил запрос серверу вот такого вида: http://suggest.yandex.ru/suggest-ya.cgi?ct=text/html&part=%D0%BF , а в ответ очень быстро получил вот такую строку:
suggest.apply(["п", ["погода", "переводчик", "поздравления с днем рождения", "почта", "переводчик онлайн", "приколы", "прогноз погоды", "погода в москве", "поздравления с новым годом", "поздравления"], []], []) , где в квадратных скобочках можно увидеть все эти наиболее популярные поисковые запросы. JavaScript в браузере быстренько добавил к этому списочку HTML-разметку и отобразил ее на вашей странице в абсолютно позиционированном DIV-е.
Сайт http://maps.google.com/ вообще весь целиком и полностью построен на AJAX. Именно поэтому, когда вы двигаете мышью карту, ваша страница не перезагружается.
Посмотрим теперь из чего состоит AJAX. В его основе лежат 4 базовые вещи:

  1. JavaScript. Если вы профессионал в веб-разработке, то без него здесь никуда. Именно на нем реализована функциональность на стороне клиента. И даже если вы используете готовые AJAX-решения, вам не избежать того, что придется еще кое-что писать ручками.
  2. Объектная модель документа(DOM). Знание этой модели нужно, чтобы отобразить на странице в браузере ту информацию, что пришла в ответ на асинхронный запрос серверу от браузера.
  3. Объект XMLHttpRequest. Именно он позволяет из JavaScript организовать асинхронный доступ к серверу. Без этого объекта AJAX – мертв!
  4. Ну и, наконец, любая из серверных технологий, будь то PHP, ASP, ASP.NET, JSP, Ruby on Rails и т.д. и т.п. Вы можете использовать здесь то, что вам больше по душе.

Как это работает?

  1. Страница (конечно же, посредством JavaScript) в браузере пользователя, по какому-либо событию (нажатие клавиши, таймер) с помощью объекта XMLHttpRequest подает запрос серверу, обращаясь к некоему серверному обработчику, передавая ему некоторые параметры, например, значения, введенные пользователем в поле «Имя пользователя» на форме регистрации.
  2. Обработчик принимает этот запрос и обрабатывает его. Чаще всего, это некий поиск базе данных, и формирование результатов в виде структуры данных, а может и в виде готовой HTML-разметки. Собственно, в результате выполнения запроса на выходе получается некая строка, в которой упакованы данные. По завершению обработки данных, обработчик выдает эти данные обратно браузеру пользователя. Упаковка чаще всего производится либо с использованием JSON, либо XML.
  3. Браузер принимает эту строку, распаковывает ее, и использует для отображения на загруженной странице. В нашем случае, рядом с полем «Имя пользователя» появится надпись «имя свободно» или «имя занято». Кстати, в качестве первого примера использования AJAX мы напишем собственное веб-приложение, которое будет отвечать на вопрос, занято или свободно выбранное имя пользователя.

Ну что ж, а теперь попробуем создать свое первое веб-приложение, использующее технологию AJAX. Для этого вам понадобится локальный веб-сервер с поддержкой PHP, и если вы не знаете, откуда его взять, то зайдите сюда , и уже спустя несколько минут у вас будет свой собственный локальный веб-сервер.
А теперь создадим наше первое AJAX-приложение.

  1. Создайте страницу регистрации пользователя index.html. На ней расположены поле ввода имени пользователя, кнопка «Проверить имя» и DIV, в котором будут выводиться результаты проверки.
    <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd“>
    <html xmlns=”http://www.w3.org/1999/xhtml“>
    <head>
    <title> Простой пример на AJAX</title>
    <script type=”text/javascript” src=”ajax.js”></script>
    </head>
    <body>
    Имя пользователя: <input type=”text” id=”username”><input type=”button” onclick=”checkName()” value=”проверить имя”>
    <div id=”umess”>…</div>
    </body>
    </html>
  2. Создайте файл ajax.js, содержащий в себе клиентский скрипт на JavaScript. Его функциональность подробно прокомментирована в самом тексте.
    // Это и есть объект XmlHttpRequest
    var xmlHttp=createXmlHttpRequest();
    // синоним для getElementById
    function gebi(id) {
    return document.getElementById(id);
    }
    // функция кроссбраузерно создает объект XmlHttpRequest
    function createXmlHttpRequest() {
    var xmlHttp;
    try {
    if(window.ActiveXObject) // для IE
    xmlHttp=new ActiveXObject(”Microsoft.XMLHTTP”);
    else // для остальных браузеров
    xmlHttp=new XMLHttpRequest();
    }
    catch(e) {
    xmlHttp=false;
    alert(”Объект XMLHttpRequest не создан!”);
    }
    return xmlHttp;
    }
    // вызывается по клику на кнопке “Проверить имя”
    function checkName() {
    // проверяем, завершил ли объект XMLHttpRequest прошлый вызов
    if(xmlHttp.readyState==4 || xmlHttp.readyState==0) {
    // получаем строку, введенную пользователем
    usname=encodeURIComponent(gebi(”username”).value);
    // говорим объекту XMLHttpRequest куда и как он должен обратиться
    xmlHttp.open(”GET”, “handler.php?username=”+usname, true);
    // говорим объекту XMLHttpRequest какую функцию он должен вызывать при изменении своего статуса
    xmlHttp.onreadystatechange=handleResponse;
    // посылаем асинхронный запрос серверу
    xmlHttp.send(null);
    }
    }
    // вызывается при изменении статуса объекта XMLHttpRequest
    function handleResponse() {
    // проверяем по readyState завершена ли транзакция
    if(xmlHttp.readyState==4) {
    // проверяем по status успешность транзакции
    if(xmlHttp.status==200) {
    // если все порядке, читаем возвращенный XML документ
    xmlResponse=xmlHttp.responseXML;
    xmlElement=xmlResponse.documentElement;
    res=xmlElement.firstChild.data;
    var umess=gebi(”umess”);
    // в соответствии с возвращенным результатом, выводим на страницу нужное сообщение
    if(res==’true’)
    umess.innerHTML=”Имя свободно”;
    else
    umess.innerHTML=”Имя занято”;
    }
    else
    alert(”Ошибка при обращении к серверу. “)+xmlHttp.statusText;
    }
    }
  3. Создайте файл handler.php. Именно с этим серверным скриптом будет взаимодействовать страница в браузере пользователя. По хорошему, здесь должная быть настоящая проверка на существование в базе MySQL пользователя с введенным именем. В демонстрационных целях здесь реализована фиктивная проверка по первой букве имени.
    <?php
    // возвращать будем XML
    header("Content-Type: text/xml");
    // создаем заголовок XML и элемент response
    echo '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>';
    echo ('<response>');
    // из GET-строки получаем имя пользователя
    $username=$_GET['username'];
    // Фиктивная проверка на существование такого пользователя БД
    if(substr($username,0,1)=='a')
    echo('true');
    else
    echo('false');
    // закрываем элемент response
    echo('</response>');
    ?>
  4. А теперь введите в браузере http://localhost/index.html и протестируйте ваше приложение.

Здесь расположен архив со всеми необходимыми файлами. Просто распакуйте его в корневую директорию вашего веб-сервера и выполните в браузере http://localhost/index.html.

Прочтите еще:

В помощь фотошоперу – кисти

Автор: веб-дизайнер | веб-дизайн | 19 Янв 2009 11:02 пп

Сегодняшний наш разговор я хотел бы выстроить вокруг важнейшего инструмента фотошопа – вокруг кисти. Точнее, вокруг этой самой кисти настроек. Ведь согласитесь, было такое, что когда вы открывали панель Brushes (F5), вы думали: “Твою мать, что все это значит?”. Уверяю вас, это совершенно нормально, я в первый раз подумал точно также.

Но обо всем по порядку. Итак, кисть. Кисть нужна практически всегда – ретушь и рисование это 99% фотошопа. Казалось бы, что там думать – взял кисть, выставил цвет, настроил диаметр (кнопки “[" и "]“), жесткость контура – и вваливай!

Не все так просто. Двумя кликами в настройках кисти можно быстро сделать достаточно красивый и эффектный фон, скажем.

Итак, поехали. Строчка первая – Brush presets:

Тут мы можем выбрать сэмпл кисти и установить главный диаметр.

Строчка вторая: Brush tip shape:

Здесь мы по-прежнему можем выбрать сэмпл кисти и настроить главный диаметр штриха. А также – нажать кнопку “Use sample size”, для того, чтобы установить тот диаметр, который прописан для кисти по умолчанию.
Следующий блок у нас отвечает за пространственную ориентацию сэмпла кисти. С помощью круглого лимба со стрелкой его можно вертеть вокруг своей оси (ясное дело, что это не для идеально круглых кистей – че там вертеть-то?), а с помощью чекбоксов flip x и flip y – зеркально отображать по осям х и у соответственно. Также можно установить угол поворота вручную в поле Angle и соотношение вертикального и горизонтального диаметров кисти.
Следующим пунктом у нас идет шкала жесткости контура. Меньше значение – мягче, размытей контур, больше – резче.
И последнее – spacing. Сиречь – расстояние между сэмплами кисти. Скажем, если вы рисуете сплошную линию, то этот параметр лучше вообще отключить. А если у вас в качестве кисти какой-то декоративный сэмпл – тогда с ним можно поиграться, чтобы настроить “разлет” сэмплов по площади.

Строчка третья: Shape dynamics:

Первая шкала – size jitter. Этот параметр отвечает за изменение размера сэмпла вдоль линии движения. Под ним есть небольшой селект, отвечающий за то, как этим параметром управлять. Корректно работает он только при наличии планшета (методы управления – фэйд, давление на стилус, наклон стилуса, нажатие кнопок на стилусе (это все касается и все остальных селектов, которые нам встретятся)). Minimum diameter указывает на то, каким будет минимальный диаметр сэмпла. Tilt scale связан с углом наклона стилуса и подробно пока я на нем останавливаться не буду.
Angle Jitter – разброс угла поворота сэмпла. Опять же – имеет смысл только для некруглых сэмплов.
Roundness Jitter – разброс вертикального (относительно направления оси Х кисти) диаметра сэмпла.
Minimum Roundness – соответственно установка минимального значения вертикального диаметра сэмпла в процентах от размера текущего (oh, fukk!)

Следующим пунктом у нас идет scattering:

Первая шакала – scatter. Отвечает она за разброс сэмплов вдоль направления рисования. Очень удобно рисовать всяике листики, снежинки и прочее. Чекбок Both Axes указывает на то, как разбрасывать – вдоль обоих осей (галка включена) или вдоль одной (в этом случае касательная от сэмпла до направления рисования всегда перпендикуляр).

Count отвечает за количество сэмплов на единицу площади. Count jitter немного изменяет расстояние между сэмплами.

Далее – texture:

В окошке можно выбрать сэмпл текстуры, которой будет заливаться закрашенная кистью область, а также инвертировать текстуру.
С помощью scale подгоните размер сэмпла текстуры по размеру.
Обратите внимание, что если вы не поставили галку в Texture each tip, то, сколько не возюкайте кистью – заливка сэмплом будет равномерной. Если же галка установлена, то необходимо настроить следующие параметры:
* выставить режим смешивания;
* с помощью параметра depth укажите, как у вас будет текстуризоваться штрих кисти – от минимального (текстура только по краям) до макисмального (весь штрих заливается текстурой);
* min depth отвечает за размер минимальной глубины текстуризации (я так и не смог заставить его работать);
* depth jitter, соответственно, отвечает за разброс глбуины текстуризации по семплам вдоль линии рисования.

Dual Brush:

В общем, параметр дуал браш позволяет назначить вторую кисть, которая будет своеобразной маской для риса первой.
То есть, если мы, скажем, выберем кисть в виде листочка, а потом в дуал браш назначим вторую просто круглуюс меньшим диаметром, то у нас получится контур второй кисти, заполненный попавшими в нее частями сэмплов первой.
Настройки – Diameter устанавливает диаметр кисти-маски. Spacing – расстояние между сэмплами кисти-маски. Scatter – разлет между сэмплами кисти-маски вдоль линии рисования (чекбокс отсноится к этому параметру). Count – устанавливает количество сэмплов кисти-маски по линии риса.

Color Dynamics:

этот параметр позволяет установить разброс по цвету, насыщенности тона и прочим параметрам между отдельными сэмплами кисти на линии рисования.
Foreground/Background jitter – устанавливает разлет между передним и задним цветами на сэмплах кисти (то есть, если передний цвет – красный, а задний – белый, то сэмплы будут окрашены в оттенки от белого до красного случайным образом).
Hue jitter позволяет установить разброс по оттенкам от двух соседних цветов (например – красный/желтый) при малых значениях, до всей цветовой палитры при высоких (при условии, что цвет кисти не черный, и не оттенок серого). Saturation jitter отвечает за разброс между сэмплами кисти насыщенности выбранного цветового оттенка. Brightness jitter – за яркость. Purity – за чистоту цвета. Максимальные отрицательные значения делают сэмплы монохромными.

Вкладка Other Dynamics:

Здесь у нас две шкалы – Opacity jitter и Flow jitter. Обе они случайным образом влияют на прозрачность сэмпла, и в чем между ними сугубая разница экспериментальным путем выяснить не удалось.

Лежащие ниже опции:
* noise – добавляет шум по краям сэмпла кисти;
* wet edges – делает рис кисти прозрачным, а края немного темнее, что создает эффект акварельного мазка;
* airbrush – эмулирует аэрозольный баллончик. По идее:-)
* smoothing – сглаживает края кисти.
* protect texture – запоминает текущую текстуру и назначает ее всем новым сэмплам.

Замочки помогают “заблокировать” нужные свойства, чтобы они назначались автоматом всем остальным выбранным сэмплам кисти.

Вот хорошая статья в тему: http://www.art-gu.ru/texts/files/db.0006/. Она написана для более старой версии фотошопа, но все поведение кистей там проиллюстрировано. Так что – надо посмотреть.
————————————-

Прочтите еще:

Позиционирование элементов на JavaScript.

Автор: Вячеслав Гринин | веб-программирование | 13 Янв 2009 12:17 дп

Сегодня я расскажу о том, как правильно позиционировать элементы страницы друг относительно друга.
Зачем это нужно? Например, чтобы создать красивый выпадающий список. Сегодня мы зададимся целью создать некий пользовательский комбо-бокс. И стандартные возможности HTML нас не устраивают. То есть, мы хотим получить нечто более сложное, чем вот это.

<select>
<option>Item 1</option>
<option>Item 2</option>
<option>Item 3</option>
</select>

А получить хотели бы нечто вроде этого:

<input type=’text’ style=’width: 100px;’ id=’textbox1′/>
<div style=’border: 1px solid #072; background-color: #59E75D; width: 100px;’ id=’list1′>
<ul>
<li><a href=’#'>Item 1</a></li>
<li><a href=’#'>Item 2</a></li>
<li><a href=’#'>Item 3</a></li>
</ul>

То есть мы хотим отпозиционировать DIV так, чтобы он прикрепился к одному из углов другого элемента на странице. 

Вообще, для позиционирования элемента в координатах, заданных своими величинами (X, Y) подойдет вот такая функция:

function setPosXY(obj,x,y) {
  if(obj) {
    obj.style.position=’absolute’;
    obj.style.left=x+’px’;
    obj.style.top=y+’px’;
  }
}

Эта функция проста и особых пояснений не требует. Осталось только правильно определить координаты того элемента(E1), относительно которого хочется спозиционировать заданный элемент(E2), да еще и в соответствии с тем, к какому именно углу E1 будет пристыкован E2.  Углов у любого прямоугольника всего 4. Соответственно и вариантов позиционирования будет 4.

Вот они:

Функция getBounds определяет параметры left, top, width, height объекта. Цикл while нужен для того, чтобы определить абсолютные координаты объекта относительно контейнера <body>.

function getBounds(obj){
  var w=obj.offsetWidth;
  var h=obj.offsetHeight;
  var x=y=0;
  while(obj){
    x+=obj.offsetLeft;
    y+=obj.offsetTop;
    obj=obj.offsetParent;
  }
  return{x:x,y:y,width:w,height:h};
}

 Ну а вот и сама функция позиционирования:

function setPos(anc_id,obj_id,corner,margin){
// anc_id – id элемента, относительно которого будем позиционировать
// obj_id – id элемента, который будем позиционировать
// corner – номер угла (смотрите Рис.1)
// margin – отступ между элементами, чтобы они не “слипались”
  if(!corner)corner=1;
  var obj=document.getElementById(obj_id);
  var anc=document.getElementById(anc_id);
  if(!obj||!anc) return;
  var b=getBounds(anc);
  var c=getBounds(obj);
  var xs=0,ys=0; // координаты left и top родительского элемента (на случай, если кто-то из родителей абсолютно позиционирован)
  var par=obj;
  for(var i=0;i<50;i++){
    par=par.parentNode;
    if(!par||par.tagName==’BODY’) break;
    var s=getCurrentStyle(par);
    if(par.tagName==’DIV’&&s&&s.position==’absolute’){
      var p=getBounds(par);
      xs+=p.x
      ys+=p.y;
      break;
    }
  }
  var xc=0,yc=0; // Дополнительные отступы, учитывающие номер угла
  switch(corner){
    case 2:
      yc=-c.height-b.height;
      break;
    case 3:
      yc=-c.height-b.height;
      xc=-c.width;
      break;
    case 4:
      xc=-c.width+b.width;
      break;
  }
  var xm=0;ym=0; // Дополнительные отступы, учитывающие параметр margin
  if(margin){
    xm=margin.x;
    ym=margin.y;
  }
  SetPosXY(obj,b.x-xs+xc+xm,b.y+b.height-ys+yc+ym);
}

И чуть не забыл, функция getCurrentStyle нужна, чтобы кроссбаузерно определить текущий стиль элемента:

function getCurrentStyle(el){
  if(!el) return null;
  var s=el.currentStyle; 
  if(!s) s=document.defaultView.getComputedStyle(el,null); // Для FireFox
  return s;
}

А вот здесь находится весь скрипт.  Пользуйтесь на здоровье.
Ну а вызов этой функции может выглядеть так:

setPos(’textbox1′,’list1′,1,{’x':2, ‘y’:2});

————————————-

Прочтите еще:

Позже »