วิธีเพิ่มป๊อปอัพการยืนยัน 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;
    });
  }
}

ฉันได้เพิ่ม $ ('. ยืนยัน'). unbind ('mousedown'); เหตุการณ์ 'mousedown' ของ Drupal listerns ก็เช่นกัน
milkovsky

จะไม่ทำให้ปุ่มแตกถ้าผู้ใช้ยกเลิกกล่องโต้ตอบยืนยันจากนั้นคลิกอีกครั้ง? (เพราะ$('.confirm').unbind('click');) ... หรือว่าฉันอ่านผิด ขออภัยไม่คุ้นเคยกับunbind
ErichBSchulz

1
@ErichBSchulz Unbind ถูกเรียกเพียงครั้งเดียวโดยวิธีการแนบซึ่งเรียกว่าเมื่อโหลดหน้าเว็บ
googletorp

gist.github.com/guoxiangke/0dffa7722a67f052c7ce Uncaught TypeError: ไม่สามารถอ่านคุณสมบัติ 'คลิก' ที่ไม่ได้กำหนด ?????? ฉันมีแบบฟอร์มใน 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);

เป็นการสิ้นเปลืองทรัพยากรในการโคลนวัตถุ DOM เว้นแต่ว่าคุณต้องการมันจริง ๆ
googletorp

สวัสดีฉันพบคำถามเดียวกันทุกอย่างไปได้ดี แต่ฉันพบข้อผิดพลาด js: "Uncaught TypeError: ไม่สามารถอ่านคุณสมบัติ 'คลิก' ที่ไม่ได้กำหนด" สำหรับ "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');
});

ทั้งสองรุ่นใช้งานได้!


ใช่ ฉันชอบอันนี้เพราะทำในสิ่งที่คุณต้องการ: ให้คุณจัดการกระบวนการ Drupal นอกชั้นวางที่คุณสามารถโทรหาเมื่อคุณต้องการ 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.

วิธีนี้คุณกำจัดปัญหาการอ้างอิงวัตถุใด ๆ ดังนั้นเมื่อยกเลิกการผูกเหตุการณ์คลิกก็ไม่ได้ผูกใน var ของคุณเช่นกัน;)

และโปรดทราบว่าเนื่องจาก jQuery 1.8 the .data () วิธีการได้รับการคัดค้าน การรับข้อมูลเหตุการณ์ทำได้ผ่านโครงสร้างข้อมูลภายใน:

.data (“ events”) : jQuery เก็บข้อมูลที่เกี่ยวข้องกับเหตุการณ์ไว้ในวัตถุข้อมูลชื่อ (รอให้มัน) เหตุการณ์ในแต่ละองค์ประกอบ นี่คือโครงสร้างข้อมูลภายในดังนั้นใน 1.8 นี้จะถูกลบออกจากพื้นที่ชื่อข้อมูลผู้ใช้ดังนั้นมันจะไม่ขัดแย้งกับรายการที่มีชื่อเดียวกัน ข้อมูลเหตุการณ์ของ jQuery ยังคงสามารถเข้าถึงได้ผ่านทาง jQuery._data (องค์ประกอบ, "events") แต่โปรดทราบว่านี่เป็นโครงสร้างข้อมูลภายในที่ไม่มีเอกสารประกอบและไม่ควรแก้ไข

ที่มา: http://blog.jquery.com/2011/11/08/building-a-slimmer-jquery/


0

ฉันพบคำตอบที่มีประโยชน์มากมายด้านบนและสามารถทำให้แบบฟอร์มของฉันทำงานได้ นี่คือสิ่งที่ใช้ได้ผลกับแอปพลิเคชันของฉัน: ปุ่มแบบฟอร์มลบพร้อมข้อความยืนยันและ AJAX โทรกลับเพื่อแก้ไขเนื้อหาของรายการที่เลือก

จาวาสคริปต์:

$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 callback:

function ajax_delete_callback ($form, $form_state) {

  // callback implementation code

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

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

มันใช้งานได้ดีสำหรับฉัน


1
มันนับว่าเป็นแฮ็คหลักและควรหลีกเลี่ยง
Mołot

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 ของ Drupal เพื่อทำความเข้าใจให้ดีขึ้น
เฟลิกซ์อีฟ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.