Come aggiungere un popup di conferma JS quando si fa clic su un pulsante #ajax


10

Ho un input del pulsante FAPI di base che è #ajax abilitato e funziona bene, ma voglio aggiungere un JS "Sei sicuro?" pop-up di conferma quando si fa clic sul pulsante prima che il codice venga effettivamente eseguito e non sono sicuro di come farlo perché JS di FAPI sembra stia mangiando il clic prima di poterlo ottenere, indipendentemente da ciò che faccio.

Ho provato ad aggiungere un gestore onclick inline, in questo modo:

$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
  ),
);

... che non aiuta, e ho anche provato ad aggiungere:

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

nel mio modulo JS che viene anche ignorato.

Altre idee? C'è un modo per aggiungere un gestore di invio in cima allo stack che Drupal #ajax riconoscerà?

Risposte:


15

Drupal è un framework PHP, ed è incredibile quanta fantasia AJAX puoi ottenere usando questo e la FAPI. Ma ha dei limiti e per un caso d'uso come questo, suggerirei di utilizzare JavaScript personalizzato. Inoltre, invece di utilizzare la normale finestra di dialogo JavaScript, è possibile utilizzare l'interfaccia utente jQuery per creare una finestra di dialogo tematica.

Comunque il problema che stai affrontando è probabilmente causato perché usi AJAX sul pulsante di invio. Dal momento che stai usando AJAX per l'effettiva chiamata di eliminazione, preventDefaulte simili non funzioneranno.

Quello che dovresti fare è qualcosa di simile. (Questo non è ampiamente testato ma dovrebbe funzionare.)

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

Ho aggiunto anche $ ('. Confirm'). Unbind ('mousedown'); Drupal ascolta anche l'evento 'mousedown'.
milkovsky

non rompere questo pulsante se l'utente annulla la finestra di dialogo di conferma e poi fa di nuovo clic? (perché $('.confirm').unbind('click');) ... o sto leggendo male? scusa non ho familiarità conunbind
ErichBSchulz,

1
@ErichBSchulz Unbind viene chiamato solo una volta, dal metodo attach che viene chiamato al caricamento della pagina.
googletorp

gist.github.com/guoxiangke/0dffa7722a67f052c7ce Errore di tipo non rilevato : impossibile leggere la proprietà "clic" di non definito ?????? Ho un modulo, nel nodo / add / content-type, e lo
accetto

4

confermando che Jeroen sta riparando il codice del googletorp.

Tuttavia, io stesso ho scoperto che i pari di tipo "mousedown" devono essere non accoppiati e vincolati di nuovo. Quindi il pezzo di codice che ha funzionato per me è il seguente:

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

È davvero uno spreco di risorse per clonare oggetti DOM a meno che tu non ne abbia realmente bisogno.
googletorp

Ciao, ho incontrato la stessa domanda, tutto va bene, ma ho riscontrato un errore js: "Uncaught TypeError: Impossibile leggere la proprietà 'clic' di undefined" anche per "mousedown".
bluesky_still

Questa è l'unica soluzione che ho potuto mettere al lavoro. La clonazione è la chiave qui. Senza il clone, quando si fa clic su OK, l'avviso ricompare all'istante.
Felix Eve,

4

La domanda è vecchia, ma mi interessava anche me. Secondo me, il modo più semplice è usare l'evento click nella tua definizione Ajax, perché Drupal usa l'evento mousedown come predefinito:

$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',
  ),
);

Quindi devi solo aggiungere un .mousedown()evento al tuo pulsante nel tuo file Javascript, perché viene generato prima dell'evento click:

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

Se desideri ancora che la tua richiesta Ajax venga chiamata con l'evento mousedown, puoi utilizzare un evento personalizzato:

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

Quindi puoi attivare questo evento nel .mousedown()caso del tuo file Javascript:

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

Entrambe le versioni funzionano!


Si! Mi piace questo perché fa quello che vuoi: ti dà una mano sul processo standard di Drupal che puoi quindi chiamare quando ne hai bisogno. Nb. Avevo bisogno di avere un preventDefaultgestore nel mio clic per impedire l'invio normale (non js) del modulo, comunque.
artfulrobot,

0

Hai provato a eseguire il tuo JS all'interno di un comportamento Drupal? Potrebbe essere che il tuo gestore di clic sia collegato dopo quello di Drupal.

Ad ogni modo, dovresti essere in grado di separare il gestore di clic di Drupal sul pulsante in modo da essere chiamato per primo e puoi chiamare il gestore di clic Ajax di Drupal manualmente (e in modo condizionale).


0

Rispondere a notare che il codice di googletorp non è corretto al 100%.

È necessario modificare la riga in cui sono memorizzati gli eventi:

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

In questo modo si eliminano eventuali problemi di riferimento agli oggetti, quindi quando si annullano gli eventi click, non si scioglie anche nel var;)

Inoltre, tieni presente che da jQuery 1.8 il metodo .data () è stato deprecato. La raccolta dei dati degli eventi viene ora eseguita tramite una struttura di dati interna:

.data ("eventi") : jQuery memorizza i suoi dati relativi agli eventi in un oggetto dati denominato (wait) eventi su ciascun elemento. Questa è una struttura di dati interna, quindi in 1.8 verrà rimossa dallo spazio del nome dei dati dell'utente in modo che non sia in conflitto con elementi con lo stesso nome. È ancora possibile accedere ai dati degli eventi di jQuery tramite jQuery._data (elemento, "eventi"), ma tenere presente che si tratta di una struttura di dati interna non documentata e che non deve essere modificata.

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


0

Ho trovato molte risposte utili sopra e sono riuscito a far funzionare il mio modulo. Mettendo tutto insieme, questo è ciò che ha funzionato per la mia applicazione: un pulsante del modulo di eliminazione con una finestra di dialogo di conferma e callback AJAX per modificare il contenuto di un elenco selezionato.

Il 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>
  ',
);

L'elemento modulo (seleziona elenco) da modificare:

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

Il tasto:

$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',
    ),

);

E infine, il callback AJAX:

function ajax_delete_callback ($form, $form_state) {

  // callback implementation code

  return $form['my_form']['select_list'];
}

-1

Ho risolto questo problema modificando il file drupal misc / ajax.jx.

Creare una copia del file ajax.js e inserirlo in qualsiasi modulo personalizzato e modificare la Drupal.ajax = function (base, element, element_settings) { funzione in precedenza

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);   
     }    
},

Funziona bene per me.


1
Conta come core di hacking e probabilmente dovrebbe essere evitato.
Mołot,

1
Ed è completamente inutile - en.wikipedia.org/wiki/Monkey_patch
Clive

Questo è stato l'unico modo per far funzionare questo concetto senza mostrare doppie caselle di conferma. L'unica eccezione è che dovevo verificare se if ajax.url == 'field_collection_remove_js'. Forse è a causa della versione di Drupal che sto usando?
Richard,

-1

Forse un po 'vecchio, ma mi chiedo perché non possiamo semplicemente usare:

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

Perché Drupal si lega all'evento mousedown in modo che il gestore dell'evento click non si attivi mai.
Felix Eve,

Drupal non sta cambiando il modo in cui PHP o JS funzionano. Perché NON dovrebbe ascoltare l'evento click? Qui Drupal è appena usato per allegare il codice JS. Una volta caricato il sito Drupal ha fatto il suo lavoro. Gli ascoltatori di JS sono tutti lì, giusto? ;)
schlicki il

Fai una buona domanda e ad essere sincero, non so perché l'evento click non si attivi. Tuttavia, dopo test approfonditi, posso confermare che non funziona. Probabilmente avrai bisogno di leggere ajax.js di Drupal per capire meglio.
Felix Eve,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.