Як додати спливаюче вікно підтвердження 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 для створення діалогового діалогу.

У будь-якому випадку проблема, з якою ви стикаєтесь, ймовірно, викликана тим, що ви використовуєте 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;
    });
  }
}

Я також додав $ ('. Підтвердження'). Unbind ('mousedown'); Друпальські лістерні "походи" теж.
мілковський

не буде це перервати кнопку, якщо користувач скасує діалогове вікно підтвердження, а потім знову натисне? (тому що $('.confirm').unbind('click');) ... чи я читаю це неправильно? Вибачте, що не знайомийunbind
ErichBSchulz

1
@ErichBSchulz Unbind викликається лише один раз методом вкладення, який викликається при завантаженні сторінки.
googletorp

gist.github.com/guoxiangke/0dffa7722a67f052c7ce Uncaught TypeError: Неможливо прочитати властивість "click" невизначеного ?????? У мене форма, в node / add / content-type, і я її ajax використовую js validate
bluesky_still

4

підтверджуючи, що Джеройн фіксує код googletorp.

Однак я сам виявив, що переддень типу "мусоун" повинен бути відмежований і зв'язаний знову. Тож фрагмент коду, який працював для мене, такий:

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

Дійсно витрачати ресурси для клонування об'єктів DOM, якщо вони вам справді не потрібні.
googletorp

Привіт, я зустрічався з тим самим питанням, все йде добре, але я зустрів помилку js: "Uncaught TypeError: Неможливо прочитати властивість 'click' of undefined" також для "mousedown".
bluesky_still

Це єдине рішення, яке я міг взяти на роботу. Клонування тут є ключовим. Без клону, тоді, коли ви натискаєте ОК, попередження відразу миттєво з’являється.
Фелікс Єва

4

Питання давнє, але мене це теж цікавило. На мою думку, найпростішим способом є використання події клацання у визначенні 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, оскільки вона запускається перед подією натискання:

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

Якщо ви все ще хочете, щоб ваш запит на Ajax викликався разом із подією в 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');
});

Обидві версії працюють!


Ага! Мені це подобається, тому що він робить те, що ви хочете: дає змогу впоратися з процесом "Друпал", який ви зможете зателефонувати, коли вам це потрібно. Nb. Мені потрібно було мати preventDefaultсвій обробник кліків, щоб запобігти нормальному (не-js) надсиланню форми.
artfulrobot

0

Ви спробували запустити свій JS всередині поведінки Drupal? Це може бути просто те, що ваш обробник кліків додається після Drupal.

У будь-якому випадку, хоча ви повинні мати змогу відв’язати обробник клацань Drupal на кнопці, щоб вас викликали першими, і ви могли зателефонувати в обробник Ajax натискань Drupal вручну (і умовно).


0

Відповідаючи, зауважимо, що код googletorp не є 100% правильним.

Вам потрібно змінити рядок, де зберігаються події, на це:

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

Таким чином ви усуваєте будь-які проблеми з посиланням на об'єкт, тому при розв’язуванні подій клацання він також не скасовується у вашому варі;)

Також слід враховувати, що з моменту jQuery 1.8 метод .data () був застарілим. Отримання даних про події зараз здійснюється за допомогою внутрішньої структури даних:

.data ("події") : jQuery зберігає свої пов'язані з подіями дані в об'єкті даних, названий (чекайте цього) події на кожному елементі. Це внутрішня структура даних, тому в 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'];
}

-1

Я виправив це, змінивши файл mispal / ajax.jx drupal.

Створіть копію файлу 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);   
     }    
},

Це працює добре для мене.


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

Оскільки Drupal прив’язується до події mousedown, тому ваш обробник подій клацання ніколи не запускатиметься.
Фелікс Єва

Drupal не змінює спосіб роботи PHP або JS. Чому б він НЕ слухав події клацання? Тут Drupal використовується просто для приєднання JS-коду. Після завантаження сайту Drupal зробив свою роботу. Слухачі JS все там, правда? ;)
schlicki

Ви ставите гарне запитання і якщо чесно, я не знаю, чому подія клацання не спрацьовує. Однак після обширного тестування я можу підтвердити, що це не так. Ймовірно, потрібно прочитати ajax.js Друпала, щоб краще зрозуміти.
Фелікс Єва
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.