Як запустити Drupal.attachBehaviors після успішного Ajax


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. 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);
  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

Примітка. Я знаю, що це лише питання активації attachBehaviors після кожного клацання, щоб "пришвидшити" новий html, що вставляється / змінюється. Якщо я натискаю посилання, а потім на консолі введіть 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, так чому його недостатньо?
Молот

поведінка в моєму випадку не пересвоюється автоматично. thx
JSL

Відповіді:


1

Це може бути складним приєднання поведінки ajax до вмісту, який повертається з самого запиту ajax. Однак це можливо.

Хоча фрагмент коду куки_мену виглядає неповним, припускаючи, що він правильний (повертає $ елементи та функція закрита) - У вашому випадку вам може знадобитися просто налаштувати зворотний виклик доставки на '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;

}

Дякую за пропозицію, але це також не працює. Я використовую ваш код у moka_menu, і поведінка не повторно закріплюється автоматично.
JSL

1

Після деякої налагодження я зрозумів, що проблема не в моєму коді.

Проблема полягала в іншому модулі, в моєму випадку - кольоровому модулі, який був джерелом помилки js у власній функції поведінки. Я вважаю, що помилка призвела до припинення процесу поведінки приєднання, і, як такий, моя власна поведінкова функція не повторювалась. Помилку видно на консолі.

Помилка кольорової панелі: в 7.24

Uncaught TypeError: Cannot read property 'transition' of undefined colorbox_inline.js?

та в 7,25

Uncaught TypeError: Cannot read property 'mobiledetect' of undefined

Моє рішення полягало в тому, щоб відключити модуль colorbox.

Велике спасибі всім, хто допомагав.


1

Я не можу коментувати першу відповідь , але ви можете встановити властивість для кольорового поля в налаштуваннях. Наприклад:

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'
});
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.