Başarılı Ajax'tan sonra Drupal.attachBehaviors nasıl tetiklenir


10

Bir bağlantı tıklatıldığında ajax aracılığıyla bir düğümü güncelleştiren bir modül var.

Bağlantı bir geçiştir, düğümü ilk tıklamada 1 değeriyle, ardından sonraki tıklamada 0 değeriyle vb. Güncellemelidir. Bir şeyi açma / kapatma gibi.

Aşağıdaki kod, sayfa yüklendikten sonraki ilk tıklamada çalışır, ancak sonraki tıklamalarda çalışmaz. Drupal.attachBehaviors'ın her tıklamadan sonra çağrılması / tetiklenmesi gerektiğine inanıyorum, ancak bunu nasıl yapacağımı anlayamıyorum.

  1. Modül

    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. Şimdiye kadar denedim:

(a) ajax_command_invoke(NULL, 'mymodule');$ ajax_commands dizisine bir $.fn.mymoduleişlevle birleştirilmiş bir

(b) $('body').ajaxSuccess(Drupal.attachBehaviors);Javascriptime ekle . ajaxComplete de denedi. Belgede de denedim.

(c) Burada ayrıntılı olarak açıklandığı gibi özel bir komut oluşturun http://www.jaypan.com/tutorial/calling-function-after-ajax-event-drupal-7

Not: Her yeni tıklamanın eklenen / değiştirilen 'ajaxify' için her tıklamadan sonra attachBehaviors tetiklenmesi meselesi olduğunu biliyorum. Bağlantıyı tıklatır ve sonra konsolda Drupal.attachBehaviors () yazarsam, bağlantı 'middone' sınıfının eklenmesiyle kanıtlandığı gibi tekrar javascript tarafından işlenir ve tekrar tıklanabilir.

Not: Ayrıca, $ajax_commandsboş bırakıp geri arama işlevinin sonunda (boş dizi) döndürürsem, bağlantı ilk ve sonraki tıklamalarda tıklanabilir olarak kalır. Aradığım işlevselliğe sahip olacak (bir geçiş). Bununla birlikte, her tıklamadan sonra html'de herhangi bir değişiklik yapılmadığından, kullanıcının geçişin açık veya kapalı olduğunu bilmesinin bir yolu yoktur.

Herhangi bir işaretçi büyük mutluluk duyacağız.

================================================== =====

Kısmi Yanıt:

Drupal ajax.js başarı işlevi yalnızca formlar için davranışları yeniden ekler (sanırım?)

    if (this.form) {
      var settings = this.settings || Drupal.settings;
      Drupal.attachBehaviors(this.form, settings);
    }

bu yüzden tüm ajax nesnelerimin başarı işlevini hacklemeye karar verdim.

Javascript artık

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

Başarı işlevi, yeniden bağlama davranışları için eklenen bir satırla birlikte ajax.js'den varsayılan kopya kopyasıdır. Bazı nedenlerden dolayı, Drupal.attachBehaviorsbir zamanlayıcı içinde olmalıdır. Göz ardı ettiğim bir sebepten ötürü tek başına yapamam.

Birisi daha zarif bir çözüm bulabilir ve / veya zamanlayıcı tuhaflığını açıklayabilirse bu soruyu birkaç kişi için açık bırakacağım.

Çok teşekkürler


Neden davranışları tekrar tekrar eklemek istesin ki? AJAX kullanılarak oluşturulan herhangi bir yeni öğede otomatik olarak yeniden çalıştırılırlar, bu yüzden neden yeterli değil?
Mołot

Davranışlarım benim durumumda otomatik olarak yeniden oluşturulmuyor. thx
JSL

Yanıtlar:


1

Bir ajax isteğinin kendisinden döndürülen içeriğe ajax davranışları eklemek zor olabilir. Ancak mümkündür.

Hook_menu kod snippet'iniz eksik görünse de, doğru olduğu varsayılarak ($ ​​öğeleri döndürür ve işlev kapalıdır) - Durumunuzda, teslimat geri aramasını 'ajax_deliver' olarak ayarlamanız gerekebilir.

yani:

/**
 * 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;

}

Öneri için teşekkürler ama bu da çalışmıyor. Kodunuzu hook_menu içinde kullanıyorum ve davranışlar otomatik olarak yeniden eklenmiyor.
JSL

1

Bazı hata ayıklama sonra, sorun kodumla olmadığını fark ettim.

Sorun başka bir modül, benim durumumda kendi davranışları işlevinde bir js hatası kaynağı olan colorbox modülü, yalan söyledi. Hatanın ekleme davranışları sürecinin durmasına neden olduğuna inanıyorum ve bu nedenle kendi davranışlarımın işlevi yeniden eklenmedi. Hata, konsolda görülebilir.

Renk kutusu hatası: 7.24'te

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

ve 7.25

Uncaught TypeError: Cannot read property 'mobiledetect' of undefined

Benim çözümüm colorbox modülünü devre dışı bırakmaktı.

Yardım eden herkese çok teşekkürler.


1

İlk cevaba yorum yapamıyorum , ancak ayarlardan colorbox için özellik ayarlayabilirsiniz. Örneğin:

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'
});
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.