SlideShare uma empresa Scribd logo
1 de 26
Drupal 7 и History.js
или
как AJAX-ифицировать сайт.
Малай Вадим
Drupal developer
vadim.malai@wearepropeople.com
Зачем ?
• Иметь статичную зону контента.
• Иметь возможность навигации Back
или Forward в истории browser-a
• Избежать несоответствий при
использовании родного
window.History
Составляющие
1. Ajaxify Pages
2. History.js
3. Libraries
History.js (Введение)
• Придерживается HTML5 History API
насколько это возможно;
• Кросбраузерность для всех HTML5
браузеров;
• Поддержка HTML4 браузеров;
• Адаптация link-ов в зависимости от
HTML5 или HTML4;
• Поддержка javaScript framerork-ов как "
jQuery", "MooTools", "Prototype", "Zepto".
History.js (Где это работает ?)
HTML5 Browsers
HTML4 Browsers
HTML5 Browsers
Firefox 4+ Safari 5.0+
Chrome 8+ Safari iOS 4.3+
Opera 11.5
IE 6, 7, 8, 9 Safari 4
Firefox 3 Safari iOS 4.2, 4.1,
4.0, 3.2
Opera 10, 11.0
History.js (Как это работает ?)
(function(window,undefined){
var History = window.History;
// Bind to StateChange Event
History.Adapter.bind(window,'statechange',function(){ // Note: We are using statechange instead of popstate
var State = History.getState(); // Note: We are using History.getState() instead of event.state
History.log(State.data, State.title, State.url);
});
// Change our States
History.pushState({state:1}, "State 1", "?state=1"); // logs {state:1}, "State 1", "?state=1"
History.pushState({state:2}, "State 2", "?state=2"); // logs {state:2}, "State 2", "?state=2"
History.replaceState({state:3}, "State 3", "?state=3"); // logs {state:3}, "State 3", "?state=3"
History.pushState(null, null, "?state=4"); // logs {}, '', "?state=4"
History.back(); // logs {state:3}, "State 3", "?state=3"
History.back(); // logs {state:1}, "State 1", "?state=1"
History.back(); // logs {}, "Home Page", "?"
History.go(2); // logs {state:3}, "State 3", "?state=3"
})(window);
History.js (Разбор полётов)
History.Adapter.bind(window,'statechange',function(){}); - Привязка к событию
(Срабатывает, когда состояние страницы изменилось).
History.getState() - Получает текущее состояние браузера, возвращает
объект с data, title и url.
History.pushState({state:1}, "State 1", "?state=1") - Вталкивает новое
"состояния" в браузер; data может быть нулевыми или объектом, title
может быть нулевым или строкой, URL должен быть строкой.
History.js (Разбор полётов)
History.replaceState({state:3}, "State 3", "?state=3") - Заменяет существующее
"состояние" новым; (В случае замены, будет утеряно "состояние"
предшествующее нынешнему)
History.back() - Назад в историю на 1 шаг;
History.go(2) - Вперед в историю на 2 шага;
History.log(...) - Вывод сообщения в консоли;
History.js (Что еще?)
События :
1. 'statechange' - Срабатывает, когда состояние страницы изменилось;
2. 'onanchrorchange' - Срабатывает, когда "якорь" страницы изменился;
History.replaceState(data,title,url) - Заменяет текущее состояние страницы
новым.
History.getHash() - Возвращает значение URL после # (hash); (HTML 4)
History.Adapter.trigger(element,event) - Триггер события;
History.Adapter.onDomLoad(callback) - onDomLoad связующее;
History.forward() - шаг впреред в историю браузера;
History.debug(...) - тоже что и History.log(...), но работает только если
History.debug.enable === true
History.js в Drupal-e
History.js и Drupal
(Привязка к URL)
1. Drupal.behaviors.ajaxify_pages = {};
2. Drupal.behaviors.ajaxify_pages.attach = function(context, settings) {
3. $(Drupal.settings.ajaxify_pages.links_selector, context).each(function() {
4. var to_avoid = Drupal.settings.ajaxify_pages.links_to_avoid;
5. var links = $(this).attr("href");
6. var links_obj = $(this);
7. if (typeof links !== 'undefined') {
8. $.each(to_avoid, function(index, value) {
9. if (links.indexOf(value) < 0 && links !== '/') {
10. var href = links_obj.addClass('ajaxify-pages-processed');
11. href = decodeURIComponent(href);
12. if (href.indexOf("<script>") > 0) {
13. return false;
14. }
15. if (typeof href !== 'undefined') {
16. $(this).click(function() {
17. History.pushState(null, null, href);
18. return false;
19. }); }} }); } });
History.js и Drupal
(Привязка к URL)
1. if (typeof Drupal.settings.ajaxify_pages.processed !== 'undefined') {
2. return false;
3. }
4. Drupal.settings.ajaxify_pages.processed = 'processed';
5. Drupal.ajaxify_pages = {cache: {}};
6. History.Adapter.bind(window, 'statechange', function() {
7. loadPage(History.getState().url);
8. });
9. Drupal.ajaxify_pages.cache[History.getState().url] = {
10. title: $('title').html(),
11. content: $(Drupal.settings.ajaxify_pages.content_selector)
12. };
13. };
History.js и Drupal
(Привязка к URL) Разбор полётов
Что, и зачем мы сделали ?
1. Указываем в админке части URL, при нахождении которых, мы
игнорируем URL. (Избегаем внешних ссылок, картинок и т.д);
2. Заменяем каждую escape-последовательность в закодированном URI
символом, который она представляет;
3. Вталкивает новое "состояния" в браузер;
4. Привязываемся к событию смены состояния страницы, и вызываемся
функцию, которая будет получать новый контент;
5. Сохраняем новые значения; (При возврате на URI, на котором мы уже
были, можно вытащить уже сохранённые значения, что бы не делать
лишний AJAX запрос)
History.js и Drupal
Получаем новый контент
Для получения контента, делаем обычный AJAX запрос, НО ! :
1. Drupal, генерирует BODY классы в зависимости от страницы, так что не
забываем их заменять на "новой" странице;
2. Разные страницы могут иметь разные CSS файлы, их тоже нужно
добавить;
3. Разные страницы могут иметь разные JS файлы, и их :) ;
4. Меняем title страницы;
5. Не забываем про Trobber, потому как AJAX запрос может быть разной
продолжительности;
History.js и Drupal
Получаем новый контент (немного кода)
1. Drupal.ajaxify_pages.cache[url] = {
2. title: new_page.title,
3. content: new_page.content,
4. scripts: new_page.new_script,
5. css: new_page.new_css,
6. body_class: new_page.body_class,
7. admin_menu: new_page.admin_menu
8. };
9. processPage(Drupal.ajaxify_pages.cache[url], url);
Не забываем сохранить страницу в "кэш", что бы мы в следующий раз,
при возвращении Back в браузере, ну или новым кликом на ссылку
этой страницы, не делали новый AJAX запрос, а использовали
существующие данные.
History.js и Drupal
Заменяем контент
1. $('head script').each(function() {
2. if ($(this)[0].src.length > 0) {
3. to_replace.page_script.push($(this)[0].src.match(/([^<]+)(.js)/)[0]);
4. }
5. if ($(this).text().length > 0) {
6. $(this).remove();
7. }
8. });
9.
10. if (typeof to_replace.new_script !== 'undefined') {
11. $.grep(to_replace.new_script, function(el) {
12. if ($.inArray(el, to_replace.page_script) === -1)
13. to_replace.diff_script.push(el);
14. i++;
15. });
16. }
History.js и Drupal
Заменяем контент
Нет нужды заменять все JS файлы, потому что при этом, будут
перезапущены все скрипты. При этом, не стоит пугаться что JS или CSS
файл не появился в вашем DOM-e.
Мы только добавляем новые файлы.
В определённый момент, у нас соберутся в кучу все JS и CSS файлы
сайты, но на мой взгляд, это не смертельно.
Так же, не стоит забывать, что Drupal делает агрегацию файлов, то есть
добавляет символы в конец имени файла. Это надо учесть при получении
и сравнении новых файлов.
History.js и Drupal
Views, как быть ?
1. Drupal.settings.views = {
2. ajaxViews: {},
3. ajax_path: "/views/ajax"
4. };
5. $("[class^=view]").ready(function() {
6. $(".view").each(function() {
7. if ($("[class*=view-]").length > 0 && $("[class*=view-dom-id]").length
> 0 && $("[class*=view-display-id]").length > 0) {
8. var view_classes_array = $("[class*=view-]").attr('class').split(' '),
9. view_name = view_classes_array[1].replace(/view-/g, ""),
10. view_display_id = view_classes_array[3].replace(/view-display-
id-/g, ""),
11. view_dom_id = view_classes_array[4].replace(/view-dom-id-/g,
""),
12. view_path = '';
13. view_path = location.pathname.substring(1,
location.pathname.length);
14. view_name = view_name.replace("-", "_");
History.js и Drupal
Views, как быть ?
1. Drupal.settings.views.ajaxViews['views_dom_id:'+view_display_id] = {
2. pager_element: "0",
3. view_args: "",
4. view_base_path: null,
5. view_display_id: view_display_id,
6. view_dom_id: view_dom_id,
7. view_name: view_name,
8. view_path: view_path
9. };
10. }
11. });
12. });
History.js и Drupal
Views, как быть? (Разбор полётов)
Так как мы получаем контент по AJAX, все JS обьекты, мы строим рукчами :(
pager_element - Элемент страничной навигации;
view_args - Аргумент передаваеммый во Views;
view_base_path - Родной адресс Views;
view_display_id - ID "отображения" Views;
view_dom_id - Рандомный хэш, который присваивается как класс контейнеру
Views;
view_name - Машинное имя Views;
view_path - URL на котором вызывается Views. При совпадении с
view_base_path, можно указывать только view_path, а view_base_path оставить
как NULL.
• Drupal.settings.views = {
• ajaxViews: {},
• ajax_path: "/views/ajax"
• };
Views обьект в которов будет список
всех Views на странице.
Каждая Views идентифицируется с
помощью ключа
"'views_dom_id:'+view_display_id"
History.js и Drupal
Views, как быть? (Разбор полётов)
Приведенный пример, должен использоывться не только по отношению ко
Views, но также и в случае AJAX форм, Ctools modals, Omega layouts ... в
общем ко всему что могло бы быть динамично добавлено при генерации
страницы.
Спасибо за Внимание !
Drupal 7 и history.js или как ajax инфицировать сайт

Mais conteúdo relacionado

Mais procurados

XML Native Database на примере SednaXML
XML Native Database на примере SednaXMLXML Native Database на примере SednaXML
XML Native Database на примере SednaXMLSlach
 
Web осень 2013 лекция 3
Web осень 2013 лекция 3Web осень 2013 лекция 3
Web осень 2013 лекция 3Technopark
 
Школа-студия разработки для iOS. Лекция 4. Работа с данными
Школа-студия разработки для iOS. Лекция 4. Работа с даннымиШкола-студия разработки для iOS. Лекция 4. Работа с данными
Школа-студия разработки для iOS. Лекция 4. Работа с даннымиГлеб Тарасов
 
basis.js - почему я не бросил разрабатывать свой фреймворк
basis.js - почему я не бросил разрабатывать свой фреймворкbasis.js - почему я не бросил разрабатывать свой фреймворк
basis.js - почему я не бросил разрабатывать свой фреймворкRoman Dvornov
 
YiiConf: Миграции и инсталляции
YiiConf: Миграции и инсталляцииYiiConf: Миграции и инсталляции
YiiConf: Миграции и инсталляцииPaul Klimov
 
Database (Lecture 14 – database)
Database (Lecture 14 – database)Database (Lecture 14 – database)
Database (Lecture 14 – database)Noveo
 
Basis.js - почему я не бросил разрабатывать свой фреймворк (extended)
Basis.js - почему я не бросил разрабатывать свой фреймворк (extended)Basis.js - почему я не бросил разрабатывать свой фреймворк (extended)
Basis.js - почему я не бросил разрабатывать свой фреймворк (extended)Roman Dvornov
 
C# Web. Занятие 12.
C# Web. Занятие 12.C# Web. Занятие 12.
C# Web. Занятие 12.Igor Shkulipa
 
Cookies, session и другое в JSP
Cookies, session и другое в JSPCookies, session и другое в JSP
Cookies, session и другое в JSPUnguryan Vitaliy
 
Web осень 2013 лекция 1
Web осень 2013 лекция 1Web осень 2013 лекция 1
Web осень 2013 лекция 1Technopark
 
2013 09 19 кеширование на клиенте и сервере
2013 09 19 кеширование на клиенте и сервере2013 09 19 кеширование на клиенте и сервере
2013 09 19 кеширование на клиенте и сервереYandex
 
Александр Шуменко - Varnish for authenticated users
Александр Шуменко - Varnish for authenticated usersАлександр Шуменко - Varnish for authenticated users
Александр Шуменко - Varnish for authenticated usersLEDC 2016
 
JavaScript-библиотека
JavaScript-библиотекаJavaScript-библиотека
JavaScript-библиотекаVasya Petrov
 
хранение данных
хранение данныххранение данных
хранение данныхNoveo
 
Олег Годовых «Страх и ненависть в Event Bus»
Олег Годовых «Страх и ненависть в Event Bus»Олег Годовых «Страх и ненависть в Event Bus»
Олег Годовых «Страх и ненависть в Event Bus»DevDay
 
Страх и ненависть в Event Bus
Страх и ненависть в Event BusСтрах и ненависть в Event Bus
Страх и ненависть в Event Bus0leGG
 
Примеры быстрой разработки API на масштабируемом сервере приложений Impress д...
Примеры быстрой разработки API на масштабируемом сервере приложений Impress д...Примеры быстрой разработки API на масштабируемом сервере приложений Impress д...
Примеры быстрой разработки API на масштабируемом сервере приложений Impress д...Timur Shemsedinov
 
константин лебедев
константин лебедевконстантин лебедев
константин лебедевkuchinskaya
 

Mais procurados (20)

XML Native Database на примере SednaXML
XML Native Database на примере SednaXMLXML Native Database на примере SednaXML
XML Native Database на примере SednaXML
 
Web осень 2013 лекция 3
Web осень 2013 лекция 3Web осень 2013 лекция 3
Web осень 2013 лекция 3
 
Школа-студия разработки для iOS. Лекция 4. Работа с данными
Школа-студия разработки для iOS. Лекция 4. Работа с даннымиШкола-студия разработки для iOS. Лекция 4. Работа с данными
Школа-студия разработки для iOS. Лекция 4. Работа с данными
 
JDBC
JDBCJDBC
JDBC
 
basis.js - почему я не бросил разрабатывать свой фреймворк
basis.js - почему я не бросил разрабатывать свой фреймворкbasis.js - почему я не бросил разрабатывать свой фреймворк
basis.js - почему я не бросил разрабатывать свой фреймворк
 
YiiConf: Миграции и инсталляции
YiiConf: Миграции и инсталляцииYiiConf: Миграции и инсталляции
YiiConf: Миграции и инсталляции
 
Database (Lecture 14 – database)
Database (Lecture 14 – database)Database (Lecture 14 – database)
Database (Lecture 14 – database)
 
Basis.js - почему я не бросил разрабатывать свой фреймворк (extended)
Basis.js - почему я не бросил разрабатывать свой фреймворк (extended)Basis.js - почему я не бросил разрабатывать свой фреймворк (extended)
Basis.js - почему я не бросил разрабатывать свой фреймворк (extended)
 
C# Web. Занятие 12.
C# Web. Занятие 12.C# Web. Занятие 12.
C# Web. Занятие 12.
 
Cookies, session и другое в JSP
Cookies, session и другое в JSPCookies, session и другое в JSP
Cookies, session и другое в JSP
 
Web осень 2013 лекция 1
Web осень 2013 лекция 1Web осень 2013 лекция 1
Web осень 2013 лекция 1
 
2013 09 19 кеширование на клиенте и сервере
2013 09 19 кеширование на клиенте и сервере2013 09 19 кеширование на клиенте и сервере
2013 09 19 кеширование на клиенте и сервере
 
Александр Шуменко - Varnish for authenticated users
Александр Шуменко - Varnish for authenticated usersАлександр Шуменко - Varnish for authenticated users
Александр Шуменко - Varnish for authenticated users
 
JavaScript-библиотека
JavaScript-библиотекаJavaScript-библиотека
JavaScript-библиотека
 
JSP
JSPJSP
JSP
 
хранение данных
хранение данныххранение данных
хранение данных
 
Олег Годовых «Страх и ненависть в Event Bus»
Олег Годовых «Страх и ненависть в Event Bus»Олег Годовых «Страх и ненависть в Event Bus»
Олег Годовых «Страх и ненависть в Event Bus»
 
Страх и ненависть в Event Bus
Страх и ненависть в Event BusСтрах и ненависть в Event Bus
Страх и ненависть в Event Bus
 
Примеры быстрой разработки API на масштабируемом сервере приложений Impress д...
Примеры быстрой разработки API на масштабируемом сервере приложений Impress д...Примеры быстрой разработки API на масштабируемом сервере приложений Impress д...
Примеры быстрой разработки API на масштабируемом сервере приложений Impress д...
 
константин лебедев
константин лебедевконстантин лебедев
константин лебедев
 

Semelhante a Drupal 7 и history.js или как ajax инфицировать сайт

Web весна 2012 лекция 9
Web весна 2012 лекция 9Web весна 2012 лекция 9
Web весна 2012 лекция 9Technopark
 
Webuibasics - Lesson 3 - Nginx, SSI (in russian)
Webuibasics - Lesson 3 - Nginx, SSI (in russian)Webuibasics - Lesson 3 - Nginx, SSI (in russian)
Webuibasics - Lesson 3 - Nginx, SSI (in russian)xasima
 
Документирование исходных текстов (javadoc)
Документирование исходных текстов (javadoc)Документирование исходных текстов (javadoc)
Документирование исходных текстов (javadoc)Fedor Malyshkin
 
FrontTalks: Константин Лебедев (Mail.ru), File API: обработка файлов на клиен...
FrontTalks: Константин Лебедев (Mail.ru), File API: обработка файлов на клиен...FrontTalks: Константин Лебедев (Mail.ru), File API: обработка файлов на клиен...
FrontTalks: Константин Лебедев (Mail.ru), File API: обработка файлов на клиен...Yandex
 
JavaScript Базовый. Занятие 08.
JavaScript Базовый. Занятие 08.JavaScript Базовый. Занятие 08.
JavaScript Базовый. Занятие 08.Igor Shkulipa
 
Кеширование. Api. http 1.1 (rfc 2616)
Кеширование. Api. http 1.1 (rfc 2616)Кеширование. Api. http 1.1 (rfc 2616)
Кеширование. Api. http 1.1 (rfc 2616)Artjoker
 
Библиотеки для передачи данных (Lecture 13 – multithreading, network (libs))
Библиотеки для передачи данных (Lecture 13 – multithreading, network (libs))Библиотеки для передачи данных (Lecture 13 – multithreading, network (libs))
Библиотеки для передачи данных (Lecture 13 – multithreading, network (libs))Noveo
 
Практическое применение HTML5 в Я.Почте
Практическое применение HTML5 в Я.ПочтеПрактическое применение HTML5 в Я.Почте
Практическое применение HTML5 в Я.ПочтеAlexey Androsov
 
#6 "Изоморфный фреймворк Catberry.js" Денис Речкунов
#6 "Изоморфный фреймворк Catberry.js" Денис Речкунов#6 "Изоморфный фреймворк Catberry.js" Денис Речкунов
#6 "Изоморфный фреймворк Catberry.js" Денис РечкуновJSib
 
Node.js введение в технологию, КПИ #ITmeetingKPI
Node.js введение в технологию, КПИ  #ITmeetingKPINode.js введение в технологию, КПИ  #ITmeetingKPI
Node.js введение в технологию, КПИ #ITmeetingKPITimur Shemsedinov
 
Web весна 2013 лекция 3
Web весна 2013 лекция 3Web весна 2013 лекция 3
Web весна 2013 лекция 3Technopark
 
The Old New ASP.NET
The Old New ASP.NETThe Old New ASP.NET
The Old New ASP.NETVitaly Baum
 
библиотека Google closure java script
библиотека Google closure java scriptбиблиотека Google closure java script
библиотека Google closure java scriptYova Stoika
 
Интеграция Яндекс Сервер
Интеграция Яндекс СерверИнтеграция Яндекс Сервер
Интеграция Яндекс СерверPVasili
 
TARS: Сделай уровень frontend-рутины 0% — Артём Малко, 2ГИС
TARS: Сделай уровень frontend-рутины 0% — Артём Малко, 2ГИСTARS: Сделай уровень frontend-рутины 0% — Артём Малко, 2ГИС
TARS: Сделай уровень frontend-рутины 0% — Артём Малко, 2ГИС2ГИС Технологии
 

Semelhante a Drupal 7 и history.js или как ajax инфицировать сайт (20)

Web весна 2012 лекция 9
Web весна 2012 лекция 9Web весна 2012 лекция 9
Web весна 2012 лекция 9
 
Webuibasics - Lesson 3 - Nginx, SSI (in russian)
Webuibasics - Lesson 3 - Nginx, SSI (in russian)Webuibasics - Lesson 3 - Nginx, SSI (in russian)
Webuibasics - Lesson 3 - Nginx, SSI (in russian)
 
Документирование исходных текстов (javadoc)
Документирование исходных текстов (javadoc)Документирование исходных текстов (javadoc)
Документирование исходных текстов (javadoc)
 
FrontTalks: Константин Лебедев (Mail.ru), File API: обработка файлов на клиен...
FrontTalks: Константин Лебедев (Mail.ru), File API: обработка файлов на клиен...FrontTalks: Константин Лебедев (Mail.ru), File API: обработка файлов на клиен...
FrontTalks: Константин Лебедев (Mail.ru), File API: обработка файлов на клиен...
 
JavaScript Базовый. Занятие 08.
JavaScript Базовый. Занятие 08.JavaScript Базовый. Занятие 08.
JavaScript Базовый. Занятие 08.
 
Кеширование. Api. http 1.1 (rfc 2616)
Кеширование. Api. http 1.1 (rfc 2616)Кеширование. Api. http 1.1 (rfc 2616)
Кеширование. Api. http 1.1 (rfc 2616)
 
Библиотеки для передачи данных (Lecture 13 – multithreading, network (libs))
Библиотеки для передачи данных (Lecture 13 – multithreading, network (libs))Библиотеки для передачи данных (Lecture 13 – multithreading, network (libs))
Библиотеки для передачи данных (Lecture 13 – multithreading, network (libs))
 
Module 4
Module 4Module 4
Module 4
 
Практическое применение HTML5 в Я.Почте
Практическое применение HTML5 в Я.ПочтеПрактическое применение HTML5 в Я.Почте
Практическое применение HTML5 в Я.Почте
 
#6 "Изоморфный фреймворк Catberry.js" Денис Речкунов
#6 "Изоморфный фреймворк Catberry.js" Денис Речкунов#6 "Изоморфный фреймворк Catberry.js" Денис Речкунов
#6 "Изоморфный фреймворк Catberry.js" Денис Речкунов
 
Jsfwdays 2013-2
Jsfwdays 2013-2Jsfwdays 2013-2
Jsfwdays 2013-2
 
Node.js введение в технологию, КПИ #ITmeetingKPI
Node.js введение в технологию, КПИ  #ITmeetingKPINode.js введение в технологию, КПИ  #ITmeetingKPI
Node.js введение в технологию, КПИ #ITmeetingKPI
 
Web весна 2013 лекция 3
Web весна 2013 лекция 3Web весна 2013 лекция 3
Web весна 2013 лекция 3
 
Backbone js
Backbone jsBackbone js
Backbone js
 
JSSDK: Начало
JSSDK: НачалоJSSDK: Начало
JSSDK: Начало
 
The Old New ASP.NET
The Old New ASP.NETThe Old New ASP.NET
The Old New ASP.NET
 
библиотека Google closure java script
библиотека Google closure java scriptбиблиотека Google closure java script
библиотека Google closure java script
 
Интеграция Яндекс Сервер
Интеграция Яндекс СерверИнтеграция Яндекс Сервер
Интеграция Яндекс Сервер
 
TARS: Сделай уровень frontend-рутины 0% — Артём Малко, 2ГИС
TARS: Сделай уровень frontend-рутины 0% — Артём Малко, 2ГИСTARS: Сделай уровень frontend-рутины 0% — Артём Малко, 2ГИС
TARS: Сделай уровень frontend-рутины 0% — Артём Малко, 2ГИС
 
Eternal static (RIT 2011)
Eternal static (RIT 2011)Eternal static (RIT 2011)
Eternal static (RIT 2011)
 

Mais de DrupalCamp Kyiv Рысь

система управления конфигурацией в Drupal 8. анализ результатов изменений.
система управления конфигурацией в Drupal 8. анализ результатов изменений.система управления конфигурацией в Drupal 8. анализ результатов изменений.
система управления конфигурацией в Drupal 8. анализ результатов изменений.DrupalCamp Kyiv Рысь
 
ознакомления с модулем Entity api
ознакомления с модулем Entity apiознакомления с модулем Entity api
ознакомления с модулем Entity apiDrupalCamp Kyiv Рысь
 
Cdn hosting решения для drupal (medium)
Cdn hosting   решения для drupal (medium)Cdn hosting   решения для drupal (medium)
Cdn hosting решения для drupal (medium)DrupalCamp Kyiv Рысь
 
Aegir. развертывание и управление большой сетью drupal сайтов
Aegir. развертывание и управление большой сетью drupal сайтовAegir. развертывание и управление большой сетью drupal сайтов
Aegir. развертывание и управление большой сетью drupal сайтовDrupalCamp Kyiv Рысь
 

Mais de DrupalCamp Kyiv Рысь (17)

Drupal association slides us 2013
Drupal association slides us 2013Drupal association slides us 2013
Drupal association slides us 2013
 
Drupal association slides ru
Drupal association slides ruDrupal association slides ru
Drupal association slides ru
 
#D8 cx: upgrade your modules to drupal 8
#D8 cx: upgrade your modules to drupal 8 #D8 cx: upgrade your modules to drupal 8
#D8 cx: upgrade your modules to drupal 8
 
Game of-sales-presentation
Game of-sales-presentationGame of-sales-presentation
Game of-sales-presentation
 
Backbone js-slides
Backbone js-slidesBackbone js-slides
Backbone js-slides
 
система управления конфигурацией в Drupal 8. анализ результатов изменений.
система управления конфигурацией в Drupal 8. анализ результатов изменений.система управления конфигурацией в Drupal 8. анализ результатов изменений.
система управления конфигурацией в Drupal 8. анализ результатов изменений.
 
симфони это не страшно
симфони   это не страшносимфони   это не страшно
симфони это не страшно
 
ознакомления с модулем Entity api
ознакомления с модулем Entity apiознакомления с модулем Entity api
ознакомления с модулем Entity api
 
Services в drupal 8
Services в drupal 8Services в drupal 8
Services в drupal 8
 
Facet api
Facet apiFacet api
Facet api
 
Facet api
Facet apiFacet api
Facet api
 
Erpal erp with drupal
Erpal   erp with drupalErpal   erp with drupal
Erpal erp with drupal
 
Drupal 8 theming principles
Drupal 8 theming principlesDrupal 8 theming principles
Drupal 8 theming principles
 
Cdn hosting решения для drupal (medium)
Cdn hosting   решения для drupal (medium)Cdn hosting   решения для drupal (medium)
Cdn hosting решения для drupal (medium)
 
Aegir. развертывание и управление большой сетью drupal сайтов
Aegir. развертывание и управление большой сетью drupal сайтовAegir. развертывание и управление большой сетью drupal сайтов
Aegir. развертывание и управление большой сетью drupal сайтов
 
Behat
BehatBehat
Behat
 
что нового в мире Services
что нового в мире Servicesчто нового в мире Services
что нового в мире Services
 

Drupal 7 и history.js или как ajax инфицировать сайт

  • 1. Drupal 7 и History.js или как AJAX-ифицировать сайт. Малай Вадим Drupal developer vadim.malai@wearepropeople.com
  • 2. Зачем ? • Иметь статичную зону контента. • Иметь возможность навигации Back или Forward в истории browser-a • Избежать несоответствий при использовании родного window.History
  • 4. History.js (Введение) • Придерживается HTML5 History API насколько это возможно; • Кросбраузерность для всех HTML5 браузеров; • Поддержка HTML4 браузеров; • Адаптация link-ов в зависимости от HTML5 или HTML4; • Поддержка javaScript framerork-ов как " jQuery", "MooTools", "Prototype", "Zepto".
  • 5. History.js (Где это работает ?) HTML5 Browsers HTML4 Browsers HTML5 Browsers Firefox 4+ Safari 5.0+ Chrome 8+ Safari iOS 4.3+ Opera 11.5 IE 6, 7, 8, 9 Safari 4 Firefox 3 Safari iOS 4.2, 4.1, 4.0, 3.2 Opera 10, 11.0
  • 6.
  • 7. History.js (Как это работает ?) (function(window,undefined){ var History = window.History; // Bind to StateChange Event History.Adapter.bind(window,'statechange',function(){ // Note: We are using statechange instead of popstate var State = History.getState(); // Note: We are using History.getState() instead of event.state History.log(State.data, State.title, State.url); }); // Change our States History.pushState({state:1}, "State 1", "?state=1"); // logs {state:1}, "State 1", "?state=1" History.pushState({state:2}, "State 2", "?state=2"); // logs {state:2}, "State 2", "?state=2" History.replaceState({state:3}, "State 3", "?state=3"); // logs {state:3}, "State 3", "?state=3" History.pushState(null, null, "?state=4"); // logs {}, '', "?state=4" History.back(); // logs {state:3}, "State 3", "?state=3" History.back(); // logs {state:1}, "State 1", "?state=1" History.back(); // logs {}, "Home Page", "?" History.go(2); // logs {state:3}, "State 3", "?state=3" })(window);
  • 8.
  • 9. History.js (Разбор полётов) History.Adapter.bind(window,'statechange',function(){}); - Привязка к событию (Срабатывает, когда состояние страницы изменилось). History.getState() - Получает текущее состояние браузера, возвращает объект с data, title и url. History.pushState({state:1}, "State 1", "?state=1") - Вталкивает новое "состояния" в браузер; data может быть нулевыми или объектом, title может быть нулевым или строкой, URL должен быть строкой.
  • 10. History.js (Разбор полётов) History.replaceState({state:3}, "State 3", "?state=3") - Заменяет существующее "состояние" новым; (В случае замены, будет утеряно "состояние" предшествующее нынешнему) History.back() - Назад в историю на 1 шаг; History.go(2) - Вперед в историю на 2 шага; History.log(...) - Вывод сообщения в консоли;
  • 11. History.js (Что еще?) События : 1. 'statechange' - Срабатывает, когда состояние страницы изменилось; 2. 'onanchrorchange' - Срабатывает, когда "якорь" страницы изменился; History.replaceState(data,title,url) - Заменяет текущее состояние страницы новым. History.getHash() - Возвращает значение URL после # (hash); (HTML 4) History.Adapter.trigger(element,event) - Триггер события; History.Adapter.onDomLoad(callback) - onDomLoad связующее; History.forward() - шаг впреред в историю браузера; History.debug(...) - тоже что и History.log(...), но работает только если History.debug.enable === true
  • 13. History.js и Drupal (Привязка к URL) 1. Drupal.behaviors.ajaxify_pages = {}; 2. Drupal.behaviors.ajaxify_pages.attach = function(context, settings) { 3. $(Drupal.settings.ajaxify_pages.links_selector, context).each(function() { 4. var to_avoid = Drupal.settings.ajaxify_pages.links_to_avoid; 5. var links = $(this).attr("href"); 6. var links_obj = $(this); 7. if (typeof links !== 'undefined') { 8. $.each(to_avoid, function(index, value) { 9. if (links.indexOf(value) < 0 && links !== '/') { 10. var href = links_obj.addClass('ajaxify-pages-processed'); 11. href = decodeURIComponent(href); 12. if (href.indexOf("<script>") > 0) { 13. return false; 14. } 15. if (typeof href !== 'undefined') { 16. $(this).click(function() { 17. History.pushState(null, null, href); 18. return false; 19. }); }} }); } });
  • 14. History.js и Drupal (Привязка к URL) 1. if (typeof Drupal.settings.ajaxify_pages.processed !== 'undefined') { 2. return false; 3. } 4. Drupal.settings.ajaxify_pages.processed = 'processed'; 5. Drupal.ajaxify_pages = {cache: {}}; 6. History.Adapter.bind(window, 'statechange', function() { 7. loadPage(History.getState().url); 8. }); 9. Drupal.ajaxify_pages.cache[History.getState().url] = { 10. title: $('title').html(), 11. content: $(Drupal.settings.ajaxify_pages.content_selector) 12. }; 13. };
  • 15.
  • 16. History.js и Drupal (Привязка к URL) Разбор полётов Что, и зачем мы сделали ? 1. Указываем в админке части URL, при нахождении которых, мы игнорируем URL. (Избегаем внешних ссылок, картинок и т.д); 2. Заменяем каждую escape-последовательность в закодированном URI символом, который она представляет; 3. Вталкивает новое "состояния" в браузер; 4. Привязываемся к событию смены состояния страницы, и вызываемся функцию, которая будет получать новый контент; 5. Сохраняем новые значения; (При возврате на URI, на котором мы уже были, можно вытащить уже сохранённые значения, что бы не делать лишний AJAX запрос)
  • 17. History.js и Drupal Получаем новый контент Для получения контента, делаем обычный AJAX запрос, НО ! : 1. Drupal, генерирует BODY классы в зависимости от страницы, так что не забываем их заменять на "новой" странице; 2. Разные страницы могут иметь разные CSS файлы, их тоже нужно добавить; 3. Разные страницы могут иметь разные JS файлы, и их :) ; 4. Меняем title страницы; 5. Не забываем про Trobber, потому как AJAX запрос может быть разной продолжительности;
  • 18. History.js и Drupal Получаем новый контент (немного кода) 1. Drupal.ajaxify_pages.cache[url] = { 2. title: new_page.title, 3. content: new_page.content, 4. scripts: new_page.new_script, 5. css: new_page.new_css, 6. body_class: new_page.body_class, 7. admin_menu: new_page.admin_menu 8. }; 9. processPage(Drupal.ajaxify_pages.cache[url], url); Не забываем сохранить страницу в "кэш", что бы мы в следующий раз, при возвращении Back в браузере, ну или новым кликом на ссылку этой страницы, не делали новый AJAX запрос, а использовали существующие данные.
  • 19. History.js и Drupal Заменяем контент 1. $('head script').each(function() { 2. if ($(this)[0].src.length > 0) { 3. to_replace.page_script.push($(this)[0].src.match(/([^<]+)(.js)/)[0]); 4. } 5. if ($(this).text().length > 0) { 6. $(this).remove(); 7. } 8. }); 9. 10. if (typeof to_replace.new_script !== 'undefined') { 11. $.grep(to_replace.new_script, function(el) { 12. if ($.inArray(el, to_replace.page_script) === -1) 13. to_replace.diff_script.push(el); 14. i++; 15. }); 16. }
  • 20. History.js и Drupal Заменяем контент Нет нужды заменять все JS файлы, потому что при этом, будут перезапущены все скрипты. При этом, не стоит пугаться что JS или CSS файл не появился в вашем DOM-e. Мы только добавляем новые файлы. В определённый момент, у нас соберутся в кучу все JS и CSS файлы сайты, но на мой взгляд, это не смертельно. Так же, не стоит забывать, что Drupal делает агрегацию файлов, то есть добавляет символы в конец имени файла. Это надо учесть при получении и сравнении новых файлов.
  • 21. History.js и Drupal Views, как быть ? 1. Drupal.settings.views = { 2. ajaxViews: {}, 3. ajax_path: "/views/ajax" 4. }; 5. $("[class^=view]").ready(function() { 6. $(".view").each(function() { 7. if ($("[class*=view-]").length > 0 && $("[class*=view-dom-id]").length > 0 && $("[class*=view-display-id]").length > 0) { 8. var view_classes_array = $("[class*=view-]").attr('class').split(' '), 9. view_name = view_classes_array[1].replace(/view-/g, ""), 10. view_display_id = view_classes_array[3].replace(/view-display- id-/g, ""), 11. view_dom_id = view_classes_array[4].replace(/view-dom-id-/g, ""), 12. view_path = ''; 13. view_path = location.pathname.substring(1, location.pathname.length); 14. view_name = view_name.replace("-", "_");
  • 22. History.js и Drupal Views, как быть ? 1. Drupal.settings.views.ajaxViews['views_dom_id:'+view_display_id] = { 2. pager_element: "0", 3. view_args: "", 4. view_base_path: null, 5. view_display_id: view_display_id, 6. view_dom_id: view_dom_id, 7. view_name: view_name, 8. view_path: view_path 9. }; 10. } 11. }); 12. });
  • 23. History.js и Drupal Views, как быть? (Разбор полётов) Так как мы получаем контент по AJAX, все JS обьекты, мы строим рукчами :( pager_element - Элемент страничной навигации; view_args - Аргумент передаваеммый во Views; view_base_path - Родной адресс Views; view_display_id - ID "отображения" Views; view_dom_id - Рандомный хэш, который присваивается как класс контейнеру Views; view_name - Машинное имя Views; view_path - URL на котором вызывается Views. При совпадении с view_base_path, можно указывать только view_path, а view_base_path оставить как NULL. • Drupal.settings.views = { • ajaxViews: {}, • ajax_path: "/views/ajax" • }; Views обьект в которов будет список всех Views на странице. Каждая Views идентифицируется с помощью ключа "'views_dom_id:'+view_display_id"
  • 24. History.js и Drupal Views, как быть? (Разбор полётов) Приведенный пример, должен использоывться не только по отношению ко Views, но также и в случае AJAX форм, Ctools modals, Omega layouts ... в общем ко всему что могло бы быть динамично добавлено при генерации страницы.