Я сделал блог на эту тему JS with AJAX and PHP и наклеил его ниже.
JS с помощью AJAX и PHP
Drupal имеет расширенную поддержку JS и AJAX в рамках своих стандартных форм и есть учебники, которые объясняют, как это работает. Тем не менее, я не смог найти хороший учебник, чтобы объяснить, как Javascript может общаться с модулем Drupal специальным образом. Например, я хотел иметь возможность изменять любые произвольные html на основе информации о состоянии, доступной в PHP. Этот метод представлен ниже.
В верхней части этой страницы вы увидите вкладки, которые по умолчанию в этой теме довольно просты. Я хотел изменить их так, чтобы выбранная в данный момент вкладка выделялась больше. Конечно, это можно сделать только с помощью CSS, но я хотел разработать этот метод для случаев, когда одного CSS недостаточно.
Ниже приведен JS, который может быть добавлен непосредственно в файл JS, описанный ранее. Существует функция jQuery, которая работает с элементом с id 'main-menu-links' каждый раз, когда страница загружена и готова. Я получаю innerHTML и использую encodeURIComponent для преобразования его в безопасную строку, которая может быть передана как параметр URL. Я должен был сделать это, потому что одна из вкладок ссылается на URL-адрес, который передает параметр.
var xmlhttp;
var childnodes;
// Send post to specified url
function loadXMLDoc(url,cfunc)
{
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=cfunc;
// alert("loadXMLDoc: " + url);
xmlhttp.open("POST",url,true);
xmlhttp.send();
}
// AJAX redirect to camr_custom/getvisits with callback function to replace the href
// with something to disable the link for nodes that have not been visited.
function getMenuTabs(str)
{
loadXMLDoc("?q=flashum_status/get_menu_tabs&block="+str,function()
{
// alert("getMenuTabs status: " + xmlhttp.status + " readyState: " + xmlhttp.readyState);
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
// alert("getMenuTabs: " + xmlhttp.responseText);
data= jQuery.parseJSON('['+xmlhttp.responseText+']')
$.each(data,function(){
// alert(this['block']);
document.getElementById("main-menu-links").innerHTML = this['block'];
});
}
});
}
// Locate book navigation block and send innerHTML to PHP module
$('#main-menu-links').ready(function() {
lis = document.getElementById("main-menu-links").innerHTML;
// alert("main-menu-links: " + lis);
// safe encode this block so that it can contain arbitrary urls in the href links
lis = encodeURIComponent(lis);
getMenuTabs(lis);
});
Функция JQuery заканчивается вызовом loadXMLDoc который где пост AJAX происходит с указанием URL, который захваченное hook_menu в модуле Drupal. Он также использует функцию обратного вызова, которая передается в параметре cfunc. По возвращении ответ JSON обрабатывается, чтобы преобразовать его в HTML, и он сохраняется непосредственно в исходном innerHTML. Таким образом, независимо от того, что PHP-модуль сделал с HTML, вместо исходного HTML.
На стороне PHP есть первый элемент массива из hook_menu:
$items['flashum_status/get_menu_tabs'] = array(
'page callback' => 'get_menu_tabs',
'access arguments' => array('access flashum status'),
'type' => MENU_CALLBACK,
);
Функция обратного вызова затем показан ниже. Сначала он вытягивает параметр блока и загружает его в объект DOM, чтобы его можно было проанализировать. Объект simple_html_dom предоставляется модулем simplehtmldom, который вам нужно будет установить и включить. Не забудьте также установить соответствующую библиотеку. Это должно закончиться в /all/libraries/simplehtmldom/simple_html_dom.php.
function get_menu_tabs() {
// drupal_set_message(t("get_menu_tabs: @code", array('@code' => print_r(null, TRUE))));
if (array_key_exists ('block', $_GET)) {
$block = $_GET['block'];
// drupal_set_message(t("get_menu_tabs block: @code", array('@code' => print_r($block, TRUE))));
// Create a DOM object.
$html_obj = new simple_html_dom();
// Load HTML from a string.
$html_obj->load($block);
// remove href for nodes not yet visited
$index = 0;
foreach ($html_obj->find('li') as $li) {
$start = strpos($li->innertext, 'href');
$end = strpos($li->innertext, '>', $start);
$start_html = substr($li->innertext, 0, $end);
$end_html = substr($li->innertext, $end);
if (strpos($li->innertext, 'active')) {
$li->innertext = $start_html.' style="color:red;border: solid red;margin-left:5px;margin-right:5px;"'.$end_html;
// drupal_set_message(t("get_menu_tabs html_obj: @code", array('@code' => print_r($li->innertext, TRUE))));
}
else
$li->innertext = $start_html.' style="color:black;border: solid #777;"'.$end_html;
$index++;
}
$str = $html_obj->save();
// drupal_set_message(t("get_menu_tabs str: @code", array('@code' => print_r($str, TRUE))));
// Release resources to avoid memory leak in some versions.
$html_obj->clear();
unset($html_obj);
return drupal_json_output(array('block'=>$str));
}
}
Наконец, он перебирает элементы Li добавив стиль CSS рядного, что меняется в зависимости от того, активна или нет вкладки. Затем он просто создает строку из объекта DOM и возвращает ее через drupal_json_output, которая преобразует его в формат JSON. Это, конечно, получено в функции обратного вызова JS.