web-dev-qa-db-fra.com

Comment ajouter une fenêtre de confirmation JS en cliquant sur un bouton #ajax

J'ai une entrée de bouton FAPI de base qui est activée #ajax et qui fonctionne bien, mais je veux ajouter un JS "Êtes-vous sûr?" une fenêtre de confirmation lorsque vous cliquez sur le bouton avant que le code ne s'exécute réellement, et je ne sais pas comment le faire, car le JS de FAPI semble manger le clic avant que je puisse y accéder, peu importe ce que je fais.

J'ai essayé d'ajouter un gestionnaire onclick en ligne, comme ceci:

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

... ce qui n'aide pas, et j'ai également essayé d'ajouter:

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

dans le JS de mon module qui est également ignoré.

D'autres idées? Existe-t-il un moyen d'ajouter un gestionnaire de soumission en haut de la pile que Drupal #ajax reconnaîtra?

10
Mike Crittenden

Drupal est un framework PHP, et c'est incroyable combien de fantaisie AJAX trucs que vous pouvez obtenir en utilisant cela et le FAPI. Mais il a ses limites et pour une utilisation Dans ce cas, je vous suggère d'utiliser du JavaScript personnalisé. De plus, au lieu d'utiliser la boîte de dialogue généralement JavaScript, vous pouvez utiliser l'interface jQuery pour créer une boîte de dialogue thématique à la place.

Quoi qu'il en soit, le problème auquel vous êtes confronté est probablement dû au fait que vous utilisez AJAX sur le bouton d'envoi. Puisque vous utilisez AJAX pour l'appel de suppression réel, preventDefault et autres ne fonctionneront pas.

Ce que vous auriez à faire est quelque chose comme ça. (Ceci n'est pas largement testé mais devrait fonctionner.)

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

La question est ancienne, mais je m'y intéressais aussi. À mon avis, le moyen le plus simple consiste à utiliser l'événement click dans votre définition Ajax, car Drupal utilise l'événement mousedown par défaut:

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

Ensuite, il vous suffit d'ajouter un événement .mousedown() à votre bouton dans votre fichier Javascript, car il est déclenché avant l'événement click:

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

Si vous souhaitez toujours que votre demande Ajax soit appelée avec l'événement mousedown, vous pouvez utiliser un événement personnalisé:

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

Ensuite, vous pouvez déclencher cet événement dans l'événement .mousedown() de votre fichier Javascript:

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

Les deux versions fonctionnent!

4
Daniel

confirmant que Jeroen corrige le code de googletorp.

Cependant, j'ai moi-même découvert que les égalités de type "mousedown" doivent être débidées et reliées à nouveau. Donc, le morceau de code qui a fonctionné pour moi est le suivant:

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

Avez-vous essayé d'exécuter votre JS à l'intérieur d'un comportement Drupal? Il se peut que votre gestionnaire de clics soit attaché après celui de Drupal.

Quoi qu'il en soit, vous devriez pouvoir dissocier le gestionnaire de clics de Drupal sur le bouton afin que vous soyez appelé en premier et vous pouvez appeler le gestionnaire de clics Ajax de Drupal manuellement (et conditionnellement).

0
Adam DiCarlo

Répondre à noter que le code de googletorp n'est pas correct à 100%.

Vous devez changer la ligne où les événements sont stockés en ceci:

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

De cette façon, vous éliminez tout problème de référence d'objet, donc lors de la dissociation des événements de clic, il ne se dissocie pas également dans votre var;)

Sachez également que depuis jQuery 1.8, la méthode .data () est obsolète. L'obtention des données d'événement se fait désormais via une structure de données interne:

. data ("events") : jQuery stocke ses données liées aux événements dans un objet de données nommé (wait for it) events sur chaque élément. Il s'agit d'une structure de données interne. Dans la version 1.8, elle sera supprimée de l'espace de nom des données utilisateur afin qu'elle n'entre pas en conflit avec les éléments du même nom. Les données d'événement de jQuery sont toujours accessibles via jQuery._data (élément, "events") mais sachez qu'il s'agit d'une structure de données interne non documentée et qui ne doit pas être modifiée.

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

0
Jeroen

J'ai trouvé de nombreuses réponses utiles ci-dessus et j'ai réussi à faire fonctionner mon formulaire. Ensemble, voici ce qui a fonctionné pour mon application: un bouton de suppression de formulaire avec une boîte de dialogue de confirmation et un rappel AJAX pour modifier le contenu d'une liste de sélection).

Le 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'élément de formulaire (liste de sélection) à modifier:

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

Le bouton:

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

);

Et enfin, le rappel AJAX:

function ajax_delete_callback ($form, $form_state) {

  // callback implementation code

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