Jak dodać wyskakujące okienko potwierdzenia JS po kliknięciu przycisku #ajax

10

Mam podstawowe wejście przycisku FAPI, które jest włączone #ajax i działa dobrze, ale chcę dodać JS „Jesteś pewien?” wyskakujące okienko z potwierdzeniem po kliknięciu przycisku przed faktycznym uruchomieniem kodu, i nie jestem pewien, jak to zrobić, ponieważ JS FAPI wydaje się jeść kliknięcie, zanim będę mógł do niego dotrzeć, bez względu na to, co zrobię.

Próbowałem dodać wbudowany moduł obsługi onclick, na przykład:

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

... co nie pomaga, a także próbowałem dodać:

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

w JS mojego modułu, który jest również ignorowany.

Jakieś inne pomysły? Czy istnieje sposób, aby dodać moduł obsługi przesyłania do górnej części stosu, który rozpozna Drupal #ajax?

Mike Crittenden
źródło

Odpowiedzi:

15

Drupal jest frameworkiem PHP i to niesamowite, ile fantazyjnych rzeczy AJAX można uzyskać za pomocą tego i interfejsu FAPI. Ma to jednak ograniczenia i w takim przypadku sugerowałbym użycie niestandardowego JavaScript. Ponadto zamiast używać zwykle okna dialogowego JavaScript, można użyć interfejsu użytkownika jQuery, aby zamiast tego utworzyć tematyczne okno dialogowe.

W każdym razie problem, który napotykasz, jest prawdopodobnie spowodowany, ponieważ używasz AJAX na przycisku przesyłania. Ponieważ używasz AJAX do rzeczywistego połączenia usuwania, preventDefaulti podobne nie będą działać.

Musisz zrobić coś takiego. (Nie jest to szeroko testowane, ale powinno działać.)

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
źródło
Dodałem także $ („.irm”). Unbind („mousedown”); Drupal listerns także wydarzenie „mousedown”.
Milkovsky,
czy to nie złamie przycisku, jeśli użytkownik anuluje okno dialogowe potwierdzenia, a następnie kliknie ponownie? (ponieważ $('.confirm').unbind('click');) ... czy źle to czytam? przepraszam, nie znamunbind
ErichBSchulz
1
@ErichBSchulz Unbind jest wywoływany tylko raz, metodą attach, która jest wywoływana podczas ładowania strony.
googletorp
gist.github.com/guoxiangke/0dffa7722a67f052c7ce Błąd typu Uncaught Type : Nie można odczytać właściwości „click” niezdefiniowanej ?????? Mam formularz, w węźle / add / content-type, i
odsyłam
4

potwierdzając, że Jeroen naprawia kod googletorp.

Jednak sam odkryłem, że znaki typu „mousedown” muszą zostać cofnięte i ponownie powiązane. Tak więc fragment kodu, który zadziałał dla mnie, jest następujący:

(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
źródło
Klonowanie obiektów DOM jest naprawdę marnotrawstwem zasobów, chyba że faktycznie ich potrzebujesz.
googletorp
Cześć, spotkałem się z tym samym pytaniem, wszystko idzie dobrze, ale spotkałem błąd js: „Uncaught TypeError: Nie można odczytać właściwości„ click ”niezdefiniowanej” również dla „mousedown”.
bluesky_still
To jedyne rozwiązanie, które mogłem dostać do pracy. Klonowanie jest tutaj kluczem. Bez klonowania, po kliknięciu OK, alert natychmiast się pojawia.
Felix Eve
4

Pytanie jest stare, ale interesowało mnie to. Moim zdaniem najłatwiejszym sposobem jest użycie zdarzenia click w definicji Ajax, ponieważ Drupal domyślnie używa zdarzenia mousedown:

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

Następnie wystarczy dodać .mousedown()zdarzenie do przycisku w pliku JavaScript, ponieważ jest on uruchamiany przed zdarzeniem kliknięcia:

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

Jeśli nadal chcesz, aby Twoje żądanie Ajax było wywoływane ze zdarzeniem mousedown, możesz użyć zdarzenia niestandardowego:

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

Następnie możesz wywołać to zdarzenie w .mousedown()przypadku pliku JavaScript:

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

Obie wersje działają!

Daniel
źródło
Tak! Podoba mi się ten, ponieważ robi to, co chcesz: daje ci kontrolę nad gotowym procesem Drupala, do którego możesz zadzwonić, kiedy go potrzebujesz. Uwaga Musiałem mieć preventDefaultw moim module obsługi kliknięć, aby nadal uniemożliwiać normalne (nie js) przesyłanie formularza.
artfulrobot
0

Czy próbowałeś uruchomić JS w zachowaniu Drupala? Może się tak zdarzyć, że Twój program do obsługi kliknięć jest dołączany za Drupalem.

Tak czy inaczej, powinieneś być w stanie usunąć powiązanie programu obsługi kliknięć Drupala na przycisku, abyś został wywołany jako pierwszy i możesz wywoływać procedurę obsługi kliknięć Drupala Ajax ręcznie (i warunkowo).

Adam DiCarlo
źródło
0

Odpowiadając, aby zauważyć, że kod googletorp nie jest w 100% poprawny.

Musisz zmienić linię, w której są przechowywane zdarzenia:

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

W ten sposób eliminujesz wszelkie problemy z odniesieniami do obiektu, więc gdy odłączysz zdarzenia kliknięcia, nie rozłączysz się również w twoim var;)

Należy również pamiętać, że od jQuery 1.8 metoda .data () jest przestarzała. Pobieranie danych zdarzeń odbywa się teraz za pomocą wewnętrznej struktury danych:

.data („zdarzenia”) : jQuery przechowuje dane związane ze zdarzeniem w obiekcie danych o nazwie (czekaj na to) zdarzenia w każdym elemencie. Jest to wewnętrzna struktura danych, więc w wersji 1.8 zostanie ona usunięta z przestrzeni nazw danych użytkownika, aby nie powodowała konfliktu z elementami o tej samej nazwie. Do danych zdarzeń jQuery można nadal uzyskać dostęp za pośrednictwem jQuery._data (element, „zdarzenia”), ale należy pamiętać, że jest to wewnętrzna struktura danych, która jest nieudokumentowana i nie powinna być modyfikowana.

Źródło: http://blog.jquery.com/2011/11/08/building-a-slimmer-jquery/

Jeroen
źródło
0

Znalazłem wiele przydatnych odpowiedzi powyżej i udało mi się uruchomić mój formularz. Podsumowując, działało to w mojej aplikacji: przycisk Usuń formularz z oknem dialogowym potwierdzenia i wywołaniem zwrotnym AJAX, aby zmodyfikować zawartość listy wyboru.

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

Element formularza (wybierz listę) do modyfikacji:

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

Przycisk:

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

);

I na koniec, wywołanie zwrotne AJAX:

function ajax_delete_callback ($form, $form_state) {

  // callback implementation code

  return $form['my_form']['select_list'];
}
Susanne
źródło
-1

Naprawiłem to, modyfikując plik drupal misc / ajax.jx.

Utwórz kopię pliku ajax.js i umieść go w dowolnym module niestandardowym i zmodyfikuj wcześniej Drupal.ajax = function (base, element, element_settings) { funkcję Wyślij:

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

Dla mnie działa dobrze.

Hemant
źródło
1
Liczy się jako rdzeń hakerski i prawdopodobnie należy go unikać.
Mołot
1
I jest całkowicie niepotrzebny - pl.wikipedia.org/wiki/Monkey_patch
Clive
To był jedyny sposób, w jaki mogłem uruchomić tę koncepcję bez pokazywania podwójnych pól potwierdzenia. Jedynym wyjątkiem jest to, że musiałem sprawdzić instrukcję if, jeśli ajax.url == 'field_collection_remove_js'. Może to z powodu wersji Drupala, której używam?
Richard
-1

Może trochę stary, ale zastanawiam się, dlaczego nie możemy po prostu użyć:

(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
źródło
Ponieważ Drupal wiąże zdarzenie mousedown, więc program obsługi zdarzenia kliknięcia nigdy się nie uruchomi.
Felix Eve
Drupal nie zmienia sposobu działania PHP lub JS. Dlaczego NIE miałoby nasłuchiwać zdarzenia kliknięcia? Tutaj Drupal służy tylko do dołączenia kodu JS. Po załadowaniu strony Drupal wykonał swoją pracę. Słuchacze JS już tam są, prawda? ;)
schlicki
Zadajesz dobre pytanie i szczerze mówiąc nie wiem, dlaczego zdarzenie kliknięcia się nie uruchamia. Jednak po szeroko zakrojonych testach mogę potwierdzić, że tak nie jest. Prawdopodobnie konieczne jest przeczytanie ajax.js Drupala, aby uzyskać lepsze zrozumienie.
Felix Eve