26 января 2010
AJAX и история или одна из идей как упростить себе труд
В целом об AJAX написано много. Море фреймворков, библиотек, учебников, уроков вокруг облегчающих работу с этой технологией. Но всегда хочется сделать еще проще, еще удобнее и иногда быстрее чем у других и возможно погоня за оригинальностью. Не скажу, что всё это про мой пост, просто пришла идея и захотелось реализовать.
Потому и набросал этот код чисто для иллюстрации посетившей идеи. Сильно не ругать, с JQuery я не так давно, потому как-то так, но для примера вполне хватит, главное понять идею, а дальше уже можно и другие фишки задавать.
В целом — идея.
Меня постоянно убивало, что нужно писать много кода, куда и что запрашивать AJAX и при этом делать несколько версий. В момент работы с Prototype был написан один большой объект, где просто назначались действия, какую ссылку запросить, куда засунуть, какое сообщение показать. Но время движется и хочется не таскать для простых казалось таскать столь громадные махины как Prototype, я перешел на JQuery. Конечно и вторая причина перехода, это обилие плагинов сыграло роль.
JQuery код упрощает, хотя и меняет логику привычную с Prototype.
Но код всё же опять пухнет, смешивается в кучу JavaScript и HTML, вставки кругом, поддержка работы без JavaScript (например для поисковиков) — всё это заставляет мешать и мешать код. Мне это не нравится.
В какой-то момент меня посещает идея, что все ссылки которые будут например работать в двух версиях, как переход например на страницу 1.html и как вторая версия это загрузка этой самой 1.html страницы в поле #content, можно легко пометить классом, уникальным id и для удобства назначения запроса AJAX мы можем втюхать его в атрибут rel:
То есть мы просто при загрузке нашей страницы вставим свой обработчик нажатия на каждую такую ссылку и можем с легкостью доставать адреса запросов и творить с ними удобные штуки.
Встал второй вопрос, история. Как все понимают AJAX никак не отражается на нашей адресной строке и истории браузера — они вообще не изменяются! Но как уже вошло в практику мы можем использовать якора (anchor). Да эти самые простые штучки #link1 будут нашими путеводителями, подумал я! Как раз по якорю как id элемента мы начнем определять есть ли ссылка и указан у неё ли rel с адресом запроса. Можно пойти конечно дальше, если захотите например засовывать в rel некий json текст с указаниями например div#id куда будет результат попадать или эффекты какие, но это уже расширение.
Ну в целом, вот пример, смотрите mrak7.com/ex/dax/
Сразу можете открыть код и сравнить например ссылку 1 и 2 в реализации :) Обе работают, кнопка браузера работает так же :) Проверял разумеется пока только в FireFox 3.6 и Chrome 4, остальные не знаю, пока для примера идеи считаю не важно.
На всякий случай копирую код сюда:
И разумеется ссылка на скачивание всего кода .rar 1.5 Kb
P.S. Метод у объекта DAX можно даже убрать или сократить, без bind'а так сказать
Потому и набросал этот код чисто для иллюстрации посетившей идеи. Сильно не ругать, с JQuery я не так давно, потому как-то так, но для примера вполне хватит, главное понять идею, а дальше уже можно и другие фишки задавать.
В целом — идея.
Меня постоянно убивало, что нужно писать много кода, куда и что запрашивать AJAX и при этом делать несколько версий. В момент работы с Prototype был написан один большой объект, где просто назначались действия, какую ссылку запросить, куда засунуть, какое сообщение показать. Но время движется и хочется не таскать для простых казалось таскать столь громадные махины как Prototype, я перешел на JQuery. Конечно и вторая причина перехода, это обилие плагинов сыграло роль.
JQuery код упрощает, хотя и меняет логику привычную с Prototype.
Но код всё же опять пухнет, смешивается в кучу JavaScript и HTML, вставки кругом, поддержка работы без JavaScript (например для поисковиков) — всё это заставляет мешать и мешать код. Мне это не нравится.
В какой-то момент меня посещает идея, что все ссылки которые будут например работать в двух версиях, как переход например на страницу 1.html и как вторая версия это загрузка этой самой 1.html страницы в поле #content, можно легко пометить классом, уникальным id и для удобства назначения запроса AJAX мы можем втюхать его в атрибут rel:
<a href="1.html" id="link1" class="ajax" rel="1-ajax.php">Наша ссылка</a>
То есть мы просто при загрузке нашей страницы вставим свой обработчик нажатия на каждую такую ссылку и можем с легкостью доставать адреса запросов и творить с ними удобные штуки.
Встал второй вопрос, история. Как все понимают AJAX никак не отражается на нашей адресной строке и истории браузера — они вообще не изменяются! Но как уже вошло в практику мы можем использовать якора (anchor). Да эти самые простые штучки #link1 будут нашими путеводителями, подумал я! Как раз по якорю как id элемента мы начнем определять есть ли ссылка и указан у неё ли rel с адресом запроса. Можно пойти конечно дальше, если захотите например засовывать в rel некий json текст с указаниями например div#id куда будет результат попадать или эффекты какие, но это уже расширение.
Ну в целом, вот пример, смотрите mrak7.com/ex/dax/
Сразу можете открыть код и сравнить например ссылку 1 и 2 в реализации :) Обе работают, кнопка браузера работает так же :) Проверял разумеется пока только в FireFox 3.6 и Chrome 4, остальные не знаю, пока для примера идеи считаю не важно.
На всякий случай копирую код сюда:
(function($) {
function DAX(){
// наш мега объект
this.anchor = '';
this.initialize();
};
$.extend(
DAX.prototype, {
// типа конструктор
initialize: function() {
// проходим по всем ссылкам с классом AJAX и ставим наш обработчик
$("a.ajax").bind("click", function(e){
// обработчик, достаем у ссылки его id и засовываем в uri якорем
// чтобы "временной" обработчик потом схавал его и увидел изменения
var id = $(this).attr('id');
document.location.hash = '#'+id;
return false;
});
// запустим наш временной обработчик с интервалом
setInterval(this.check, 100);
},
// наш триггер по времени
check: function() {
// достанем якорь из uri
var hash = document.location.hash;
hash = hash.replace(/^#/, '');
// изменился ли он, не пустой и не ноль?
if( (hash != $.DAX.anchor) && (hash!='') && (hash!=null) ){
// если так, то попробуем поискать rel у возможной ссылки
var url = $('#'+hash).attr('rel');
if( url ){
/*
если есть rel с адресом, то попробуем запросить его
и т.п. тут уже от разработчика
*/
$.ajax({
type: 'POST',
url: url,
success: function(text){
$('#content').html(text);
$.DAX.anchor = hash;
}
});
}
}
}
});
$(document).ready(function() { $.DAX = new DAX(); }); // Создаем наш объект, синглетон
})(jQuery);
И разумеется ссылка на скачивание всего кода .rar 1.5 Kb
P.S. Метод у объекта DAX можно даже убрать или сократить, без bind'а так сказать
- akhmetov
- 26 января 2010, 17:52
- 0
Советую почитать:
softwaremaniacs.org/blog/2007/09/12/http-ajax-и-jquery/
softwaremaniacs.org/blog/2007/09/12/http-ajax-и-jquery/
- MpaK
- 26 января 2010, 18:33
- 0
Почитал, ничего нового и интересного по данной теме нету.
Как принцип hijak соблюден.
Одно только, что я определение делаю так на сервере, а не как тот автор.
model: Request.php
Как принцип hijak соблюден.
Одно только, что я определение делаю так на сервере, а не как тот автор.
model: Request.php
if( $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') $this->ajax = TRUE;
- xxen
- 26 января 2010, 19:04
- 0
можно вообще обойтись без атрибута rel, а спрашивать ajax у того же адреса, что указан в href. Просто узнавать на сервере ajax это или обычный запрос.
ps: в Yii например это можно узнать из переменной Yii::app()->request->isAjaxRequest
ps: в Yii например это можно узнать из переменной Yii::app()->request->isAjaxRequest
- MpaK
- 26 января 2010, 20:17
- 0
В каком-то простейшем случае конечно можно, так как всё же суть темы не та, но отвлекусь и объясню почему.
В простейшем случае конечно у тебя один запрос — один ответ модуля, как YII сработает MVC, определяем запрос был из аякса и отдаем разные контенты. Кстати выше комментом написал как раз как определяю лично я, а не механизм YII :)
Но в случае некой системы, запрос к странице /news/ к примеру будет запускать кучу модулей установленных на оной (например: меню, новости 4х категорий, контакты и т.п.), что нам разумеется не надо. Конечно мы можем узнать как нас вызвали, но всё равно надо же нам какой-то один модуль например новости раздела политика. К тому и rel например я указал в примере своего поста. Разумеется можно поставить проверку на пустоту и использовать href, но цель всё же была объяснить другую идею :)
В простейшем случае конечно у тебя один запрос — один ответ модуля, как YII сработает MVC, определяем запрос был из аякса и отдаем разные контенты. Кстати выше комментом написал как раз как определяю лично я, а не механизм YII :)
Но в случае некой системы, запрос к странице /news/ к примеру будет запускать кучу модулей установленных на оной (например: меню, новости 4х категорий, контакты и т.п.), что нам разумеется не надо. Конечно мы можем узнать как нас вызвали, но всё равно надо же нам какой-то один модуль например новости раздела политика. К тому и rel например я указал в примере своего поста. Разумеется можно поставить проверку на пустоту и использовать href, но цель всё же была объяснить другую идею :)
- xxen
- 31 января 2010, 12:51
- 0
какую еще кучу модулей7. Модули(виджеты) вызываются в шаблоне. В нормальных MVC фреймворках можно отдавать вьюшку в чистом виде(без шаблона).
- MpaK
- 31 января 2010, 15:36
- 0
Это MVC в чистом виде, когда нет модулей, а виджеты (или еще любят называть их компонентами) это так сказать блоки.
Я имею в виду про модульную систему, например CMS когда не как MVC работаем, а как страница ядра, а потом куча модулей. В CodeIgniter этому есть расширение HMVC. Но думаю подробнее расскажу попоже как буду презентовать нашу систему, она как раз на базе CI и модульная до косточек.
Я имею в виду про модульную систему, например CMS когда не как MVC работаем, а как страница ядра, а потом куча модулей. В CodeIgniter этому есть расширение HMVC. Но думаю подробнее расскажу попоже как буду презентовать нашу систему, она как раз на базе CI и модульная до косточек.
- daken
- 26 января 2010, 20:04
- 0
у меня js-код пробегается по всем ссылкам и перебивает те, которые ведут на этот же домен на аякс-запросы.
в качестве возврата идет json, где есть
preJs — javascript код, его выполнить перед трансформацией шаблонов и вставки контента в нужные места
postJs — то же самое, только в конце
content — ассоциативный массив, где ключ — jQuery селектор, куда надо засунуть контент, который лежит в значении
transform — массив, каждый элемент которого содержит название шаблона, данные и то, куда засунуть результат. для трансформации юзаю jTemplates, но там есть 1 минус — нет поддержки рекурсии, так что многоуровневые меню через него хз как сделать.
errors — ошибки, которые надо сообщить юзеру, используется для отладки.
пхп-скрипт при любом обращении генерит такой массив, просто если запрос был через аякс — выкидывает результат через json_encode, иначе рендерит в хтмл. при желании тут хоть генерацию пдф на лету можно прикрутить)
в качестве возврата идет json, где есть
preJs — javascript код, его выполнить перед трансформацией шаблонов и вставки контента в нужные места
postJs — то же самое, только в конце
content — ассоциативный массив, где ключ — jQuery селектор, куда надо засунуть контент, который лежит в значении
transform — массив, каждый элемент которого содержит название шаблона, данные и то, куда засунуть результат. для трансформации юзаю jTemplates, но там есть 1 минус — нет поддержки рекурсии, так что многоуровневые меню через него хз как сделать.
errors — ошибки, которые надо сообщить юзеру, используется для отладки.
пхп-скрипт при любом обращении генерит такой массив, просто если запрос был через аякс — выкидывает результат через json_encode, иначе рендерит в хтмл. при желании тут хоть генерацию пдф на лету можно прикрутить)
- MpaK
- 26 января 2010, 20:25
- 0
Мысли сходят, у меня тоже такой же код был, вот старая версия на Prototype объект:
Хотя статью писал не о том, АЯКС тут как пример, я о кнопку BACK браузера, о том как html код сам начинает решать как что и варианты использования слежения за location.hash
DC.AJAX = {
// When load begin
ajaxLoad: function( divID ){
if(divID){ this.toggleRollDiv(divID); }
$('ajaxprogress').show();
},
// When complete
ajaxSuccess: function ( divID ){
$('ajaxprogress').hide();
if(divID){ new Effect.BlindDown(divID, { duration: 0.5 });}
},
// Get query, analize and do what need
get: function( url, divID, form, dont_serialize ){
if(!url) return;
if(form) {
if( !(dont_serialize) ){
form = $(form).serialize();
}
}else{
form = '';
}
new Ajax.Request(url, {
method: 'POST',
parameters: form,
onLoading:function(request){ DC.AJAX.ajaxLoad(); },
onComplete:function(request){ DC.AJAX.ajaxSuccess(); },
onSuccess: function(transport) {
res = transport.responseText;
// if JSON
if( res.isJSON() ){
res = res.evalJSON(true);
// error
if(res.error){
DC.message( 'error', res.error );
}
// msg
if(res.msg){
DC.message( 'ok', res.msg );
}
// if have id_text and text go and update it!
if( (res.id_text) && (res.text) ){
$(res.id_text).update( res.text );
}
// if have id_append and text go and APPEND it!
if( (res.id_append) && (res.append) ){
$(res.id_append).insert( {bottom: res.append} );
}
//# todo:
// if have id_top and text go and REPLACE it!
if( (res.id_replace) && (res.replace) ){
$(res.id_replace).insert( res.replace );
}
// if some need code to evaluate
if(res.eval){
eval( res.eval );
}
}else{
// else only update if have container
if(divID) $(divID).update( res );
}
}
}
);
}
}
Хотя статью писал не о том, АЯКС тут как пример, я о кнопку BACK браузера, о том как html код сам начинает решать как что и варианты использования слежения за location.hash
- eye-ru
- 27 января 2010, 02:21
- 0
Хорошая тема. У меня она станет актуальной в ближайшее время в проекте на ASP.NET MVC + jQuery.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.
Комментарии:9