• Save
Drupal 7 и history.js или как ajax инфицировать сайт
Upcoming SlideShare
Loading in...5
×
 

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

on

  • 913 views

 

Statistics

Views

Total Views
913
Views on SlideShare
295
Embed Views
618

Actions

Likes
1
Downloads
0
Comments
0

1 Embed 618

http://camp13.drupal.ua 618

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

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

  • Drupal 7 и History.jsиликак AJAX-ифицировать сайт.Малай ВадимDrupal developervadim.malai@wearepropeople.com
  • Зачем ?• Иметь статичную зону контента.• Иметь возможность навигации Backили Forward в истории browser-a• Избежать несоответствий прииспользовании родногоwindow.History
  • Составляющие1. Ajaxify Pages2. History.js3. Libraries
  • History.js (Введение)• Придерживается HTML5 History APIнасколько это возможно;• Кросбраузерность для всех HTML5браузеров;• Поддержка HTML4 браузеров;• Адаптация link-ов в зависимости отHTML5 или HTML4;• Поддержка javaScript framerork-ов как "jQuery", "MooTools", "Prototype", "Zepto".
  • History.js (Где это работает ?)HTML5 BrowsersHTML4 BrowsersHTML5 BrowsersFirefox 4+ Safari 5.0+Chrome 8+ Safari iOS 4.3+Opera 11.5IE 6, 7, 8, 9 Safari 4Firefox 3 Safari iOS 4.2, 4.1,4.0, 3.2Opera 10, 11.0
  • History.js (Как это работает ?)(function(window,undefined){var History = window.History;// Bind to StateChange EventHistory.Adapter.bind(window,statechange,function(){ // Note: We are using statechange instead of popstatevar State = History.getState(); // Note: We are using History.getState() instead of event.stateHistory.log(State.data, State.title, State.url);});// Change our StatesHistory.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_menu8. };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 и DrupalViews, как быть ?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 и DrupalViews, как быть ?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_path9. };10. }11. });12. });
  • History.js и DrupalViews, как быть? (Разбор полётов)Так как мы получаем контент по 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 и DrupalViews, как быть? (Разбор полётов)Приведенный пример, должен использоывться не только по отношению коViews, но также и в случае AJAX форм, Ctools modals, Omega layouts ... вобщем ко всему что могло бы быть динамично добавлено при генерациистраницы.
  • Спасибо за Внимание !