web-dev-qa-db-ja.com

#ajaxボタンをクリックしたときにJS確認ポップアップを追加する方法

#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が認識するスタックの最上部に送信ハンドラを追加する方法はありますか?

10
Mike Crittenden

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

質問は古いですが、私も興味を持っていました。私の意見では、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',
_

次に、Javascriptファイルの.mousedown()イベントでこのイベントをトリガーできます。

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

どちらのバージョンでも機能します。

4
Daniel

jeroenが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);
4
Turtletrail

Drupal動作内でJSを実行してみましたか?クリックハンドラーがDrupalの後に接続されている可能性があります。

どちらの方法でも、ボタンでDrupalのクリックハンドラーのバインドを解除して、最初に呼び出され、DrupalのAjaxクリックハンドラーを手動で(および条件付きで)呼び出すことができるようにする必要があります。

0
Adam DiCarlo

Googletorpのコードは100%正しくないことに注意してください。

イベントが格納されている行を次のように変更する必要があります。

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

このようにして、オブジェクト参照の問題を排除するため、クリックイベントのバインドを解除しても、変数のバインドは解除されません;)

また、jQuery 1.8以降、.data()メソッドは推奨されなくなりました。イベントデータの取得は、内部データ構造を介して行われます。

。data(“ events”):jQueryは、そのイベント関連データを、各要素のイベント(待機)イベントという名前のデータオブジェクトに格納します。これは内部データ構造であるため、1.8ではユーザーデータの名前空間から削除されるため、同じ名前の項目と競合しません。 jQueryのイベントデータはjQuery._data(element、 "events")を介して引き続きアクセスできますが、これはドキュメント化されていない内部データ構造であり、変更しないでください。

ソース: http://blog.jquery.com/2011/11/08/building-a-slimmer-jquery/

0
Jeroen

上記の多くの有用な答えを見つけ、フォームを機能させることができました。すべてをまとめると、これは私のアプリケーションで機能したものです。確認ダイアログと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'];
}
0
Susanne