AJAX と PHPを使用したこのテーマの JS に関するブログを作成し、以下に貼り付けました。
JS と AJAX および PHP
Drupal は、標準フォームの一部として JS と AJAX を幅広くサポートしており、これがどのように機能するかを説明するチュートリアルがあります。ただし、Javascript が Drupal モジュールとアドホックに通信する方法を説明する適切なチュートリアルを見つけることができませんでした。たとえば、PHP で利用可能な状態情報に基づいて、任意の html を変更できるようにしたいと考えました。このテクニックを以下に示します。
このページの上部には、このテーマのデフォルトでプレーンなタブが表示されます。現在選択されているタブがより目立つように変更したかったのです。もちろん、これは CSS だけでも可能ですが、CSS だけでは不十分な場合に備えて、この手法を開発したいと考えました。
以下は、前述の JS ファイルに直接追加できる JS です。ページが読み込まれて準備が整うたびに、id 'main-menu-links' を持つ要素で動作する jQuery 関数があります。innerHTML を取得し、encodeURIComponent を使用して、URL パラメーターとして渡すことができる安全な文字列に変換します。タブの 1 つがパラメーターを渡す 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 関数は、Drupal モジュールの hook_menu によってキャプチャされた URL を指定して、AJAX ポストが行われる loadXMLDoc を呼び出すことになります。また、パラメーター 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));
}
}
最後に、タブがアクティブかどうかによって変化するインライン CSS スタイルを追加する li アイテムをループします。次に、DOM オブジェクトから文字列を作成し、それを JSON 形式に変換する drupal_json_output を介して返します。もちろん、これは JS コールバック関数で受信されます。