Cara memicu Drupal.attachBehaviors setelah Ajax berhasil

10

Saya memiliki modul yang memperbarui simpul melalui ajax ketika tautan diklik.

Tautannya adalah toggle, itu harus memperbarui node dengan nilai 1 pada klik pertama, kemudian dengan nilai 0 pada klik berikutnya, dll. Seperti menghidupkan / mematikan sesuatu.

Kode di bawah ini berfungsi pada klik pertama setelah memuat halaman, tetapi tidak pada klik berikutnya. Saya percaya Drupal.attachBehaviors harus dipanggil / dipicu setelah setiap klik, tapi saya tidak tahu bagaimana melakukan ini.

  1. Modul

    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. Apa yang saya coba sejauh ini:

(a) Tambahkan ajax_command_invoke(NULL, 'mymodule');ke array $ ajax_commands ditambah dengan $.fn.mymodulefungsi

(B) Tambahkan $('body').ajaxSuccess(Drupal.attachBehaviors);ke javascript saya. ajaxComplete mencoba juga. Mencobanya di dokumen juga.

(c) Buat perintah khusus seperti yang dijelaskan di sini http://www.jaypan.com/tutorial/calling-function-after-ajax-event-drupal-7

Catatan: Saya tahu itu hanya masalah memicu attachBehaviors setelah setiap klik untuk 'ajaxify' html baru dimasukkan / dimodifikasi. Jika saya mengklik tautan dan kemudian mengetik Drupal.attachBehaviors () di konsol, tautan tersebut akan diproses lagi oleh javascript saya, sebagaimana dibuktikan dengan penambahan kelas 'middone', dan dapat diklik lagi.

Catatan: Juga menarik, jika saya meninggalkan yang $ajax_commandskosong dan mengembalikannya (array kosong) di akhir fungsi panggilan balik, tautan akan tetap dapat diklik pada klik pertama dan selanjutnya. Ini akan memiliki fungsionalitas yang saya cari (beralih). Namun, karena tidak ada perubahan yang dilakukan pada html setelah setiap klik, tidak ada cara bagi pengguna untuk mengetahui apakah sakelar hidup atau mati.

Petunjuk apa pun akan sangat dihargai.

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

Jawaban sebagian:

Fungsi sukses Drupal ajax.js hanya melampirkan kembali perilaku untuk formulir (saya pikir?)

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

jadi saya memutuskan untuk meretas fungsi sukses semua objek ajax saya.

Javascript sekarang menjadi

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

Fungsi sukses adalah copy paste dari default dari ajax.js dengan baris tambahan untuk perilaku pemasangan kembali. Untuk beberapa alasan, Drupal.attachBehaviorsharus berada dalam timer. Saya tidak bisa memilikinya sendiri karena suatu alasan yang saya abaikan.

Saya akan membiarkan pertanyaan ini terbuka untuk beberapa orang kalau-kalau ada yang bisa menemukan solusi yang lebih elegan dan / atau menjelaskan keanehan timer.

Terimakasih banyak

JSL
sumber
Mengapa Anda ingin melampirkan perilaku berulang kali? mereka secara otomatis dijalankan kembali pada elemen baru yang dibuat menggunakan AJAX, jadi mengapa itu tidak cukup?
Mołot
perilaku tidak secara otomatis dipasang kembali dalam kasus saya. thx
JSL

Jawaban:

1

Mungkin sulit melampirkan perilaku ajax ke konten yang dikembalikan dari permintaan ajax itu sendiri. Namun, itu mungkin.

Meskipun snipet kode hook_menu Anda terlihat tidak lengkap, dengan asumsi itu benar (mengembalikan $ item dan fungsi ditutup) - Dalam kasus Anda, Anda mungkin hanya perlu menyesuaikan callback pengiriman ke 'ajax_deliver'

yaitu:

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

}
David Thomas
sumber
Terima kasih atas sarannya tetapi ini juga tidak berhasil. Saya menggunakan kode Anda di hook_menu dan perilaku tidak melampirkan kembali secara otomatis.
JSL
1

Setelah beberapa debug, saya menyadari bahwa masalahnya bukan pada kode saya.

Masalahnya terletak pada modul lain, dalam kasus saya modul colorbox, yang merupakan sumber kesalahan js dalam fungsi perilakunya sendiri. Saya percaya kesalahan itu menyebabkan proses perilaku attach berhenti, dan karena itu, fungsi perilaku saya sendiri tidak terpasang kembali. Kesalahan bisa dilihat di konsol.

Kesalahan colorbox: di 7.24

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

dan di 7.25

Uncaught TypeError: Cannot read property 'mobiledetect' of undefined

Solusi saya adalah menonaktifkan modul colorbox.

Terima kasih banyak untuk semua yang telah membantu.

JSL
sumber
1

Saya tidak bisa mengomentari jawaban pertama , tetapi Anda dapat mengatur properti untuk colorbox di pengaturan. Sebagai contoh:

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'
});
Ilya Krigouzov
sumber