una script salir parar funcion detener destruir como cerrar anular javascript ajax wordpress listener dom-events

javascript - salir - Fuerce el reinicio de todos(scripts/funciones) en un contenido ajaxed



salir de un if en javascript (7)

Esto es lo que puedes probar:

La mayoría de los guiones, como mampostería o Google Map, están configurados para volver a iniciarse en el cambio de tamaño de la ventana. Por lo tanto, si activa el evento de cambio de tamaño después de completar ajax, ayudará a volver a disparar esos scripts automáticamente.

Pruebe el siguiente código -

$( document ).ajaxComplete( function() { $( window ).trigger(''resize''); } );

Esto obligará a los scripts a volver a iniciarse una vez que se haya completado ajax, ya que ahora activará el evento de cambio de tamaño una vez que se haya cargado el contenido.

tl; dr

Uso ajax para buscar contenido nuevo. El contenido se busca y se agrega a la página. Sin embargo, las secuencias de comandos no "vuelven a activarse" porque sus llamadas están fuera del div ajaxed.

Los scripts se cargan y disparan sin problemas en la carga de la página inicial, pero no cuando agrego contenido nuevo a través de ajax. No recibo errores de consola y no hay problemas si visito la URL directamente.

Relacionado:

  1. Forzar secuencia de comandos para ejecutar en la página AJAX cargada : se relaciona con un script específico. Quiero arreglar (refinar) todos los scripts, incluidos los dinámicos de las aplicaciones Cloudflare
  2. Uso de script jQuery con Ajax en Wordpress : igual que en el caso anterior, esto se relaciona solo con un script específico
  3. contenido cargado de ajax, el script no se está ejecutando

Introducción:

Uso Ajaxify WordPress Site (AWS) en un sitio web de WordPress.

El complemento le permite seleccionar un div por su id y luego obtiene nuevo contenido dentro de ese div usando ajax

marcado HTML

<html> <head></head> <body> <div id="page"> <header></header> <main id="ajax"> <!-- This is what I want to ajaxify --> <div class="container"> main page content </div> </main> <!-- end of ajaxfied content --> <footer></footer> </div> <!-- #page --> </body> </html>

Problema

El complemento funciona y obtengo contenido nuevo cargado y con estilo, pero hay un problema. Algunos de los scripts de mi página y las llamadas a funciones están fuera del div en el que uso ajax. Tengo dos ejemplos

1- La mampostería se carga y se llama en el <footer>

<html> <head></head> <body> <div id="page"> <header></header> <main id="ajax"> <!-- This is what I want to ajaxify --> <div class="container"> main page content </div> </main> <!-- end of ajaxfied content --> <footer></footer> <!-- Masonry script is loaded and called here --> </div> <!-- #page --> </body> </html>

2- La llamada a Google maps está en <head>

<html> <head></head> <!-- Google maps is called here --> <body> <div id="page"> <header></header> <main id="ajax"> <!-- This is what I want to ajaxify --> <div class="container"> main page content </div> </main> <!-- end of ajaxfied content --> <footer></footer> </div> <!-- #page --> </body> </html>

Estos son solo dos ejemplos . Hay otros en otros lugares. Como puede ver, tales scripts no se volverán a llamar ya que lo único que se recarga en la página es <main id="ajax"> . Si bien el nuevo contenido dentro de <main> está allí , algunos de los scripts necesarios para representarlo correctamente no se vuelven a llamar y, por lo tanto, termino con elementos faltantes / diseño roto.

No soy el único que ha enfrentado este problema; un vistazo rápido al foro de soporte del complemento en wordpress.org muestra que este problema es común.

Nota: No intentaría solucionar esto si el complemento tuviera muchos otros problemas. Funciona para mí, solo necesito los scripts para volver a disparar.

La respuesta oficial es que es posible volver a cargar / volver a generar scripts agregando lo siguiente en los archivos php del complemento:

$.getScript(rootUrl + ''PATH TO SCRIPT'');

Que funciona Funciona bien. por ejemplo si agrego

$.getScript(rootUrl + ''/Assets/masonry.js'');

Luego las llamadas a la función de mampostería se vuelven a disparar cuando se recupera el contenido ajax incluso si masonry.js se carga fuera del div ajaxed

Los remito a los archivos del plugin en github para obtener más claridad sobre lo que realmente hace la corrección (no puedo entender lo que sucede cuando se usa $.getScript )

En resumen

La solución oficial funciona bien si tiene entre 3 y 4 scripts que deben volver a activarse en un contenido ajax.

Esto no funciona para mi objetivo porque

  1. es muy rígido y está codificado
  2. Algunos de los scripts se agregan dinámicamente a la página a través de aplicaciones Cloudflare

Una posible solución podría implicar agregar un evento que imita el desencadenador que hace que los scripts se disparen en la parte inferior del div ajaxed

Pregunta:

¿Cómo fuerzo a todos los scripts, incluidos los dinámicamente agregados, para volver a disparar cuando solo una determinada parte de la página se ha vuelto a cargar mediante ajax?

Notas:

  1. Estoy tratando de evitar llamar guiones uno por uno, ya que eso requeriría conocimiento de sus llamadas de antemano. Probablemente estoy hablando por encima de mi cabeza, pero ...

    Estoy intentando imitar la carga de la página y / o los eventos listos para el documento, en los que se activan la mayoría de los scripts condicionales ( corríjanme si estoy equivocado ) al final de <main> en mi html cuando se agrega nuevo contenido ajax pero sin afectando el documento cuando la página se carga mediante el uso de la url directamente ... o cualquier otro enfoque similar.

  2. Solo por un poco de contexto, aquí hay una lista de algunos de los oyentes del evento en la página mientras el complemento está apagado . Sé que hay cosas allí que no tendré que disparar. Acabo de agregar esto para referencia. Además, tenga en cuenta que esta es una muestra tomada de una de las páginas. otras páginas pueden diferir

DOMContentLoaded beforeunload blur click focus focusin focusout hashchange keydown keyup load message mousedown mousemove mouseout mouseover mouseup mousewheel orientationchange readystatechange resize scroll submit touchscreen unload


La solución que elija aquí dependerá de cómo se inicialicen los scripts. Hay un par de posibilidades comunes:

  1. Las acciones del script se evocan inmediatamente después de la carga del script. En este caso, el script podría verse más o menos así:

    (function() { console.log(''Running script...''); })();

  2. Las acciones del guión se evocan en respuesta a algún evento (como los eventos de preparación de documentos (JQuery) o eventos de carga de ventanas (JavaScript)). En este caso, el script podría verse más o menos así:

    $(window).on(''load'', function() { console.log(''Running script...''); });

Algunas opciones para estas dos posibilidades se consideran a continuación.

Para scripts que se ejecutan inmediatamente al cargar

Una opción sería eliminar los elementos del <script> que desea desencadenar desde el DOM y luego volver a conectarlos. Con JQuery, podrías hacer

$(''script'').remove().appendTo(''html'');

Por supuesto, si el fragmento de arriba está en una etiqueta <script> , entonces creará un bucle infinito para separar y volver a unir constantemente todos los scripts. Además, puede haber algunos scripts que no desea volver a ejecutar. En este caso, puede agregar clases a los scripts para seleccionarlos positiva o negativamente. Por ejemplo,

// Positively select scripts with class ''reload-on-ajax'' $(''script.reload-on-ajax'').remove().appendTo(''html''); // Negatively select scripts with class ''no-reload'' $(''script'').not(''no-reload'').remove().appendTo(''html'')

En su caso, colocaría uno de los fragmentos anteriores en el controlador de eventos para la finalización de AJAX. El siguiente ejemplo utiliza un clic de botón en lugar de un evento de finalización de AJAX, pero el concepto es el mismo (tenga en cuenta que este ejemplo no funciona bien en el entorno limitado de , intente cargarlo como una página separada para obtener el mejor resultado) :

<html> <head></head> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <script class="reload-on-ajax"> console.log(''Script after head run.''); </script> <body> <button id="reload-scripts-button">Reload Scripts</button> </body> <script class="reload-on-ajax"> console.log(''Script after body run.''); </script> <script> $(''#reload-scripts-button'').click( () => $(''script.reload-on-ajax'').remove().appendTo(''html'') ); </script> </html>

Tenga en cuenta que si los scripts no están en línea (por ejemplo, se obtienen a través del atributo src ), entonces se volverán a cargar desde el servidor o se recuperarán del caché del navegador, dependiendo del navegador y la configuración. En este caso, el mejor enfoque es probablemente eliminar todos los <script> que operan en el contenido cargado con AJAX, y cargarlos / ejecutarlos a través de algo como la función getScript() JQuery desde un manejador de eventos de finalización AJAX. De esta forma, solo cargará / ejecutará los scripts una vez en el momento apropiado (es decir, después de cargar el contenido de AJAX):

// In AJAX success event handler $.getScript(''script1.js''); $.getScript(''script2.js'');

Un posible problema con ambas variantes de este enfoque es que la carga asincrónica del script está sujeta a restricciones de origen cruzado. Entonces, si los scripts están alojados en un dominio diferente y no se permiten las solicitudes de origen cruzado, no funcionará.

Para scripts que se ejecutan en respuesta a un evento

Si los scripts se activan en la carga de la ventana, entonces puede activar este evento:

$(window).trigger(''load'');

Desafortunadamente, si los propios guiones utilizan el evento listo para documentos de JQuery, entonces no estoy al tanto de una manera fácil de activarlo manualmente. También es posible que los scripts se ejecuten en respuesta a algún otro evento.

Obviamente, puedes combinar los enfoques anteriores según sea necesario. Y, como otros lo han mencionado, si hay algunas funciones de inicialización en los scripts a las que solo podría llamar, entonces esa es la forma más limpia.


Quizás arriesgado, pero deberías poder usar DOMSubtreeModified en tu elemento <main> para esto.

$(''#ajaxed'').bind(''DOMSubtreeModified'', function(){ //your reload code });

Luego, debería poder agregar todos sus scripts nuevamente en su área de recarga

var scripts = document.getElementsByTagName(''script''); for (var i=0;i<scripts.length;i++){ var src = scripts[i].src; var sTag = document.createElement(''script''); sTag.type = ''text/javascript''; sTag.src = src; $(''head'').append(sTag); }

Otra opción podría ser crear su propio oyente de eventos y tener el mismo código de recarga.

$(document).on(''ajaxContentLoaded'', function(){//same reload code});

Luego, podría activar un evento en el complemento una vez que el contenido haya sido actualizado.

$(document).trigger(''ajaxContentLoaded'');

O posiblemente una combinación de edición del complemento para activar un oyente y agregar a su base de código para volver a ejecutar cualquier cosa que considere necesario para volver a ejecutar ese oyente, en lugar de volver a cargar nada.

$(document).on(''ajaxContentLoaded'', function(){ //Javascript object re-initialization myObj.init(); //Just a portion of my Javascript? myObj.somePortion(); });


Respuesta corta: no es posible hacerlo de forma genérica. ¿Cómo debe saber su script qué eventos necesitan ser activados?

Respuesta más larga: es más como una pregunta estructural que programática. ¿Quién es responsable de la funcionalidad deseada? Tomemos la albañilería como ejemplo:

Masonry.js en sí mismo no escucha ningún evento. Necesita crear una instancia de mampostería por su cuenta (lo que probablemente se haga en domready en su plugin de Wordpress). Si habilita la opción de cambio de tamaño, agregará un detector al evento de cambio de tamaño. Pero lo que realmente desea es escuchar al "cambio de contenido DOM" (consulte https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver para obtener una posible solución). Como masonry.js no proporciona dicha función, tiene las siguientes opciones:

  1. Espere la implementación (o hágalo usted mismo) en masonry.js
  2. Espere la implementación (o hágalo usted mismo) en el plugin Wordpress de mampostería.
  3. Agregue la funcionalidad en otro lugar (su plantilla, su complemento ajax, etc.)
  4. 4.

Como puede ver, cada opción incluye algo de trabajo por hacer y este trabajo debe realizarse para cada secuencia de comandos que desee escuchar en los cambios DOM invocados por AJAX.


Si puede identificar una función de inicialización global o un bloque de código en sus scripts externos, puede echar un vistazo al evento ''ajaxComplete''. Puede poner este código en el encabezado de su página y poner las llamadas a la función de inicialización o los bloques de código dentro de la devolución de llamada ajaxComplete.

$(document).ajaxComplete(function(){ module1.init(); $(''#my_id'').module2_init({ foo : ''bar'', baz : 123 }); });

Cuando los scripts de los que está hablando no tienen funciones de inicialización expuestas tan fáciles de usar, sino que se inicializan en la carga de scripts, creo que no habrá un método listo para usar que funcione para todos los scripts.


Tuve este problema exacto al intentar usar ajax para volver a cargar una página con los estados del navegador y history.js, en wordpress. Encaré history.js directamente, en lugar de usar un complemento para hacer eso por mí.

Tenía toneladas de JS que necesitaban "volver a ejecutar" cada vez que se hacía clic en una nueva página. Para hacer esto, creé una función global en mi archivo javascript principal llamado global_scripts();

En primer lugar, asegúrese de que este archivo JS esté en cola después de todo lo demás, en su footer.php.

Eso podría verse más o menos así:

wp_enqueue_script(''ajax_js'', ''url/to/file.js'', ''google-maps'', 1, true);

Mi javascript que encueto está debajo.

jQuery(document).ready(function($) { // scripts that need to be called on every page load window.global_scripts = function(reload) { // Below are samples of the javascript I ran that I needed to re run. // This includes lazy image loading, paragraph truncation. /* I would put your masonry and google maps code in here. */ bLazy = new Blazy({ selector: ''.featured-image:not(.no-blazy), .blazy'', // all images offset: 100 }); /* truncate meeeee */ $(''.post-wrapper .post-info .dotdotdot'').dotdotdot({ watch: ''window'' }); } // call the method on initial page load (optional) //global_scripts(); });

Luego enganché en el JS que se ejecutaba cada vez que una página se cargaba con history.js y se llamaba global_scripts ();

Parece que el complemento que está utilizando también usa history.js. No lo he probado específicamente con tu complemento, pero puedes probar lo que publiqué a continuación (que es lo que uso en mi aplicación). Esto iría en el mismo archivo JS arriba.

History.Adapter.bind(window, ''statechange'', function() { global_scripts(); }

Mi código es un poco más complicado que lo que simplemente se pegó arriba. De hecho, compruebo el evento para determinar qué contenido se está cargando y cargo funciones específicas de JS basadas en eso. Permite un mayor control sobre lo que se vuelve a cargar.

nota: utilizo window.global_scripts cuando declaro la función porque tengo archivos JS separados que contienen este código. Puede elegir eliminar esto si están todos en el mismo.

nota2: me doy cuenta de que esta respuesta requiere saber exactamente qué se debe volver a cargar, por lo que ignora su última nota, que solicita que esto no requiera tal conocimiento. Sin embargo, puede ayudarte a encontrar tu respuesta.


Una solución podría ser duplicar todos los scripts ...

$(document).ajaxSuccess((event, xhr, settings) => { // check if the request is your reload content if(settings.url !== "myReloadedContentCall") { return; } return window .setTimeout(rejs, 100) ; }); function rejs() { const scripts = $(''script[src]''); // or, maybe alls but not child of #ajax // const scripts = $(''*:not(#ajax) script[src]''); Array .prototype .forEach .call(scripts, (script, index) => { const $script = $(script); const s = $(''<script />'', { src: $script.attr(''src'') }); // const s = $script.clone(); // should also work return s .insertAfter($script) .promise() .then(() => $script.remove()) // finally remove it ; }) ; }