web-dev-qa-db-ja.com

バックエンドにウィジェットが追加されたときのJavascriptの実行

私はそれらに接続されているJavaScriptコントロールを持っているウィジェットを持っています。

ウィジェット管理ページがロードされたときにウィジェットが存在する場合、コントロールは正しく機能します。

私が新しいウィジェットを追加するとき、それらは正しく機能しません、私はマークアップを得ます、しかしjavascriptイベントは効力を生じません。

新しいウィジェットを保存すると、フォームがリロードされたときにコントロールが正しく作成され、動作するようになりました。

ページを更新すると問題も解決しますが、これは既存のウィジェットに対してのみです。新しいウィジェットにはまだこの問題があります。

具体的には、これらの時点で選択入力を選択しています。

  • ドキュメント準備完了
  • Ajaxcomplete

私は自分のコードが必要に応じて各イベントで実行されることを確認しましたが、結果は期待通りではありません。

これは問題を実証するテストプラグインです:

https://Gist.github.com/Tarendai/8466299

あなたは私がそれが変換することができることを見つけるあらゆるselect要素と共に増加するカウンターを持っているのを見るでしょう。

ノート:

  • ウィジェットページがロードされると、JSコンソールのカウンタが予想通りに増加するのがわかります。
  • 私が新しいウィジェットを追加すると、コードは実行されますが、found.lengthが0であることが示すように、実行可能な選択要素を見つけることができません。選択要素があります
  • select要素にはそれらを識別するためのクラスがあります。このクラスは、選択ライブラリが適用されると削除され、既存のウィジェットでの重複や再処理が防止されます。
  • Selectizeを使用する前に、私は同じ問題を抱えていたSelect2を使用しました。
  • AJAXコードをコメントアウトすると、新しいウィジェットには標準の選択入力があると思います。彼らはしない。これが事実である理由はわかりません

それでは、変更を加える前にユーザーにリフレッシュ/保存をクリックするように指示せずに選択制御を機能させるにはどうすればよいでしょうか。

20
Tom J Nowell

素晴らしいニュース、

修正しました。

私の最初のコメントであなたの要旨を見逃していて、あなたがあなたが既に実行したという答えをあなたに与えることをお詫び申し上げます。電車の中で電話で答えるように教えましょう!

あなたのajaxstopの使い方は正しいです。ほとんどの部分でJSが正常に動作しているとしたら、CSSスタイルが初期化され、DOMが変更されていることがわかります。

問題は実際にはセレクタにあります。

これは、ウィジェットのコンテンツがajaxを介して読み込まれていないためです。実際、ウィジェットのコンテンツは非表示の左側の列から複製され、右側の列にウィジェットの位置を保存するためのajax呼び出しが発生します。これは、たとえ考えられたコンテンツが複製されたとしても、ajaxstopがどうしてうまくいくのかを説明しています。ただし、左側の列には隠しバージョンのウィジェットがあるため、JSはそれをインスタンス化しています。そのようにあなたがそれを右のコラムにドラッグするとき、あなたは隠されたウィジェットの壊れたクローンを得ています。

したがって、左側のものを選択する必要があります。以下は修正されたコードです。

<script>
jQuery( document ).ready( function( $ ) {
    function runSelect() {
        var found = $( '#widgets-right select.testselectize' );
        found.each( function( index, value ) {

            $( value ).selectize();
                .removeClass( 'testselectize' )
                .addClass( 'run-' + window.counter );

            console.log( $val );
            window.counter++;
        } );
    }

    window.counter = 1;

    runSelect();

    $( document ).ajaxStop( function() {
        runSelect();
    } );
} );
</script>
12
MichaelJames

@ aaron-holbrookがコメントしたように、よりクリーンなアプローチが行われるでしょう:

jQuery(document).on('widget-updated widget-added', function(){
    // your code to run
});

多くの場合、ページがロードされたときやウィジェットが更新されたときにもJSを実行したいと思うでしょう。あなたはこんな風にそうするかもしれません。

function handle_widget_loading(){
   // your code to run
}
jQuery(document).ready( handle_widget_loading );
jQuery(document).on('widget-updated widget-added', handle_widget_loading );

回答として参照用にここに貼り付けるだけで、そのコメントを見つけやすくなります。

16
chifliiiii