リンクをクリックしたときにajaxを介してノードを更新するモジュールがあります。
リンクはトグルです。最初のクリックでノードを値1で更新し、その後のクリックで値0でノードを更新する必要があります。
以下のコードは、ページの読み込み後の最初のクリックでは機能しますが、その後のクリックでは機能しません。クリックするたびにDrupal.attachBehaviorsを呼び出し/トリガーする必要があると思いますが、これを行う方法がわかりません。
モジュール
_function mymodule_menu() {
$items['mypath/%/%/ajax'] = array(
'title' => 'My title',
'page callback' => 'mymodule_ajax_callback',
'page arguments' => array(1,2),
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
...
}
function mymodule_ajax_callback($id, $status) {
//Validation[...]
//Node Update using $id as the nid and $status as the field value[...]
// Define a new array to hold our AJAX commands.
$ajax_commands = array();
// Create a new AJAX command that replaces the #div.
$replacedivid = '#status'.$id;
$replacestring = '<div id="status'.$id.'"><a data-url="'.base_path().'mypath/'.$id.'/'.$new_status.'/ajax" title="This item is marked as '.$status_text.'" id="statuslink'.$id.'" class="midui">'.$status_text.'</a></div>';
$ajax_commands[] = ajax_command_replace($replacedivid, $replacestring);
return drupal_json_output($ajax_commands);
}
_
JavaScript
_(function ($) {
Drupal.behaviors.mymodule = {
attach: function(context, settings) {
var $uilink = $('.midui'); //find all links
for (var i=0;i<$uilink.length;i++) { //Loop
var $link = $('#' + $uilink[i].id);
if (!$link.hasClass("middone")) {
new Drupal.ajax('#' + $uilink[i].id, $link, {
url: $link.attr('data-url'),
effect: 'fade',
settings: {},
progress: {
type: 'throbber'
},
event: 'click tap'
});
$link.addClass("middone"); //add class when we're done
}
}
}
}
})(jQuery);
_
これまでに試したこと:
(a)_$.fn.mymodule
_関数と組み合わせた$ ajax_commands配列にajax_command_invoke(NULL, 'mymodule');
を追加します
(b)$('body').ajaxSuccess(Drupal.attachBehaviors);
をJavaScriptに追加します。 ajaxCompleteも試しました。ドキュメントでも試してみました。
(c)ここで説明するようにカスタムコマンドを作成します http://www.jaypan.com/tutorial/calling-function-after-ajax-event-drupal-7
注:挿入または変更される新しいhtmlを「ajaxify」するためにクリックするたびにattachBehaviorsをトリガーするだけの問題であることはわかっています。リンクをクリックして、コンソールにDrupal.attachBehaviors()と入力すると、「middone」クラスが追加されたことからわかるように、リンクはJavaScriptによって再び処理され、再度クリックできるようになります。
注:また興味深いことに、コールバック関数の最後で_$ajax_commands
_を空のままにしてそれ(空の配列)を返すと、1回目以降のクリックでリンクがクリック可能なままになります。私が探している機能(トグル)があります。ただし、クリックするたびにhtmlは変更されないため、ユーザーがトグルがオンかオフかを知る方法はありません。
どんなポインタでも大歓迎です。
================================================== =====
部分的な答え:
Drupalのajax.js成功関数は、フォームの動作のみを再アタッチします(私はそう思いますか?)
_ if (this.form) {
var settings = this.settings || Drupal.settings;
Drupal.attachBehaviors(this.form, settings);
}
_
そこで、すべてのajaxオブジェクトの成功関数をハックすることにしました。
Javascriptは次のようになります
_ (function ($) {
Drupal.behaviors.mymodule = {
attach: function(context, settings) {
var $uilink = $('.midui'); //find all links
for (var i=0;i<$uilink.length;i++) { //Loop
var $link = $('#' + $uilink[i].id);
if (!$link.hasClass("middone")) {
myAjax = new Drupal.ajax('#' + $uilink[i].id, $link, {
url: $link.attr('data-url'),
effect: 'fade',
settings: {},
progress: {
type: 'throbber'
},
event: 'click tap'
});
myAjax.options.success = function (response, status) {
//Trigger Attach Behaviors
setTimeout(function(){Drupal.attachBehaviors($(myAjax.selector))}, 0);
// Sanity check for browser support (object expected).
// When using iFrame uploads, responses must be returned as a string.
if (typeof response == 'string') {
response = $.parseJSON(response);
}
return myAjax.success(response, status);
}
$link.addClass("middone"); //add class when we're done
}
}
}
}
})(jQuery);
_
成功関数は、動作を再接続するための行が追加されたajax.jsからのデフォルトのコピーペーストです。何らかの理由で、_Drupal.attachBehaviors
_はタイマー内にある必要があります。私が無視する理由のために、それだけでそれを手に入れることはできません。
誰かがよりエレガントな解決策を見つけたり、タイマーの奇妙さを説明したりできる場合に備えて、この質問はほとんど公開しません。
どうもありがとう
いくつかのデバッグの後、問題は自分のコードにあるのではないことに気付きました。
問題は別のモジュール(私の場合はcolorboxモジュール)にありました。これは、独自の動作関数のjsエラーの原因でした。エラーが原因で動作のアタッチプロセスが停止したため、自分の動作関数は再アタッチされませんでした。エラーはコンソールで確認できます。
カラーボックスエラー:7.24
Uncaught TypeError: Cannot read property 'transition' of undefined colorbox_inline.js?
そして7.25
Uncaught TypeError: Cannot read property 'mobiledetect' of undefined
私の解決策は、カラーボックスモジュールを無効にすることでした。
助けてくれたすべての人に感謝します。
コメントできません 最初の回答 ですが、設定でカラーボックスのプロパティを設定できます。例えば:
myAjax = new Drupal.ajax('#' + $uilink[i].id, $link, {
url: $link.attr('data-url'),
effect: 'fade',
settings: {
colorbox: {
mobiledetect: false
}
},
progress: {
type: 'throbber'
},
event: 'click tap'
});
Ajaxリクエスト自体から返されるコンテンツにajaxビヘイビアーをアタッチするのは難しい場合があります。ただし、可能です。
あなたのhook_menuコードスニペットは、それが正しいと仮定して不完全に見えますが($ itemsを返し、関数は閉じています)-あなたの場合、配信コールバックを「ajax_deliver」に調整する必要があるだけかもしれません
つまり:
/**
* Implements hook_menu
*/
function mymodule_menu() {
$items['mypath/%/%/ajax'] = array(
'title' => 'My title',
'page callback' => 'mymodule_ajax_callback',
'page arguments' => array(1,2),
'access arguments' => array('access content'),
'delivery callback' => 'ajax_deliver',
'theme callback' => 'ajax_base_page_theme',
'type' => MENU_CALLBACK,
);
return $items;
}