Cách thêm cửa sổ bật lên xác nhận JS khi nhấp vào nút #ajax


10

Tôi có một đầu vào nút FAPI cơ bản được kích hoạt #ajax và nó hoạt động tốt, nhưng tôi muốn thêm một mã "Bạn có chắc không?" cửa sổ bật lên xác nhận khi nhấp vào nút trước khi mã thực sự chạy và tôi không biết phải làm thế nào vì JS của FAPI dường như đang ăn nhấp chuột trước khi tôi có thể làm được điều đó cho dù tôi có làm gì đi nữa.

Tôi đã thử thêm một trình xử lý onclick nội tuyến, như vậy:

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

... không giúp được gì và tôi cũng đã thử thêm:

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

trong mô-đun JS của tôi cũng bị bỏ qua.

Còn ý tưởng nào khác không? Có cách nào để thêm trình xử lý trình lên đầu ngăn xếp mà Drupal #ajax sẽ nhận ra không?

Câu trả lời:


15

Drupal là một khung công tác PHP và thật tuyệt vời khi bạn có thể sử dụng công cụ AJAX thú vị đó và FAPI. Nhưng nó có giới hạn và đối với trường hợp sử dụng như thế này, tôi sẽ đề nghị bạn sử dụng JavaScript tùy chỉnh. Ngoài ra, thay vì sử dụng hộp thoại JavaScript thông thường, bạn có thể sử dụng Giao diện người dùng jQuery để tạo hộp thoại có thể thay thế.

Dù sao, vấn đề mà bạn gặp phải có thể là do bạn sử dụng AJAX trên nút gửi. Vì bạn đang sử dụng AJAX cho cuộc gọi xóa thực tế preventDefaultvà tương tự sẽ không hoạt động.

Những gì bạn sẽ phải làm là một cái gì đó như thế này. (Điều này không được thử nghiệm rộng rãi nhưng sẽ hoạt động.)

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

Tôi cũng đã thêm $ ('. Xác nhận'). Unbind ('mousedown'); Sự kiện 'mousedown' của Drupal cũng vậy.
milkovsky

Điều này sẽ không phá vỡ nút nếu người dùng hủy hộp thoại xác nhận sau đó nhấp lại? (bởi vì $('.confirm').unbind('click');) ... hay tôi đang đọc sai? xin lỗi không quen thuộc vớiunbind
ErichBSchulz

1
@ErichBSchulz Unbind chỉ được gọi một lần, bằng phương thức đính kèm được gọi khi tải trang.
googletorp

gist.github.com/guoxiangke/0dffa7722a67f052c7ce Uncaught TypeError: Không thể đọc thuộc tính 'click' của không xác định ?????? Tôi có một biểu mẫu, trong nút / add / type-type và tôi ajax nó, sử dụng js xác thực
bluesky_still

4

xác nhận rằng Jeroen đang sửa mã của googletorp.

Tuy nhiên, bản thân tôi đã phát hiện ra rằng các evens thuộc loại "mousedown" phải được trả giá và bị ràng buộc một lần nữa. Vì vậy, đoạn mã làm việc cho tôi là như sau:

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

Thật sự lãng phí tài nguyên để sao chép các đối tượng DOM trừ khi bạn thực sự cần chúng.
googletorp

Xin chào, tôi đã gặp một câu hỏi tương tự, tất cả đều ổn, nhưng tôi đã gặp một lỗi js: "Uncaught TypeError: Không thể đọc thuộc tính 'click' của không xác định" cũng cho "mousedown".
bluesky_still

Đây là giải pháp duy nhất mà tôi có thể làm việc. Nhân bản là chìa khóa ở đây. Nếu không có bản sao thì khi bạn bấm ok, cảnh báo sẽ xuất hiện lại ngay lập tức.
Đêm giao thừa

4

Câu hỏi đã cũ, nhưng tôi cũng quan tâm đến nó. Theo tôi, cách dễ nhất là sử dụng sự kiện nhấp chuột trong định nghĩa Ajax của bạn, bởi vì Drupal sử dụng sự kiện mousedown làm mặc định:

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

Sau đó, bạn chỉ cần thêm một .mousedown()sự kiện vào nút trong tệp Javascript của mình, vì nó được kích hoạt trước sự kiện nhấp chuột:

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

Nếu bạn vẫn muốn Yêu cầu Ajax của bạn được gọi với sự kiện mousedown, bạn có thể sử dụng một sự kiện tùy chỉnh:

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

Sau đó, bạn có thể kích hoạt sự kiện này trong trường .mousedown()hợp tệp Javascript của bạn:

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

Cả hai phiên bản đều hoạt động!


Vâng! Tôi thích cái này vì nó làm những gì bạn muốn: cung cấp cho bạn một quy trình xử lý Drupal ngoài luồng mà sau đó bạn có thể gọi khi bạn cần. Nb. Tôi cần phải có một preventDefaulttrình xử lý nhấp chuột để ngăn chặn việc gửi biểu mẫu bình thường (không phải js).
artfulrobot

0

Bạn đã thử chạy JS của mình bên trong hành vi Drupal chưa? Nó có thể chỉ là trình xử lý nhấp chuột của bạn được gắn sau Drupal.

Dù bằng cách nào bạn cũng có thể hủy liên kết trình xử lý nhấp chuột của Drupal trên nút để bạn được gọi trước và bạn có thể gọi trình xử lý nhấp chuột Ajax của Drupal theo cách thủ công (và có điều kiện).


0

Trả lời để lưu ý rằng mã của googletorp không chính xác 100%.

Bạn cần thay đổi dòng nơi các sự kiện được lưu trữ vào đây:

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

Bằng cách này, bạn loại bỏ bất kỳ vấn đề tham chiếu đối tượng nào, vì vậy khi hủy liên kết các sự kiện nhấp chuột, nó cũng không hủy liên kết với var của bạn;)

Ngoài ra, hãy lưu ý rằng vì jQuery 1.8, phương thức .data () không được dùng nữa. Nhận dữ liệu sự kiện hiện được thực hiện thông qua cấu trúc dữ liệu nội bộ:

.data (các sự kiện của Nhật Bản) : jQuery lưu trữ dữ liệu liên quan đến sự kiện của nó trong một đối tượng dữ liệu có tên (chờ cho nó) các sự kiện trên mỗi phần tử. Đây là cấu trúc dữ liệu nội bộ, vì vậy, trong 1.8, phần này sẽ bị xóa khỏi không gian tên dữ liệu người dùng để nó không xung đột với các mục cùng tên. Dữ liệu sự kiện của jQuery vẫn có thể được truy cập thông qua jQuery._data (phần tử, "sự kiện") nhưng lưu ý rằng đây là cấu trúc dữ liệu nội bộ không có giấy tờ và không nên sửa đổi.

Nguồn: http://blog.jquery.com/2011/11/08/building-a-slimmer-jquery/


0

Tôi tìm thấy nhiều câu trả lời hữu ích ở trên và đã có thể làm cho biểu mẫu của tôi hoạt động. Đặt tất cả lại với nhau, đây là những gì hoạt động cho ứng dụng của tôi: Nút xóa biểu mẫu với hộp thoại xác nhận và gọi lại AJAX để sửa đổi nội dung của danh sách chọn.

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

Phần tử biểu mẫu (danh sách chọn) sẽ được sửa đổi:

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

Nút:

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

);

Và cuối cùng, cuộc gọi lại AJAX:

function ajax_delete_callback ($form, $form_state) {

  // callback implementation code

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

-1

Tôi đã sửa lỗi này bằng cách sửa đổi tệp drupal misc / ajax.jx.

Tạo một bản sao của tệp ajax.js và đặt nó vào bất kỳ mô-đun tùy chỉnh nào và sửa đổi Drupal.ajax = function (base, element, element_settings) { chức năng trong 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);   
     }    
},

Nó làm việc tốt cho tôi.


1
Nó được coi là hack cốt lõi, và có lẽ nên tránh.
Mołot

1
Và hoàn toàn không cần thiết - vi.wikipedia.org/wiki/Monkey_patch
Clive

Đây là cách duy nhất tôi có thể khiến khái niệm này hoạt động với việc hiển thị các hộp xác nhận kép. Một ngoại lệ là tôi phải thực hiện kiểm tra câu lệnh if nếu ajax.url == 'field_collection_remove_js'. Có lẽ đó là vì phiên bản Drupal tôi đang sử dụng?
Richard

-1

Có thể hơi cũ, nhưng tôi tự hỏi tại sao chúng ta không thể sử dụng:

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

Vì Drupal liên kết với sự kiện mousedown nên trình xử lý sự kiện nhấp chuột của bạn sẽ không bao giờ kích hoạt.
Đêm giao thừa

Drupal không thay đổi cách thức hoạt động của PHP hoặc JS .. Tại sao nó KHÔNG nghe sự kiện nhấp chuột? Ở đây Drupal chỉ được sử dụng để đính kèm mã JS. Khi trang web được tải, Drupal đã hoàn thành công việc của mình. Người nghe JS đều ở đó, phải không? ;)
schlicki

Bạn đưa ra một câu hỏi hay và thành thật mà nói tôi không biết tại sao sự kiện click không kích hoạt. Tuy nhiên sau khi thử nghiệm rộng rãi tôi có thể xác nhận rằng nó không. Có lẽ cần phải đọc ajax.js của Drupal để hiểu rõ hơn.
Đêm giao thừa
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.