Най-интересната част от презентацията - въпросът как се прави менюто да е с ajax остана недообяснена поради липса на време. Надявам се тук да намерите отговорите на въпросите си по това.
Така, както подготвихме в предните постове различните компоненти - нашето меню с категории което сътветно си има целева страница в която да се зареждат резултатите, на практика е лесната част, която става без да се налага да пишем код. За ajax обаче трябва малко да се потрудим - най-малкото няма как да се мине без js.
Какво е необходимо?
- Скрипт (js), където да прихванем потребителското действие (click), да пратим на системата каква информация иска потребителя.
- Menu callback - който да получи "горното искане", да намери информацията по този критерий, да подготви резултата в подходящ за представяне формат и да го прати обратно на страницата.
За целта ще направим малък модул, който да добави тази нова функционалност. Обикновено собствени модули, които не са от http://drupal.org ги поставям в sites/all/modules/custom_modules. В тази директория създавам папка views_ext (разширения за/на views). В нея създавам файла views_ext.info с код:
name = Views extention description = Add ajax to views page dependencies[] = views package = Custom core = 7.x files[] = views_ext.module
Създавам файл views_ext.module с код:
<?php /** * Implements hook_init(). */ function views_ext_init() { drupal_add_js(drupal_get_path('module', 'views_ext') . '/views_ext.js', 'file'); } /** * Implements hook_menu(). */ function views_ext_menu() { $items['views_term/ajax'] = array( 'title' => 'Views ajax', 'page callback' => '_views_ajax', 'page arguments' => array(2), 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); return $items; } /** * Implements of hook_preprocess_HOOK(). */ function views_ext_preprocess_page(&$variables){ if($variables['page'] && arg(0) == 'views_term' && arg(1) == 'ajax') { $variables['theme_hook_suggestions'][] = 'views__ajax'; } } //views ajax function _views_ajax($arg) { $output = ''; $view_name = 'clone_of_taxonomy_term'; $display = 'page'; $output = views_embed_view($view_name, $display, $arg); return drupal_json_output(array('views_title' => $arg, 'views_content' => $output)); exit; }
и файл за js - views_ext.js с код в него:
(function ($) { Drupal.behaviors.views_ext = { attach: function(context, settings) { $('a.category').click(function() { $('a.category').removeClass('active'); $(this).addClass('active'); var args = $(this).attr('href').split('/'); var arg2 = args.slice(-1)[0]; var documents_load_url = Drupal.settings.basePath + 'views_term/ajax/' + arg2; var updateResults = function(data) { var obj = JSON.parse(data); $('h1#page-title.title').text(obj.views_title); $('#block-system-main .content').html(obj.views_content); $('#throbber').fadeOut(); } var showThrobber = function() { $('#throbber').fadeIn(); } $.ajax({ type: 'POST', url: documents_load_url, beforeSend: showThrobber, success: updateResults, dataType: 'html' }); return false; }); } }; })(jQuery);
Готовия модул с този код е прикачен в края на този пост. Инсталирайте по обичайния начин. Всичко е почти готово. Остана да направим темплейта, който ще връща информацията след клик.
Създаваме файл views--ajax.tpl.php в папката на текущата тема. В случай, че имаме много темплейти е добре да въведем някакава организация. Обикновено създавам в папката на темата папка templates и в нея допълнително съдавам папка views за темплейтите на views, папка nodes за темплейтите на различните типове нодове и т.н. Йерархията няма значение (тя е за лично удобство, а също и да се ориентира друг човек, когато преглежда нашият код и файлове) - достатъчно е самият темплейт файл да се намира в папката на текущата тема или в нейна под-папка.
Кода на views--ajax.tpl.php e
<?php print render($page['content']); ?>
Има го също като прикачен файл.
Просто, нали? :)
Някои обяснения по кода:
С този код казваме най-общо, че за тази страница ни трябва само съдържанието на централния регион най-общо - без заглавната част, без регионите, без футър.
Този темплейт се прилага когато се посети url като example.com/views_term/ajax/Term name
function views_ext_preprocess_page(&$variables){ if($variables['page'] && arg(0) == 'views_term' && arg(1) == 'ajax') { $variables['theme_hook_suggestions'][] = 'views__ajax'; } }
Какво точно да съдържа този $page['content'] се казва в
//views ajax function _views_ajax($arg) { $output = ''; $view_name = 'clone_of_taxonomy_term'; $display = 'page'; $output = views_embed_view($view_name, $display, $arg); return drupal_json_output(array('views_title' => $arg, 'views_content' => $output)); exit; }
Спомняте си, че клонирахме вю Taxonomy term и променихме контекстния му филтър да приема име на термин вместо id на термин. С
$output = views_embed_view($view_name, $display, $arg);
получаваме изхода на това вю с контекстен филтър Име на термин, получен от нашия menu_callback
/** * Implements hook_menu(). */ function views_ext_menu() { $items['views_term/ajax'] = array( 'title' => 'Views ajax', 'page callback' => '_views_ajax', 'page arguments' => array(2), 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); return $items; }
'page callback' => '_views_ajax',
указва каква функция ще се изпълни за този url
'page arguments' => array(2),
указва, че горната функция ще получи един аргумент (в този масив има един елемент), и този аргумент е третия аргумент от пътя (2 е третия, нали броим от 0 нула - при example.com/views_term/ajax/Term name аргумент 2 е Term name). Натам е лесно - views_embed_view($view_name, $display, $arg)
ще свърши останалото.
За троберчето css
#throbber { display: none; } .throbber { background: url('../images/ajax-loader-big.gif') center center no-repeat; border-radius: 5px; width: 60px; height: 60px; }
ajax-loader-big.gif е при прикачените файлове, или си направете собствен http://ajaxload.info/
За експерти:
Вероятно някой ще каже, че не е това съвсем правилният начин за имплементиране на подобна функционалност. Въпрос на гледна точка. Друг начин за реализиране на някои от горните неща има на http://api.drupal.org/api/drupal/modules%21system%21system.api.php/funct...
още в редакция