Кэширование и динамические данные в Drupal. Загружаем с помощью AJAX.

Чтобы сайт работал быстро, очевидно, что контент нужно кэшировать. Но если делать “в лоб”, например, используя модули display cache или закэшировать вывод views, то контент, который должен меняться для каждого пользователя тоже станет статичным.

Выход – часть контента кэшировать, а часть грузить с помощью AJAX.

Делюсь простым способом организовать AJAX подгрузку динамическиго контента после загрузки основного содержимого.

Ссылка на статью.

P.S. Интересно кто как решает эту задачу.

Источник: http://www.drupal.ru/node/116446

Ajax Nodeloader (D6, D7) – модуль для загрузки материалов с помощью AJAX

Модуль Ajax Nodeloader позволит вам:

Загружать и показывать страницы Drupal (node) с помощью AJAX Использовать произвольные css-селекторы для отображения вашего контента (title, body и т.д.) Загружать и отображать любые поля (node fields) для Drupal 7 Отслеживать посещения ваших AJAX-ссылок с помощью Google Analyitcs (требуется установленный Google Analytics) (опция) Использовать расширенную навигацию на основе HTML5 history API или хэш-тэгах (для устаревших браузеров) (опция) Динамически изменять заголовок браузера (опция)

2. Частые вопросы по использованию модуля.

Домашняя страница: http://www.denry.ru/drupal-ajax-nodeloader/
Частые вопросы: http://www.denry.ru/programmirovanie/662-ajax-nodeloader-f-a-q-ru/

3. Загрузка

Существует несколько способов скачать этот модуль:

1. Скачать файлы .zip с github.com

7.x-1.x.zip

6.x-1.x.zip

2. или клонировать исходный код модуля с drupal.org

Версия для Drupal 7:

git clone –branch 7.x-1.x http://git.drupal.org/sandbox/nick-denry/1447152.git ajax_nodeloader
cd ajax_nodeloader

Версия для Drupal 6:

git clone –branch 6.x-1.x http://git.drupal.org/sandbox/nick-denry/1447152.git ajax_nodeloader
cd ajax_nodeloader

или github.com

git://github.com/nick-denry/Ajax-Nodeloader.git

Внимание! Ajax Nodeloader — это проект с открытым исходным кодом, однако в настоящий момент код является экспериментальным и проходит проверку на drupal.org (en).

AJAX nodeloader на drupal.org:
http://drupal.org/sandbox/nick-denry/1447152

AJAX nodeloader на github.com:
https://github.com/nick-denry/Ajax-Nodeloader

В настоящее время модуль получил статус “reviewed & tested by the community”, но пока все еще явяется экспериментальным.

Источник: http://www.drupal.ru/node/83485

Ajax Form в Drupal7

По мотивам Как проще всего реализовать аякс с выдачей json” и Установка фокуса на элемент формы*.

В итоге, на память себе и может кому понадобится:

В hook_menu:

$items['path_to_page/%'] = array( 'type' => MENU_CALLBACK, 'page callback' => 'my_callback', 'delivery callback' => 'ajax_deliver', 'page arguments' => array(1), 'access arguments' => true, );

Непосредственно callback

function my_callback($fid) { $commands[] = ajax_command_replace('#ID_'.$fid, 'New value text'); $page = array('#type' => 'ajax', '#commands' => $commands); # если в форме у нас #type = submit ajax_deliver($page); # если у нас #type = link, то return $page; }

В форме у необходимого элемента прописываем:

'#ajax' => array( 'effect' => 'fade', # нижеперечисленное необходимо для #type = submit 'path' => 'path_to_page/'.$fid, 'event' => 'click', )

Если тип = link, необходимо ещё указать в аттрибутах класс use-ajax.

К чему все это написано:
не нашел нигде рабочего описания по работе с ajax['path'] вместо ajax['callback']
в случаях $form['element']['#type'] = ’submit’ или $form['element']['#type'] = ‘link’ – немного отличаются вывод и возврат callback.

P.S. сначала нашел решение, потом уже по delivery callback’y нашел эту статью и узнал про разницу в типах #type = submit|link.

Источник: http://www.drupal.ru/node/77567

Ajax Form в Drupal7

По мотивам Как проще всего реализовать аякс с выдачей json” и Установка фокуса на элемент формы*.

В итоге, на память себе и может кому понадобится:

В hook_menu:

$items['path_to_page/%'] = array( 'type' => MENU_CALLBACK, 'page callback' => 'my_callback', 'delivery callback' => 'ajax_deliver', 'page arguments' => array(1), 'access arguments' => true, );

Непосредственно callback

function my_callback($fid) { $commands[] = ajax_command_replace('#ID_'.$fid, 'New value text'); $page = array('#type' => 'ajax', '#commands' => $commands); # если в форме у нас #type = submit ajax_deliver($page); # если у нас #type = link, то return $page; }

В форме у необходимого элемента прописываем:

'#ajax' => array( 'effect' => 'fade', # нижеперечисленное необходимо для #type = submit 'path' => 'path_to_page/'.$fid, 'event' => 'click', )

Если тип = link, необходимо ещё указать в аттрибутах класс use-ajax.

К чему все это написано:
не нашел нигде рабочего описания по работе с ajax['path'] вместо ajax['callback']
в случаях $form['element']['#type'] = ’submit’ или $form['element']['#type'] = ‘link’ – немного отличаются вывод и возврат callback.

P.S. сначала нашел решение, потом уже по delivery callback’y нашел эту статью и узнал про разницу в типах #type = submit|link.

Источник: http://www.drupal.ru/node/77567

Ajax Microblog – стремимся реализовать Twitter.com

Рад общественности представить новый модуль. Это Ajax microblog. Данный модуль реализует функционал Twitter и будет развиваться в этом направлении. Целью модуля или пакета модулей является организация полной копии функционала предоставляемой всеми известной системой микроблогинга Twitter.com

Ссылка на проект: http://css.mirocow.com/projects/microblog
скачать тут: http://css.mirocow.com/projects/microblog/repository

Спонсор модуля: www.ruh.kz

Прикрепленный файл Размер e6674f3201affd625334c0d00cb96301.jpg 71.2 кб

Источник: http://www.drupal.ru/node/67970

Загрузка поля cck ajax-запросом.

На главной странице есть лента новостей. Она состоит из:
1. Дата новости;
2. Анонс новости;
3. Ссылка на саму новость.

Захотелось мне реализовать ajax-загрузку основного текста новости на место ссылки.
Изучив “как создать свой модуль”, основы javascript, jquery и вспомнив основы php-программирования я все таки реализовал свою идею. Возможно для профи это 5 минутное дело, у меня ушло около 5 дней в совокупности. Работу модуля можете посмотреть на www.appri.ru.
Модуль назвал loadnews. Здесь обноленный код.
Файл loadnews.module: <?php
/*
 * Implementing hook_init
 */

function loadnews_init() {
    drupal_add_css(drupal_get_path('module', 'loadnews') . "/loadnews.css");
  drupal_add_js(drupal_get_path('module', 'loadnews') ."/loadnews.js");
}

/*
 * Implementation hook_perm
 */
function loadnews_perm() {
  return array('access onthisdate content');
}

/**
 * Implementation hook_menu()
 */
function loadnews_menu() {
  // Элемент меню с соответствующим путем
  $items['loadnews'] = array (
    // Функция, которая будет "обрабатывать" путь
    'page callback' => 'loadnews_ajax',
    // Права на доступ к пути
    'access arguments' => array('access content'),
    // Элемент не будет отображаться в меню сайта
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/* Функция обработки запроса */
function loadnews_ajax() {
    /*
     * Ссылка на на новость передается методом GET в переменной 'url'
     * В БД алисы адресов хранятся без первого слеша, поэтом удаляем его
    */
    $url = substr($_GET['url'], 1);
    // По полученному алиасу ищем в таблице url_alias соответствующий системный адрес
    $sys_url = db_result(db_query("SELECT n.src FROM {url_alias} n WHERE dst = '%s'", $url));
    /* Адрес получаем в виде "node/nid". Нам нужно получить параметр nid.
     * Для этого разбиваем строку на массив из 2-х элементов, второй который наш nid
    */
    $sys_url_array = explode('/',$sys_url);
    // Сохраняем наш nid в переменную
    $nid = $sys_url_array['1'];
    // Выбираем поле основного текста новости "field_news_text_value" из таблицы "content_type_news"
    $result = db_result(db_query("SELECT n.field_news_text_value FROM {content_type_news} n WHERE n.nid = '%d'", $nid));
    // Наш ответ клиенту
    drupal_json(array('status' => 1, 'data' => $result));
}
?>

Файл loadnews.js: Drupal.behaviors.loadnews = function(context) { // Добавляем для всех ссылок в блоке новостей class =loadnews $('#block-views-news-block_news', context).find('a').addClass('loadnews') // Реагируем на клик .bind('click', function() { // Передаем с методом get адрес ссылки var href = $(this).attr('href'); // Переменная, это куда мы будем выводить ответ var target = $(this).parents(".field-content"); // Прячем ссылку $(this).hide(); // Вместо нее выводим анимацию $(target).append("<div class=loading></div>"); // Получаем данные с сервера $.get(Drupal.settings.basePath + 'loadnews', {url:href} , function(response) { // Сохраняем ответ в переменной var result = Drupal.parseJson(response); // Прячем анимацию $(target).find(".loading").hide(); // Вместо нее ставим "Свернуть" $(target).append("<span class=hidenews>Свернуть</span>"); $(target).append("<span class=shownews>Подробнее...</span>"); $(target).find(".shownews").hide(); // Создаем блок для вывода текста новости $(target).append("<div class='newstext'></div>"); // Изначально блок будет скрыт, чтобы потом красиво его развернуть $(target).find("div.newstext").hide(); // Загружаем текст из переменной в блок $(target).find("div.newstext").html(result.data); // Красиво раскрываем наш блок $(target).find("div.newstext").slideDown("fast").addClass("active"); // Реализация скрытия и раскрытия блока (нужно оптимизировать код) $(target).find(".hidenews").click(function() { $(target).find(".hidenews").hide(); $(target).find("div.newstext").slideUp("fast").removeClass("active"); $(target).find(".shownews").show(); }); $(target).find(".shownews").click(function() { $(target).find(".shownews").hide(); $(target).find("div.newstext").slideDown("fast").addClass("active"); $(target).find(".hidenews").show(); }); }); return false; }); }

Хотелось бы услышать мнения и замечания профи по коду. Спасибо за внимание.

Прикрепленный файл Размер loadnews_v6.x-1.6.zip 3.62 кб

Источник: http://www.drupal.ru/node/66172

Ajax: очередной перевод статьи

Даю полный перевод обучалки по использованию Ajax (на нее, кстати, ссылались здесь). Это дубль перевода с моего сайта, который я выложил более недели назад.
Следующее руководство шаг за шагом научит вас быстрому применению Аякса в Друпале. Мы динамически обновим страницу контентом, прочитанным с сервера, без необходимости обновлять страницу. Я постараюсь сделать это по возможности просто, описывая самые основные блоки, требуемые для внедрения Аякса. Я предлагаю вам двинуться дальше и попытаться вставить более сложные вещи, исходя из нужд вашего сайта.
Давайте начнем. Как-то я создал сайт электронной коммерции, основанный на Drupal 6 & Ubercart и теперь хочу улучшить его, применив для отображения товаров Аякс. Я хочу, чтобы пользователи выбрали категорию товаров из списка, и основываясь на этом выборе, получили список товаров для данной категории.
Замечание: я рекомендую, чтобы вы познакомились с разработкой модулей в Друпале (руководство можно найти здесь http://drupal.org/node/231276)

Шаг № 1 – Создание вашего «Модуля данных»

Для того чтобы получить данные от клиента, мы должны начать с создания модуля, который будет возвращать данные с сервера. Давайте назовем наш новый модуль “dynamic_products”. Прежде всего создади каталог для нашего нового модуля. Он должен находиться в каталоге “modules” вашего сайта (обычно /sites/default/modules). Все файлы, описанные далее в этом разделе, должны создаваться в этом каталоге. Затем создадим файл .info вашего модуля. Этот файл предоставляет информацию Друпала о вашем файле, которая нужна для его активации.
Больше информации о создании .info файла можно найти здесь http://drupal.org/node/231036
Для нашего .info файла мы будем использовать следующее:

  ; $Id$ name = "Dynamic Products" description = "Returns a list of products according to category." core = 6.x package = Example Ajax Modules

Копируем, вставляем  и сохраняем верхний код в “dynamic_products.info”. После того как мы создадим наш .info файл, мы продолжим далее создание нашего файла .module. Этот файл включает рабочий код со стороны сервера. Вернемся вверх и создадим файл “dynamic_products.info” в каталоге нашего модуля..
Для того чтобы создать вызов сервера и получить некоторые данные, нам нужен menu_hook, который будет использован для «перехвата» вызова аякса. В нем будет использоваться следующая функция:

function dynamic_products_menu() {   $items = array();   $items['products/get'] = array( 'title' => 'Dynamic Products', 'page callback' => 'dynamic_products_get_by_category_id', 'access arguments' => array('access dynamic_products content'), 'type' => MENU_CALLBACK );   return $items; }

Эта функция заставляет перехватывать все обращения по адресам “http://www.example.com/?q=products/get” или http//www.example.com/products/get и вызывать функцию обратного вызова dynamic_products_get_by_category_id.
Далее мы сообщим Друпалу, кто имеет разрешения на использование нашего модуля. Для этого мы применим Друпаловский hook_perm().

  function dynamic_products_perm() { return array('access dynamic_products content'); }

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

function dynamic_products_get_by_category_id($cat_id){ $items = ''; switch($cat_id){ case 12: $items = '<ul><li>Product 1</li><li>Product 2</li></ul>'; break; case 20: $items = '<ul><li>Product 3</li><li>Product 4</li></ul>'; break; } // создаем объект JSON. Он будет содержать свойство под названием “products”, которое является набором переменных $items. return drupal_json(array('products'=>$items)); exit; }

Наша функция обратного вызова принимает один параметр ($cat_id). В зависимости от его значения возвращаются разные списки товаров.
Функция может иметь столько параметров, сколько нам нужно. Для передачи их в функцию мы используем Url вызова Аякса
Как вы помните, ранее мы определили функцию menu_hook (dynamic_products_menu), и настроили наш модуль на перехват обращений, сделанных по адресу “http://www.example.com/products/get”. 
Для того чтобы добавить id категории к нашей функции обратного вызова, мы просто добавим его к url запроса.
Например, если мы хотим использовать значение 12 как id категории, мы просто используем следующий url http://www.example.com/products/get/12. 
Мы почти закончили делать наш файл dynamic_products.module. Позже мы вернемся к нему, а сейчас сохраним его и пойдем далее.

Шаг № 2 – Создание файла javascript

Теперь мы создадим файл javascript, который будет включать клиентскую часть, создающую вызов аякса. Создадим новый файл в каталоге модуля и назовем его dynamic_products.js. Представленный код задает обработку события нажатия кнопки одного из html-элементов на нашей странице.

// $Id$ Drupal.behaviors.dynamic_products = function (context) { $('a.categoryLink:not(.categoryLink-processed)', context).click(function () { // Эта функция будет выполняться после того, как ajax запрос на сервер был выполнен успешно var updateProducts = function(data) { // Параметр "data" является объектом JSON. Свойство “products” является списком товаров, который возвращается с сервера в ответ на запрос ajax. $('#divProducts').html(data.products); } $.ajax({ type: 'POST', url: this.href, // Which url should be handle the ajax request. This is the url defined in the <a> html tag success: updateProducts, // The js function that will be called upon success request dataType: 'json', //define the type of data that is going to get back from the server data: 'js=1' //Pass a key/value pair }); return false; // return false so the navigation stops here and not continue to the page in the link }).addClass('categoryLink-processed'); }

Копируем, вставляем  и сохраняем верхний код в “ файл dynamic_products.js ”. С ним мы работу закончили.

Шаг № 3 – загрузка файла javascript

Для того чтобы загрузить .js файл со стороны клиента, нам нужно вернуться и отредактировать наш файл .module. Для этого нам при инициализации модуля нужно использовать init_hook. Для того чтобы это сделать добавим следующие строки к файлу .module:

  function dynamic_products_theme() { return array( 'dynamic_products_javascript' => array( 'arguments' => array(), ), ); }   function dynamic_products_init() { theme('dynamic_products_javascript'); }   function theme_dynamic_products_javascript() { drupal_add_js(drupal_get_path('module', 'dynamic_products') . '/dynamic_products.js'); }

Сохраняем файл.
Замечание: не забудем активировать наш новый модуль на странице "admin/build/modules".

Шаг № 4 – Создание Html

Мы почти закончили. Нам нужно только создать на нашей странице код html, который будет делать вызов аякса. Чтобы упростить работу, давайте создадим 2 раздела div вверху страницы. Верхний div будет включать 2 ссылки, по одной для каждой категории товара. После щелчка на одной из этих ссылок будет отправляться запрос на сервер, а загруженный контент будет вставляться в нижний div.

  <div id=”topDiv”> <a class="categoryLink" href="/products/get/12">Cat. 1</a> <a class="categoryLink" href="/products/get/20">Cat. 2</a> </div> <div id="divProducts"></div>

Создайте страницу Друпала, скопируйте и вставьте верхний код, и это все. При просмотре страницы при щелчке на одной из ссылок категорий на сервер будет отправляться запрос, и на странице будет отображаться список товаров выбранной категории.

Источник: http://www.drupal.ru/node/63094

Потестим кнопочку? (Простой вариант интеграции elFinder в CKEditor)

UPD. Как выяснилось из комментариев, модуль ckeditor с версии 6.x-1.3 официально поддерживает elfinder. Таким образом, всё написанное относится к возможному способу вывода “быстрой” кнопки elfinder’a на тулбар.
UPD2(08/05/2011). Плагин доработан до автоматического определения типа файла, возвращаемого elFinder
Нужен был файлменеджер/мультизагрузчик для редактора CKeditor (именно для drupal-модуля).
Я обычно использую IMCE и стал искать дополнения к IMCE, поддерживающие мультизагрузку.
Нашёл только IMCE Swfupload, но он ещё в бета-стадии и требует установки дополнительных модулей. В общем, не устроил.
Зато как-то неожиданно открыл для себя elFinder.
Менеджер показался очень удобным (на мой взгляд, даже получше IMCE).
Мультизагрузка, drag&drop, создание-удаление директорий, файлов. Автоматические тамбы картинок, ну и в целом как-то юзабельнее выглядит.
CKEditor (по крайней мере 6.x-1.3) позволяет интегрировать IMCE как “быструю” кнопку на тулбар (отдельно от диалога выбора ссылки/картинки/файла). Просто нужно раскомментировать соответствующие определения в ckeditor.config.js и убедиться что присутствует папка imce в /modules/ckeditor/plugins
Я стырил это решение и наскоро адаптировал его под elFinder в виде скромного плагина-кнопки (elFinder).
Результат: на тулбаре имеется самодельная кнопочка, по клику на которой сразу открывается окно этого файлового менеджера (т.е. минуя диалог выбора адреса).

После выбора файла (двойной щелчок или команда меню и т.д.) в менеджере, он закрывается и ссылка возвращается в CKeditor в обвязке тегов.
В общем, почти всё как в “обычном” elFinder или IMCE.
Желающие могут пойти дальше и доработать решение плагина. Для примера сравните код приложенного плагина и стандартного плагина кнопки IMCE (функция setFile()): /modules/ckeditor/plugins/imce/plugin.js
Потребуются модули:
- модуль CKEditor
- модуль elFinder
- сам файлменеджер elfinder (он отдельно от модуля).
Плагин кнопки в архиве приложен к посту. Описание установки – в файле README.TXT архива.
После установки не забыть установить необходимые разрешения ролям для доступа к elFinder, CKEditor (если вы это ещё не сделали).
Отображение кнопки не зависит от разрешений.
То есть – если вы запретили какой-то роли использовать elFinder, то кнопка не исчезнет с панели. Просто по клику на ней будет обычный “У вас нет прав для просмотра и т.д.”.
ps. И это… Отписывайтесь, пожалуйста, у кого что получилось. Будут доработки – велкам + респект и уважуха

Прикрепленный файл Размер elfinder.zip 2.72 кб

Источник: http://www.drupal.ru/node/60796

Модуль, который позволяет обрезать фотографии и сохранять их на сервере

Недавно пришлось написать модуль, который обрезает изображения и автоматически сохраняет их на сервере. Назвал его image_cropper. Решил поделиться, может кому пригодится в хозяйстве. Скрипт изменения размеров взят отсюда (качать не надо, он уже запакован в модуле).
Перед употреблением прочитайте README.txt, там всего 2 строки.

Единственное что не удалось реализовать – это выбор контейнера, внутри которого будут обработаны все картинки, с помощью настроек внутри друпала, а не с помощью изменения js-файла. Если у кого-то есть идеи как это сделать – буду очень благодарен. Модуль в аттаче

Прикрепленный файл Размер image_cropper.rar 7.31 кб

Источник: http://www.drupal.ru/node/53252

Модуль, который позволяет обрезать фотографии и сохранять их на сервере

Недавно пришлось написать модуль, который обрезает изображения и автоматически сохраняет их на сервере. Назвал его image_cropper. Решил поделиться, может кому пригодится в хозяйстве. Скрипт изменения размеров взят отсюда (качать не надо, он уже запакован в модуле).
Перед употреблением прочитайте README.txt, там всего 2 строки.

Единственное что не удалось реализовать – это выбор контейнера, внутри которого будут обработаны все картинки, с помощью настроек внутри друпала, а не с помощью изменения js-файла. Если у кого-то есть идеи как это сделать – буду очень благодарен. Модуль в аттаче

Прикрепленный файл Размер image_cropper.rar 7.31 кб

Источник: http://drupal.ru/node/53252

Модуль ajaxmenu – подгрузка collapsed пунктов меню на лету

Позволяет подгружать скрытые (collapsed) пункты меню на лету.
Мне это помогло значить сократить размер изначальной загружаемой страницы (более тысячи пунктов меню, каталог стран/городов/отелей).

После установки нужно сбросить кеш.

Надеюсь кому-нибудь пригодится.

Пришлось использовать хак с подменой обработчика menu_item_link – через хук theme_registry_alter меняется на свой обработчик, а старый запоминается в параметр original_function. Обработчик в атрибуты ссылки дописывает id для ссылки содержащий mlid и передает вызов дальше в оригинальный обработчик. Кстате такой способ можно использовать для перехвата почти всех вызовов функций от theme (для шаблонов есть template_preprocess).

Потом яваскрипт вытаскивает mlid из id ссылки, и вешает обработчик наведения мышки с отсечкой (срабатывает если мышь более полусекунды задерживается на пункте меню), который делает аяксовый запрос детей для нужного пункта меню по mlid.

Прикрепленный файл Размер ajaxmenu.tgz 1.64 кб

Источник: http://www.drupal.ru/node/49219

AJAX popup

Цель: при клике на ссылку (заголовок ноды, картинка, дата или что нам в голову взбредет) открывается popup содержащий нужные нам поля ноды. Содержание грузиться динамически.

Условие: все через views.

Нам нужно:  Views Bonus Pack. Качаем, включаем.

Создаем views который будет “грузиться”.
Добавляем тип отображения feed, где Style == XLS file.
Указываем Path (например xls), и устанавливаем в аргументах Node: Nid.
Настриваем поля.

Создаем views который будет “грузить”.
Обязательное поле в нем Node: Nid, ставим его в самое начало и скрываем.
Теперь в поле с заголовком нужно указать Output this field as a link где Link path: == xls/[nid].
Теперь при клике на заголовок будет открываться нужный нам xls файл.

Осталось лишь одно – прикрутить к этому делу какой-нибудь lightbox. Я использую fancybox. Вот код для него:

$(".views-field-title a").click( function() { $.fancybox.showActivity(); $.ajax({ type : "POST", cache : false, url : this, data : $(this).serializeArray(), success: function(data) { var html = new Array(); var i = 0; $(data).find("td").each(function(){ html[i] = $(this).html(); i++; }); c = '<div class="views-field-field-img-fid">'+html[0]+'</div>'+ '<div class="views-field-title">'+html[1]+'</div>'+ '<div class="date-display-single">'+html[2]+'</div>'+ '<div class="">'+html[3]+'</div>' ; $.fancybox(c); } });   return false; });

Принимаю вопрос, предложения, благодарности.

Источник: http://www.drupal.ru/node/43468

© 2009 Обзор CMS