Как добавить всплывающее окно подтверждения JS при нажатии кнопки #ajax

10

У меня есть базовый ввод с помощью кнопки FAPI, который #ajax включен, и он работает нормально, но я хочу добавить JS "Вы уверены?" всплывающее окно с подтверждением при нажатии кнопки до того, как код действительно запустится, и я не уверен, как это сделать, потому что JS FAPI, кажется, съедает щелчок до того, как я могу получить его независимо от того, что я делаю.

Я попытался добавить встроенный обработчик onclick, вот так:

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

... что не помогает, и я также попытался добавить:

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

в моем модуле JS, который также игнорируется.

Есть еще идеи? Есть ли способ добавить обработчик отправки в начало стека, который распознает Drupal #ajax?

Майк Криттенден
источник

Ответы:

15

Drupal - это PHP-фреймворк, и удивительно, сколько хороших AJAX-вещей вы можете получить, используя это и FAPI. Но у него есть свои ограничения, и для такого случая использования я бы предложил использовать пользовательский JavaScript. Кроме того, вместо обычного JavaScript-диалога, вы можете использовать jQuery UI для создания диалогового окна.

В любом случае проблема, с которой вы сталкиваетесь, вероятно, вызвана тем, что вы используете AJAX для кнопки отправки. Так как вы используете AJAX для фактического вызова удаления, preventDefaultи подобное не будет работать.

То, что вам нужно сделать, это что-то вроде этого. (Это не проверено широко, но должно работать.)

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
источник
Я также добавил $ ('. Подтвердите'). Unbind ('mousedown'); «Mousedown» Drupal listerns тоже.
Милковский
Разве это не сломает кнопку, если пользователь отменяет диалог подтверждения, а затем нажимает снова? (потому что $('.confirm').unbind('click');) ... или я читаю это неправильно? извините, не знаком сunbind
ErichBSchulz
1
@ErichBSchulz Unbind вызывается только один раз, методом attach, который вызывается при загрузке страницы.
googletorp
gist.github.com/guoxiangke/0dffa7722a67f052c7ce Uncaught TypeError : Невозможно прочитать свойство 'click' из неопределенного ?????? У меня есть форма, в node / add / content-type, и я ajax ее, использую js validate
bluesky_still
4

подтверждая, что Jeroen исправляет код googletorp.

Тем не менее, я сам обнаружил, что вечера типа "mousedown" должны быть снова распакованы и переплетены. Итак, фрагмент кода, который работал для меня, выглядит следующим образом:

(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
источник
Это действительно пустая трата ресурсов для клонирования объектов DOM, если они вам действительно не нужны.
googletorp
Привет, я встретил тот же вопрос, все идет хорошо, но я встретил ошибку js: «Uncaught TypeError: Невозможно прочитать свойство« click »из undefined» также для «mousedown».
bluesky_still
Это единственное решение, которое я мог получить на работу. Клонирование является ключевым здесь. Без клона, тогда, когда вы нажмете ОК, предупреждение просто мгновенно появляется.
Феликс Ева
4

Вопрос старый, но меня это тоже заинтересовало. На мой взгляд, самый простой способ - использовать событие click в вашем определении Ajax, потому что Drupal по умолчанию использует событие 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',
  ),
);

Затем вам просто нужно добавить .mousedown()событие к вашей кнопке в вашем файле Javascript, потому что оно запускается до события click:

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

Если вы все еще хотите, чтобы ваш Ajax Request вызывался с событием mousedown, вы можете использовать пользовательское событие:

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

Затем вы можете запустить это событие в .mousedown()случае вашего файла Javascript:

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

Обе версии работают!

Даниил
источник
Да! Мне нравится этот, потому что он делает то, что вы хотите: дает вам представление о готовом процессе Drupal, который вы затем можете вызывать, когда вам это нужно. В северном направлении Мне все еще нужно было иметь preventDefaultв своем обработчике кликов, чтобы предотвратить нормальную (не js) отправку формы.
artfulrobot
0

Вы пытались запустить JS внутри Drupal? Может случиться так, что ваш обработчик кликов подключается после Drupal.

В любом случае вы должны иметь возможность отсоединить обработчик кликов Drupal на кнопке, чтобы вы вызывались первыми, и вы можете вызывать обработчик кликов Ajax Drupal вручную (и условно).

Адам ДиКарло
источник
0

Отвечая на заметку, код googletorp не на 100% правильный.

Вам нужно изменить строку, где хранятся события, следующим образом:

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

Таким образом вы устраняете любые проблемы со ссылками на объекты, поэтому при отмене привязки событий click она также не отменяется в вашей переменной;)

Также имейте в виду, что начиная с версии jQuery 1.8 метод .data () устарел. Получение данных о событиях теперь осуществляется через внутреннюю структуру данных:

.data («events») : jQuery сохраняет свои связанные с событиями данные в объекте данных с именем (wait for it) events для каждого элемента. Это внутренняя структура данных, поэтому в 1.8 она будет удалена из пространства имен пользовательских данных, поэтому она не будет конфликтовать с элементами с одинаковыми именами. К данным события jQuery все еще можно получить доступ через jQuery._data (элемент, «события»), но имейте в виду, что это внутренняя структура данных, которая не документирована и не должна изменяться.

Источник: http://blog.jquery.com/2011/11/08/building-a-slimmer-jquery/

Йерун
источник
0

Я нашел много полезных ответов выше и смог заставить мою форму работать. Собрав все это вместе, это то, что сработало для моего приложения: кнопка удаления формы с диалоговым окном подтверждения и обратным вызовом AJAX для изменения содержимого списка выбора.

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

Элемент формы (выберите список), который нужно изменить:

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

Кнопка:

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

);

И, наконец, обратный вызов AJAX:

function ajax_delete_callback ($form, $form_state) {

  // callback implementation code

  return $form['my_form']['select_list'];
}
Susanne
источник
-1

Я исправил это, изменив файл drupal misc / ajax.jx.

Создайте копию файла ajax.js, поместите его в любой пользовательский модуль и Drupal.ajax = function (base, element, element_settings) { измените функцию в beforeSend:

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

Это работает нормально для меня.

Hemant
источник
1
Это считается ядром взлома, и, вероятно, его следует избегать.
Молот
1
И совершенно не нужно - en.wikipedia.org/wiki/Monkey_patch
Clive
Это был единственный способ заставить эту концепцию работать без двойного подтверждения. Единственным исключением является то, что я должен был проверить оператор if, если ajax.url == 'field_collection_remove_js'. Может быть, это из-за версии Drupal, которую я использую?
Ричард
-1

Может быть, немного стар, но мне интересно, почему мы не можем просто использовать:

(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
источник
Поскольку Drupal связывается с событием mousedown, ваш обработчик события click никогда не сработает.
Феликс Ева
Drupal не меняет способ работы PHP или JS. Почему бы ему НЕ прослушивать событие click? Здесь Drupal просто используется для прикрепления кода JS. Как только сайт загружен, Drupal сделал свою работу. Слушатели JS все там, верно? ;)
schlicki
Вы задаете хороший вопрос и, честно говоря, я не знаю, почему не происходит событие щелчка. Однако после обширного тестирования я могу подтвердить, что это не так. Вероятно, вам нужно прочитать ajax.js из Drupal, чтобы лучше понять.
Феликс Ева