Bagaimana cara menambahkan popup konfirmasi JS saat mengklik tombol #ajax

10

Saya memiliki input tombol FAPI dasar yang diaktifkan #ajax dan itu berfungsi dengan baik, tetapi saya ingin menambahkan JS "Apakah Anda yakin?" konfirmasi popup ketika mengklik tombol sebelum kode benar-benar berjalan, dan saya tidak yakin bagaimana melakukan itu karena FAPI's JS tampaknya memakan klik sebelum saya dapat melakukannya tidak peduli apa yang saya lakukan.

Saya sudah mencoba menambahkan inclick handler inline, seperti:

$form['search_filters']['channels']['channel_delete_' . $channel->nid] = array(
  '#type' => 'button',
  '#name' => 'channel_delete_' . $channel->nid,
  '#value' => 'Delete',
  '#attributes' => array(
    'class' => array('confirm'),
    'onclick' => "return confirm('Are you sure you want to delete that?')"
  ),
  '#button_type' => 'no-submit',
  '#ajax' => array(
    'callback' => 'delete_channel_callback',
    'wrapper' => 'channel_container_' . $channel->nid
  ),
);

... yang tidak membantu, dan saya juga mencoba menambahkan:

$('.confirm').click(function(e) {
  e.preventDefault();
  alert('Is this recognized')? // never runs
});

di JS modul saya yang juga diabaikan.

Ada ide lain? Apakah ada cara untuk menambahkan submit handler ke bagian atas stack yang akan dikenali Drupal #ajax?

Mike Crittenden
sumber

Jawaban:

15

Drupal adalah kerangka kerja PHP, dan menakjubkan betapa banyak hal-hal mewah AJAX yang bisa Anda peroleh dengan menggunakan FAPI. Tetapi memiliki batas dan untuk kasus penggunaan seperti ini, saya sarankan Anda menggunakan JavaScript khusus. Juga, alih-alih menggunakan dialog JavaScript yang biasanya, Anda bisa menggunakan jQuery UI untuk membuat dialog bertema.

Bagaimanapun masalah yang Anda hadapi mungkin disebabkan karena Anda menggunakan AJAX pada tombol kirim. Karena Anda menggunakan AJAX untuk panggilan penghapusan aktual, preventDefaultdan sejenisnya tidak akan berfungsi.

Yang harus Anda lakukan adalah sesuatu seperti ini. (Ini tidak diuji secara luas tetapi harus berhasil.)

Drupal.behaviors.module = {
  attach: function() {

    var events = $('.confirm').data('events'); // Get the jQuery events.
    $('.confirm').unbind('click'); // Remove the click events.
    $('.confirm').click(function () {
      if (confirm('Are you sure you want to delete that?')) {
        $.each(events.click, function() {
          this.handler(); // Invoke the click handlers that was removed.
        });
      }
      // Prevent default action.
      return false;
    });
  }
}
googletorp
sumber
Saya juga menambahkan $ ('. Konfirmasi'). Unbind ('mousedown'); Acara 'mousedown' Drupal listerns juga.
milkovsky
tidak akan hancurkan tombol ini jika pengguna membatalkan dialog konfirmasi lalu mengklik lagi? (karena $('.confirm').unbind('click');) ... atau saya salah baca? maaf tidak familier denganunbind
ErichBSchulz
1
@ErichBSchulz Unbind hanya dipanggil sekali, dengan metode melampirkan yang dipanggil saat memuat halaman.
googletorp
gist.github.com/guoxiangke/0dffa7722a67f052c7ce Type Tidak TertangkapError: Tidak dapat membaca properti 'klik' dari undefined ?????? Saya memiliki formulir, di node / add / tipe konten, dan saya ajax, gunakan js validate
bluesky_still
4

mengkonfirmasikan bahwa Jeroen sedang memperbaiki kode googletorp.

Namun, saya sendiri menemukan bahwa jenis "mousedown" harus dilepas dan diikat kembali. Jadi bagian dari kode yang bekerja untuk saya adalah sebagai berikut:

(function ($) {
  Drupal.behaviors.confirm = {
    attach: function(context, settings) {
      var events =  $('.form-submit-delete').clone(true).data('events');// Get the jQuery events.
      $('.form-submit-delete').unbind('mousedown'); // Remove the click events.
      $('.form-submit-delete').mousedown(function () {
    if (confirm('Are you sure you want to delete that?')) {
      $.each(events.mousedown, function() {
        this.handler(); // Invoke the mousedown handlers that was removed.
      });
    }
    // Prevent default action.
    return false;
      });
    }
  }
})(jQuery);
Turtletrail
sumber
Benar-benar pemborosan sumber daya untuk mengkloning objek DOM kecuali Anda benar-benar membutuhkannya.
googletorp
Hai, saya bertemu dengan pertanyaan yang sama, semua berjalan dengan baik, tetapi saya menemukan kesalahan js: "UnEught TypeError: Tidak dapat membaca properti 'klik' yang tidak terdefinisi" juga untuk "mousedown".
bluesky_still
Ini adalah satu-satunya solusi yang bisa saya peroleh untuk bekerja. Kloning adalah kunci di sini. Tanpa klon maka ketika Anda mengklik ok peringatan itu langsung muncul kembali.
Felix Eve
4

Pertanyaannya sudah lama, tetapi saya juga tertarik. Menurut pendapat saya, cara termudah adalah menggunakan acara klik dalam definisi Ajax Anda, karena Drupal menggunakan acara mousedown sebagai default:

$form['submit'] = array(
  '#type' => 'submit',
  '#value' => t('some value'),
  '#attributes' => array(
    'class' => array('some-class'),
    ),
  '#ajax' => array(
    'event' => 'click',    //add this line!
    'callback' => 'some_callback',
    'wrapper' => 'some-wrapper',
  ),
);

Maka Anda hanya perlu menambahkan .mousedown()acara ke tombol Anda di file Javascript Anda, karena itu dipecat sebelum acara klik:

$('.some-class').mousedown(function() {
  //do something
});

Jika Anda masih ingin Permintaan Ajax Anda dipanggil dengan acara mousedown, Anda dapat menggunakan acara khusus:

//change this line in the Ajax Defintion of your button
'event' => 'click',
//to
'event' => 'custom_event',

Kemudian Anda dapat memicu acara ini jika ada .mousedown()file Javascript Anda:

$('.some-class').mousedown(function() {
  //do something
  $('.some-class').trigger('custom_event');
});

Kedua versi berfungsi!

Daniel
sumber
Ya! Saya suka yang ini karena ia melakukan apa yang Anda inginkan: memberi Anda pegangan pada proses Drupal di luar rak yang bisa Anda hubungi ketika Anda membutuhkannya. Nb. Saya perlu memiliki preventDefaultdi handler klik saya untuk mencegah pengiriman normal (non-js) formulir, masih.
artfulrobot
0

Sudahkah Anda mencoba menjalankan JS dalam perilaku Drupal? Bisa jadi handler klik Anda dilampirkan setelah Drupal.

Bagaimanapun, Anda harus dapat melepaskan ikatan handler klik Drupal pada tombol sehingga Anda dipanggil terlebih dahulu dan Anda dapat memanggil Ajax klik handler Drupal secara manual (dan kondisional).

Adam DiCarlo
sumber
0

Menjawab untuk mencatat bahwa kode googletorp tidak 100% benar.

Anda perlu mengubah baris tempat acara disimpan untuk ini:

var events = $('.confirm').clone(true).data('events'); // Get the jQuery events.

Dengan cara ini Anda menghilangkan masalah referensi objek, jadi ketika melepas ikatan peristiwa klik, itu tidak mengikat di var Anda juga;)

Perlu diketahui juga bahwa sejak jQuery 1.8, metode .data () telah usang. Mendapatkan data acara sekarang dilakukan melalui struktur data internal:

.data ("events") : jQuery menyimpan data terkait acara dalam objek data yang bernama (tunggu) peristiwa pada setiap elemen. Ini adalah struktur data internal sehingga pada 1.8 ini akan dihapus dari ruang nama data pengguna sehingga tidak akan bertentangan dengan item dengan nama yang sama. Data acara jQuery masih dapat diakses melalui jQuery._data (elemen, "events") tetapi perlu diketahui bahwa ini adalah struktur data internal yang tidak terdokumentasi dan tidak boleh dimodifikasi.

Sumber: http://blog.jquery.com/2011/11/08/building-a-slimmer-jquery/

Jeroen
sumber
0

Saya menemukan banyak jawaban yang berguna di atas dan bisa membuat formulir saya berfungsi. Menyatukan semuanya, inilah yang berfungsi untuk aplikasi saya: Tombol hapus formulir dengan dialog konfirmasi dan panggilan balik AJAX untuk mengubah konten daftar terpilih.

Javascript:

$form['my_form']['delete_button_js'] = array(
  '#markup' => '<script type="text/javascript">
  (function ($) {
     // override the default confirmation dialog behavior
     Drupal.behaviors.confirm = { 

      // Get the jQuery events.
      attach: function(context, settings) {
      var events =  $(\'.deleteButtonClass\').clone(true).data(\'events\'); 

      $(\'.deleteButtonClass\').unbind(\'mousedown\'); // Remove the mousedown event.

      $(\'.deleteButtonClass\').mousedown(function () { 
           // Popup the confirmation
           if (confirm(\'Are you sure you want to delete the Group?\')) {
             // if YES, then we fire the AJAX event 
             $(\'.deleteButtonClass\').trigger(\'deleteGroupEvent\'); 
           }
           // Override the default action.
           return false;
        });
    }
            }
  })(jQuery);
  </script>
  ',
);

Elemen formulir (daftar pilih) yang akan diubah:

$form['my_form']['select_list'] = array(
         '#type' => 'select',
         '#title' => t('My Title'),
         '#options' =>  $optionsArray,
         '#size' => 5,
         '#prefix' => t('<div id="mySelectList">'),
         '#suffix' => t('</div>'),
    }

Tombol:

$form['my_form']['delete_button'] = array(
  '#type' => 'button',
  '#value' => 'Delete',

  '#attributes' => array( 
      'class' => array('deleteButtonClass'), 
    ),

  '#ajax' => array (

    // this is the custom event that will be fired from the jQuery function
    'event' => 'deleteGroupEvent', 

    'callback' => 'ajax_delete_callback',
    'wrapper' => 'mySelectList',
    ),

);

Dan akhirnya, callback AJAX:

function ajax_delete_callback ($form, $form_state) {

  // callback implementation code

  return $form['my_form']['select_list'];
}
Susanne
sumber
-1

Saya telah memperbaikinya dengan memodifikasi file drupal misc / ajax.jx.

Buat salinan file ajax.js dan letakkan di modul khusus apa saja dan modifikasi Drupal.ajax = function (base, element, element_settings) { fungsinya sebelum Kirim:

beforeSend: function (xmlhttprequest, options) {

    if( ajax.url =='/?q=field_collection/ajax'){ // condition for when click on the Remove button
      if (confirm('Are you sure you want to remove this?')) {
       ajax.ajaxing = true;
       return ajax.beforeSend(xmlhttprequest, options);
      }
      xmlhttprequest.abort();
    } else{
        ajax.ajaxing = true;
        return ajax.beforeSend(`xmlhttprequest`, options);   
     }    
},

Ini bekerja dengan baik untuk saya.

Hemant
sumber
1
Itu dianggap sebagai inti peretasan, dan mungkin harus dihindari.
Mołot
1
Dan sama sekali tidak perlu - en.wikipedia.org/wiki/Monkey_patch
Clive
Ini adalah satu-satunya cara saya bisa membuat konsep ini bekerja tanpa menampilkan kotak konfirmasi ganda. Satu-satunya pengecualian adalah saya harus membuat pernyataan if memeriksa apakah ajax.url == 'field_collection_remove_js'. Mungkin itu karena versi Drupal yang saya gunakan?
Richard
-1

Mungkin agak tua, tapi saya bertanya-tanya mengapa kita tidak bisa menggunakan:

(function($, Drupal, window, document, undefined) {

Drupal.behaviors.oc_ua_pc = {
  attach: function(context, settings) {
    $('#button').click(function () {
      if(confirm('This action cannot be undone and you cannot change the form later. Do you want to submit?')) {
        return;
      }

      return false;
    });
  }
}
})(jQuery, Drupal, this, this.document);
schlicki
sumber
Karena Drupal mengikat acara mousedown sehingga pengendali acara klik Anda tidak akan pernah aktif.
Felix Eve
Drupal tidak mengubah cara kerja PHP atau JS .. Mengapa TIDAK mendengarkan acara klik? Di sini Drupal hanya digunakan untuk melampirkan kode JS. Setelah situs dimuat, Drupal telah melakukan tugasnya. Semua pendengar JS ada di sana, kan? ;)
schlicki
Anda mengajukan pertanyaan yang bagus dan sejujurnya saya tidak tahu mengapa acara klik tidak berhasil. Namun setelah pengujian ekstensif saya dapat mengonfirmasi bahwa itu tidak. Mungkin perlu membaca ajax.js Drupal untuk mendapatkan pemahaman yang lebih baik.
Felix Eve