成功Ajax之后如何触发Drupal.attachBehaviors


10

我有一个模块,当单击链接时,该模块通过ajax更新节点。

该链接是一个切换,它应在第一次单击时将节点更新为值1,然后在随后的单击中将节点更新为0,以此类推。就像打开/关闭某些内容一样。

下面的代码在页面加载后的第一次点击上有效,但在随后的点击上无效。我相信每次单击后都必须调用/触发Drupal.attachBehaviors,但是我不知道该怎么做。

  1. 模块

    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);
    }
  2. Java脚本

    (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);
  3. 到目前为止我尝试过的是:

(a)ajax_command_invoke(NULL, 'mymodule');在$ ajax_commands数组中加上一个$.fn.mymodule函数

(b)添加$('body').ajaxSuccess(Drupal.attachBehaviors);到我的javascript中。ajaxComplete也尝试过。在文件上也尝试过。

(c)创建一个自定义命令,如下所示:http://www.jaypan.com/tutorial/calling-function-after-ajax-event-drupal-7

注意:我知道这只是在每次单击以“ ajaxify”要插入/修改的新html之后触发attachBehaviors的问题。如果我单击该链接,然后在控制台中键入Drupal.attachBehaviors(),则该链接将由我的JavaScript再次处理,如添加的“ middone”类所证明,并且可以再次单击该链接。

注意:同样有趣的是,如果我将其保留为$ajax_commands空并在回调函数的末尾将其返回(空数组),则该链接将在第一次和随后的单击中保持可单击状态。它将具有我要寻找的功能(切换)。但是,由于每次单击后都不会对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必须在计时器内。我不能仅仅因为一个我会忽略的原因而拥有它。

如果有人可以找到一个更优雅的解决方案和/或解释计时器的奇怪之处,我将把这个问题留给少数人解决。

非常感谢


您为什么要一次又一次地附加行为?它们会在使用AJAX创建的任何新元素上自动重新运行,那为什么还不够?
Mołot

在我的情况下,行为不会自动重新触发。thx
JSL 2013年

Answers:


1

将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;

}

感谢您的建议,但这也不起作用。我在hook_menu中使用您的代码,并且行为不会自动重新附加。
JSL 2013年

1

经过一些调试后,我意识到问题不在我的代码中。

该问题与另一个模块(在我的情况下为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

我的解决方案是禁用颜色框模块。

非常感谢所有帮助的人。


1

我无法评论第一个答案,但是您可以在设置中为colorbox设置属性。例如:

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'
});
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.