单击#ajax按钮时如何添加JS确认弹出窗口


10

我有一个已启用#ajax的基本FAPI按钮输入,并且工作正常,但是我想添加一个JS“您确定吗?” 在代码实际运行之前单击该按钮时会弹出确认对话框,我不确定该怎么做,因为无论我做什么,FAPI的JS似乎都在吞噬单击之前的内容。

我尝试添加一个内联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可以识别的堆栈顶部?

Answers:


15

Drupal是一个PHP框架,使用它和FAPI可以得到多少精美的AJAX东西令人惊讶。但是它有其局限性,对于这样的用例,我建议您使用自定义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;
    });
  }
}

我还添加了$('。confirm')。unbind('mousedown'); Drupal侦探也进行“ mousedown”事件。
milkovsky

如果用户取消确认对话框然后再次单击,是否会中断按钮?(因为$('.confirm').unbind('click');)...还是我读错了吗?抱歉,您不熟悉unbind
ErichBSchulz 2013年

1
@ErichBSchulz Unbind仅通过在页面加载时调用的attach方法调用一次。
googletorp

gist.github.com/guoxiangke/0dffa7722a67f052c7ce未捕获的TypeError:无法读取未定义的属性“ click”?我有一个表单,在node / add / content-type中,我用ajax对其进行ajax,使用js验证
bluesky_still 2014年

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错误:“ mousedown”也出现了“未捕获的TypeError:无法读取未定义的属性'click'”。
bluesky_still 2014年

这是我可以使用的唯一解决方案。克隆是这里的关键。如果没有克隆,则单击“确定”时,警报会立即重新出现。
菲利克斯·夏娃

4

这个问题很老,但是我对此也很感兴趣。我认为,最简单的方法是在Ajax定义中使用click事件,因为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
});

如果仍然希望通过mousedown事件调用Ajax请求,则可以使用自定义事件:

//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)提交。
artfulrobot15年

0

您是否尝试过在Drupal行为中运行JS?可能是您的点击处理程序在Drupal之后被附加了。

无论哪种方式,您都应该能够解除按钮上Drupal的单击处理程序的绑定,以便先被调用,然后可以手动(有条件地)调用Drupal的Ajax单击处理程序。


0

请注意,googletorp的代码不是100%正确。

您需要将存储事件的行更改为此:

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

这样可以消除任何对象引用问题,因此在取消绑定click事件时,它也不会在您的var中取消绑定;)

另外,请注意,自jQuery 1.8起,不推荐使用.data()方法。现在通过内部数据结构完成事件数据的获取:

.data(“事件”):jQuery将其与事件相关的数据存储在每个元素上名为(等待)事件的数据对象中。这是一个内部数据结构,因此在1.8中,它将从用户数据名称空间中删除,因此不会与同名项目冲突。仍然可以通过jQuery._data(element,“ events”)访问jQuery的事件数据,但是请注意,这是一个内部数据结构,未记录且不应进行修改。

资料来源: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

我已经通过修改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)2014年

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事件上,所以您的click事件处理程序将永远不会触发。
菲利克斯·夏娃

Drupal不会改变PHP或JS的工作方式。为什么它不监听click事件?在这里,Drupal仅用于附加JS代码。一旦站点被加载,Drupal就完成了它的工作。JS监听器都在那里,对吗?;)
schlicki

您提出了一个很好的问题,说实话,我不知道为什么点击事件不会触发。但是,经过广泛的测试,我可以确认没有。可能需要阅读Drupal的ajax.js才能更好地理解。
菲利克斯·夏娃
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.