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


20

JavaScriptコントロールがアタッチされているウィジェットがあります。

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

新しいウィジェットを追加すると、それらは正しく機能せず、マークアップが表示されますが、javascriptイベントは有効になりません。

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

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

具体的には、これらのポイントで選択入力に対してselectizeを実行しています。

  • 文書準備完了
  • Ajaxcomplete

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

問題を実証するテストプラグインは次のとおりです。

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

変換できることがわかったすべての選択要素で増加するカウンターがあることがわかります。

ノート:

  • ウィジェットページがロードされると、JSコンソールで期待どおりにカウンターが増加するのがわかります。
  • 新しいウィジェットを追加すると、コードが実行されますが、found.lengthが0であることからわかるように、実行可能な選択要素の検索に失敗します。このタイプのすべての新しいウィジェットは、選択要素を持っている
  • select要素にはそれらを識別するためのクラスがあり、selectizeライブラリが適用されると、このクラスは削除され、既存のウィジェットでの複製と再処理が防止されます。
  • selectizeを使用する前に、同じ問題のあるSelect2を使用しました
  • AJAXコードをコメントアウトすると、新しいウィジェットには標準の選択入力が含まれることになります。彼らはしない。なぜそうなのか分かりません

それでは、変更を行う前に保存を更新/クリックするようにユーザーに通知せずに、selectizeコントロールを機能させるにはどうすればよいですか?


これはイベントの委任の問題です。jQuerys .on()メソッドの使用を検討する必要があります。イベントをドキュメントにバインドする必要があります。しかし、どのようなイベントが適切かは今のところわかりません。最終的には、元のバインディングはページがロードされたときのDOMの初期バージョンを表し、ほとんどの場合、ajaxを介して追加される新しい要素(ウィジェットコンテンツ)を認識しないためです。うまくいけば、正しい方向にあなたを向けることができます。そうでない場合は、仕事中にもっとよく答えることができます。

これが私が期待しjQuery( document ).ajaxStop( function() {ていたことであり、新しくロードされたウィジェットのコントロールを初期化できるようにパーツを追加した理由です。ただし、その行を削除すると、新しいウィジェットには標準のHTML選択入力が含まれることが期待されますが、それらには= sがありません
トムJノウェル

@ aaron-holbrookがコメントしたように、そのアプローチはwidget-updatedwidget-addedイベントを使用することで最もクリーンなアプローチです。また、@ michaeljamesコードで、要素idの使用を強調したいと思い#widgets-rightます。JSコード内のアクティブなウィジェット要素をターゲットにするためにそれを使用してください。そうしないと、コードが画面の左側にある非表示の非アクティブなウィジェット要素を選択する可能性があるため、重複した要素を取得する可能性があります(ウィジェットが追加されるとクローン化されます)
ジュリアン

回答:


12

素晴らしいニュース、

私はそれを修正しました。

私の最初のコメントであなたの要点を見失い、あなたがすでに実装した答えを与えてくれたことをおologiesびします。それは電車の中で私の電話で答えることを教えてくれます!

ajaxstopの使用は正しいです。JSの大部分は正しく動作しています。CSSスタイルが初期化され、DOMの変更が表示されます。

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

これは、ウィジェットコンテンツがajaxを介して読み込まれないためです。実際、非表示の左側の列からクローンを作成し、次にajax呼び出しを起動してウィジェットの位置を右側の列に保存します。これは、ajaxstopがおもしろい動作をする理由を説明しています。ただし、左側の列にウィジェットの非表示バージョンがあるため、JSはそのインスタンスを作成しています。そのため、右側の列にドラッグすると、隠されたウィジェットのクローンが破損します。

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

<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>

神聖な、私はこれをテストする必要があります<3
トムJノウェル

大きな頭痛の種に対する非常にエレガントなソリューション!
ボスコ14年

3
すべての「ajaxStop」イベントで実行することはお勧めしませんが、代わりに「widget-added」イベントと「widget-updated」イベントで使用することをお勧めします。
タイラン14

16

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

答えとして参照するためにここに貼り付けるだけで、そのコメントを見つけるのがはるかに簡単です


2
おそらく$ではなくjQueryを使用する必要があります
Mark Kaplun
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.