Thực thi Javascript khi một widget được thêm vào trong phần cuối


20

Tôi có các widget có các điều khiển javascript kèm theo chúng.

Nếu tiện ích có mặt khi trang quản trị tiện ích tải, các điều khiển hoạt động chính xác.

Khi tôi thêm một tiện ích mới, chúng không hoạt động chính xác, tôi nhận được đánh dấu, nhưng không có sự kiện javascript nào có hiệu lực.

Nếu tôi lưu tiện ích mới, khi biểu mẫu tải lại, các điều khiển được tạo chính xác và bây giờ hoạt động.

Làm mới trang cũng khắc phục sự cố, nhưng chỉ đối với các tiện ích hiện có. Các vật dụng mới vẫn có vấn đề này.

Cụ thể tôi đang chạy selectize trên các đầu vào được chọn tại các điểm sau:

  • tài liệu đã sẵn sàng
  • Hoàn thành

Tôi đã xác minh rằng mã của tôi được chạy trên mỗi sự kiện như mong muốn, nhưng kết quả không như mong đợi.

Đây là một plugin thử nghiệm chứng minh vấn đề:

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

Bạn sẽ thấy tôi có một bộ đếm tăng với mọi yếu tố được chọn mà nó thấy rằng nó có thể chuyển đổi.

Ghi chú:

  • Khi trang tiện ích tải, tôi có thể thấy bộ đếm tăng lên trong bảng điều khiển JS như mong đợi
  • Tuy nhiên, khi tôi thêm một tiện ích mới, mã sẽ được chạy, nó không tìm thấy bất kỳ phần tử chọn nào mà nó có thể chạy, như được chứng minh bởi Found.length là 0. Điều này không nên xảy ra, vì mọi widget mới thuộc loại đó nên có một yếu tố chọn
  • các phần tử chọn có một lớp để xác định chúng, lớp này được loại bỏ sau khi thư viện chọn được áp dụng để ngăn ngừa trùng lặp và xử lý lại trên các widget hiện có.
  • Trước khi sử dụng selectize, tôi đã sử dụng Select2, vấn đề tương tự
  • Nhận xét mã AJAX, tôi mong muốn các widget mới có đầu vào chọn chuẩn. Họ không. Tôi không biết tại sao lại như vậy

Vậy làm cách nào để làm cho điều khiển chọn lọc hoạt động mà không yêu cầu người dùng làm mới / nhấp lưu trước khi thực hiện thay đổi?


Đó là một vấn đề phái đoàn sự kiện. Bạn sẽ cần xem xét sử dụng .on()phương thức jQuery . Mà yêu cầu bạn liên kết một sự kiện với tài liệu. Tuy nhiên sự kiện nào sẽ phù hợp Tôi không chắc chắn ngay bây giờ. Cuối cùng, đó là vì các ràng buộc ban đầu của bạn đại diện cho phiên bản ban đầu của DOM khi trang được tải và phần lớn bị mù với các phần tử mới (nội dung widget) đang được thêm thông qua ajax. Hy vọng rằng điều đó sẽ chỉ cho bạn đi đúng hướng, nếu không tôi có thể trả lời tốt hơn khi tôi đang làm việc.

Đây là những gì tôi mong đợi và tại sao tôi đã thêm jQuery( document ).ajaxStop( function() {phần này để tôi có thể khởi tạo các điều khiển trong các tiện ích mới được tải. Tuy nhiên, nếu tôi xóa dòng đó, tôi sẽ mong các widget mới có các đầu vào chọn HTML tiêu chuẩn, nhưng chúng không = s
Tom J Nowell

Như @ aaron-holbrook nhận xét, cách tiếp cận của nó là cách sạch nhất bằng cách sử dụng widget-updatedwidget-addedcác sự kiện. Ngoài ra tôi muốn nhấn mạnh, trong mã @michaeljames, việc sử dụng id phần tử #widgets-right. Hãy chắc chắn sử dụng nó để nhắm mục tiêu các phần tử widget đang hoạt động bên trong mã JS của bạn nếu không bạn có thể nhận được các phần tử trùng lặp vì mã của bạn cũng có thể chọn các thành phần widget không hoạt động ẩn ở phía bên trái màn hình (và các phần tử được sao chép khi thêm widget).
Julien

Câu trả lời:


12

Tin tốt,

Tôi đã sửa nó.

Xin lỗi vì đã bỏ lỡ ý chính của bạn trong bình luận ban đầu của tôi và cho bạn một câu trả lời mà bạn đã thực hiện. Điều đó sẽ dạy tôi trả lời trên điện thoại khi đi tàu!

Việc bạn sử dụng ajaxstop là chính xác. Hầu hết các phần mềm hoạt động chính xác, bạn có thể thấy các kiểu css đang được khởi tạo và các thay đổi trong DOM.

Vấn đề nằm ở thực tế với bộ chọn của bạn.

Điều này là do nội dung widget không được tải thông qua ajax, trên thực tế, nó sao chép nó từ cột bên trái nơi nó bị ẩn và sau đó thực hiện cuộc gọi ajax để lưu vị trí của widget trong cột bên phải. Điều này giải thích tại sao ajaxstop hoạt động một điều trị, thậm chí nội dung được cho là được nhân bản. Tuy nhiên, vì có một phiên bản ẩn của tiện ích trong cột bên trái, nên JS của bạn đang bắt đầu từ đó. Như vậy khi bạn kéo nó vào cột bên tay phải, bạn sẽ nhận được một bản sao được xáo trộn của tiện ích ẩn.

Vì vậy, bạn cần phải chọn một ở phía bên trái. Dưới đây là mã sửa:

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

Chúa ơi, tôi cần phải đi kiểm tra điều này <3
Tom J Nowell

Giải pháp rất thanh lịch cho một cơn đau đầu lớn!
bosco

3
Tôi sẽ khuyên bạn không nên chạy trên mọi sự kiện 'ajaxStop' và thay vào đó hãy đề xuất sử dụng trên các sự kiện 'được thêm tiện ích' cũng như 'cập nhật tiện ích'.
Tyrun

16

Như @ aaron-holbrook đã nhận xét một cách tiếp cận sạch hơn sẽ được thực hiện:

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

Trong nhiều trường hợp, bạn cũng sẽ muốn chạy JS khi tải trang cũng như khi các widget được cập nhật. Bạn có thể làm như vậy.

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

Chỉ cần dán vào đây để tham khảo là câu trả lời dễ dàng hơn nhiều để tìm thấy những bình luận đó


2
có lẽ nên sử dụng jQuery thay vì $
Mark Kaplun
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.