Wykonywanie Javascript Gdy widżet zostanie dodany w backend

20

Mam widżety z dołączonymi kontrolkami javascript.

Jeśli widżet jest obecny podczas ładowania strony administratora widgetu, formanty działają poprawnie.

Gdy dodam nowy widżet, nie działają one poprawnie, otrzymuję znaczniki, ale żadne zdarzenia javascript nie działają.

Jeśli zapiszę nowy widżet, po ponownym załadowaniu formularza formanty są tworzone poprawnie i teraz działają.

Odświeżenie strony również rozwiązuje problem, ale tylko w przypadku istniejących widżetów. Nowe widżety nadal mają ten problem.

W szczególności uruchamiam selectize na wybranych wejściach w następujących punktach:

  • dokument gotowy
  • Ajaxcomplete

Sprawdziłem, czy mój kod jest uruchamiany przy każdym zdarzeniu zgodnie z oczekiwaniami, ale wyniki nie są zgodne z oczekiwaniami.

Oto wtyczka testowa pokazująca problem:

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

Zobaczysz, że mam licznik, który rośnie wraz z każdym wybranym elementem, który może przekonwertować.

Uwagi:

  • Po załadowaniu strony widżetu widzę wzrost licznika w konsoli JS zgodnie z oczekiwaniami
  • Gdy dodam nowy widżet, kod jest uruchamiany, jednak nie można znaleźć żadnych wybranych elementów, na których mógłby działać, jak pokazano przez find. Długość wynosi 0. Nie powinno tak być, ponieważ każdy nowy widżet tego typu powinien mieć wybrany element
  • elementy select mają klasę do ich identyfikacji, ta klasa jest usuwana po zastosowaniu biblioteki selectize, aby zapobiec powielaniu i ponownemu przetwarzaniu istniejących widgetów.
  • Przed użyciem selectize użyłem Select2, który miał ten sam problem
  • Komentując kod AJAX, oczekiwałbym, że nowe widżety będą miały standardowe wejście select. Oni nie. Nie wiem, dlaczego tak jest

Jak więc sprawić, aby kontrola wyboru działała bez powiadamiania użytkownika o odświeżeniu / kliknięciu opcji Zapisz przed dokonaniem zmian?

Tom J Nowell
źródło
To kwestia delegowania wydarzeń. Musisz przyjrzeć się .on()metodzie jQuerys . Co wymaga powiązania zdarzenia z dokumentem. Jednak jakie wydarzenie będzie odpowiednie, nie jestem teraz pewien. Ostatecznie dzieje się tak, ponieważ twoje oryginalne powiązania reprezentują początkową wersję DOM, gdy strona została załadowana, i w przeważającej części są ślepe na nowe elementy (treść widżetu), które są dodawane za pośrednictwem ajax. Mam nadzieję, że skieruje cię to w dobrym kierunku, jeśli nie, mogę odpowiedzieć lepiej, gdy jestem w pracy.
Tego się spodziewałem i dlaczego dodałem tę jQuery( document ).ajaxStop( function() {część, aby móc zainicjować formanty w nowo załadowanych widżetach. Gdybym jednak usunął ten wiersz, spodziewałbym się, że nowe widżety będą miały standardowe dane wejściowe HTML, ale nie są to s
Tom J Nowell
Jak skomentował @ aaron-holbrook, jego podejście jest najczystsze dzięki wykorzystaniu zdarzeń widget-updatedi widget-added. Chciałbym również podkreślić w kodzie @ michaeljames użycie identyfikatora elementu #widgets-right. Pamiętaj, aby używać go do kierowania elementów aktywnych widgetów w kodzie JS, w przeciwnym razie możesz uzyskać duplikaty elementów, ponieważ kod może również wybrać ukryte nieaktywne elementy widgetów po lewej stronie ekranu (i te zostaną sklonowane po dodaniu widgetu).
Julien

Odpowiedzi:

12

Dobre wieści,

Naprawiłem to.

Przepraszam za pominięcie twojej istoty w moim pierwszym komentarzu i udzielenie odpowiedzi, którą już wdrożyłeś. To nauczy mnie odbierać przez telefon w pociągu!

Twoje użycie ajaxstop jest prawidłowe. Cholera, JS w przeważającej części działa poprawnie, można było zobaczyć, że style css zostały zainicjowane i zmiany w DOM.

Problem leży w rzeczywistości w twoim selektorze.

Wynika to z faktu, że zawartość widgetu nie jest ładowana za pośrednictwem ajax, w rzeczywistości klonuje ją z lewej kolumny, w której jest ukryta, a następnie uruchamia wywołanie ajax, aby zapisać pozycję widgetu w prawej kolumnie. To wyjaśnia, dlaczego ajaxstop działa na smakołyk, nawet jeśli treść jest klonowana. Ponieważ jednak w lewej kolumnie znajduje się ukryta wersja widżetu, twoja JS tworzy ją. Dlatego przeciągając go do prawej kolumny, otrzymujesz zniekształcony klon ukrytego widżetu.

Dlatego musisz wybrać ten po lewej stronie. Poniżej znajduje się poprawiony kod:

<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>
kajzer
źródło
Cholera, muszę przejść test <3
Tom J Nowell
Bardzo eleganckie rozwiązanie poważnego bólu głowy!
bosco
3
Odradzałbym uruchamianie przy każdym pojedynczym zdarzeniu „ajaxStop” i zamiast tego sugerowałbym używanie na zdarzeniach „dodanych do widżetów” oraz „zaktualizowanych przy pomocy widgetów”.
Tyrun,
16

Jak skomentował @ aaron-holbrook, należy zastosować czystsze podejście:

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

W wielu przypadkach będziesz również chciał uruchomić JS podczas ładowania strony, a także po aktualizacji widżetów. Możesz to zrobić w ten sposób.

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

Wystarczy wkleić tutaj w celach informacyjnych, ponieważ odpowiedzi są znacznie łatwiejsze do znalezienia

chifliiiii
źródło
2
prawdopodobnie powinien użyć jQuery zamiast $
Mark Kaplun