2010-11-13 9 views
7

Estoy escribiendo un script que necesita agregar elementos DOM a la página, en el lugar donde se encuentra el script (enfoque tipo widget). ¿Cuál es la mejor manera de hacer esto?Método recomendado para ubicar el script actual?

Estas son las técnicas que estoy considerando:

  1. incluir un elemento con un id = "localizador" justo encima de la secuencia de comandos. Problemas:
    • que no me gusta el marcado adicional
    • Si reutilizar el widget en la página, varios elementos tendrán el mismo id "localizador". Estaba pensando en agregar una línea en la secuencia de comandos para eliminar la identificación una vez utilizada, pero aún así ...
  2. Agregue una identificación a la secuencia de comandos. Problemas:
    • a pesar de que parece que funciona, el atributo id no es válido para el elemento de script
    • mismo problema que el anterior, varios elementos tendrán el mismo id si volver a utilizar el script en la página.
  3. Use getElementsByTagName ("script") y elija el último elemento. Esto me ha funcionado hasta ahora, parece un poco pesado y no estoy seguro de si es confiable (pensando en los guiones diferidos)
  4. document.write: no es elegante, pero parece hacer el trabajo.

  5. [Editar] Sobre la base de la respuesta de idealmachine, estoy pensando en una opción más:

    • Incluir en la etiqueta script un atributo, por ejemplo meta = "tabify".
    • Use getElementsByTagName ("script") para obtener todos los scripts.
    • Pasa por las secuencias de comandos y marca el objetivo = "tabify" para encontrar mi script.
    • Elimina el atributo objetivo en caso de que haya otro widget en la página.
  6. [Editar] Otra idea, también inspirada en las respuestas hasta el momento:

    • Uso getElementsByTagName ("script") para obtener todos los guiones.
    • Pasa por las secuencias de comandos y comprueba innerHTML para encontrar mi secuencia de comandos.
    • Al final del script, elimine la etiqueta del script en caso de que haya otro widget en la página.

Respuesta

0

me acaba de encontrar otro método que parece responder a mi pregunta:

How to access parent Iframe from javascript

Inserción de la secuencia de comandos en un iframe permite localizar en cualquier momento, ya que el script siempre mantiene una referencia a su propia ventana.

Voto este el mejor enfoque, ya que siempre funcionará sin importar cuántas veces agregue el script a la página (widget de opinión). Eres bienvenido para comentar

Lo que me llevó a considerar iframes en primer lugar fue un experimento que hice para construir un gadget de Google.

1

He trabajado para OnlyWire que proporciona, como su servicio principal, un widget para poner en su sitio.

Utilizamos el truco var scripts = document.getElementsByTagName("script"); var thisScript = scripts[scripts.length - 1]; y parece funcionar bastante bien. Luego usamos thisScript.parentNode.insertBefore(ga, thisScript); para insertar lo que queramos antes, en el árbol DOM.

No estoy seguro de entender por qué considera que esta es una solución "pesada" ... no implica iteración, es una solución pura de navegador cruzado que se integra perfectamente.

+0

bien, "pesado" en comparación con una directa getElementById. Pero entiendo tu punto, no es gran cosa. – Christophe

1

Si suelta una etiqueta <script> en <div class="mywidget">, está agregando algo a la marca. Personalmente, prefiero este último ya que el script en sí mismo solo se agrega una vez. Demasiadas secuencias de comandos en el cuerpo de la página pueden ralentizar el tiempo de carga de la página.

Pero si necesita agregar la etiqueta de script donde va a estar el widget, no veo cuál es el problema con el uso de document.write() para colocar un div.

+2

Lo que sucede es que 'document.write()' solo "funciona" cuando la página aún se está cargando. Si realiza un 'document.write()' en un script que anexa a la página después de la carga (... o algo, no está seguro del punto de inflexión exacto), el efecto es como si la página actual se hubiera borrado justo antes a esa escritura, con el resultado de una página que contiene * solo * el código que se acaba de escribir en el documento. –

+0

Bueno, prefiero el otro camino. No he encontrado lo que describes. En la mayoría de los navegadores bajo las circunstancias que he visto, dejará de cargar otras cosas hasta que cargue javascript, por lo que se ralentiza el tiempo de carga. – aptwebapps

+0

Otra preocupación que tengo con document.write: ¿pueden los elementos incluidos de esta manera ser manipulados por métodos DOM, al igual que los elementos estándar? ¿O hay alguna restricción? – Christophe

1

O bien document.write o seleccionando el último elemento de script funcionarán sincrónicamente scripts cargados en la mayoría de las páginas web. Sin embargo, hay algunas opciones que se me ocurre que no se tuvo en cuenta para permitir la carga asincrónica:

  • Adición de un div con class="Locator" antes del script. Las clases HTML tienen la ventaja de que los duplicados son no inválidos. Por supuesto, para manejar el caso del widget múltiple, querrá cambiar el nombre de la clase del elemento cuando termine de agregar los elementos HTML para que no los agregue dos veces. (Tenga en cuenta que también es posible que un elemento a ser miembro de múltiples clases, sino que es una lista separada por espacios.)

  • Comprobación del src de cada elemento de script puede asegurar que el código de seguimiento (por ejemplo Google Analytics código de seguimiento heredado) y otras secuencias de comandos cargadas al final de la página no impedirán que la secuencia de comandos funcione correctamente cuando se utiliza la carga asincrónica. De nuevo, para manejar el caso del widget múltiple, es posible que deba eliminar los elementos del script cuando finalice con ellos (, es decir, cuando se haya agregado el código deseado a la página).


Un comentario final haré (aunque es posible que ya ser conscientes de ello) es que cuando la codificación de un widget, necesidad a declarar todas las variables utilizando var y encierran todo el código dentro de : (JSLint puede ayudar a comprobar esto)

(function(){ 
    ... 
})(); 

esto se ha llamado una "función de aplicación directa" y se asegurará de que las variables utilizadas en el script no interfieran con el resto de la página web.

+0

Uso las funciones autoejecutables. Eliminar el script no es una opción ya que el widget incluye interacción. Pensé en usar la clase, pero agarrar el elemento no es tan sencillo como con una identificación. Me gusta la idea de verificar el src u otro atributo de la etiqueta del script, esto podría ayudar a identificar el correcto. – Christophe

+0

@Christophe: no me refiero en realidad a eliminar el script en sí. Una vez que el script ya se ha cargado y ejecutado, es seguro eliminar el elemento del script que lo cargó (por supuesto, después de agregar el div que contendrá el código generado dinámicamente). – PleaseStand

+0

Escribí "otro atributo de la etiqueta del script", pero luego me di cuenta de que no había muchos para elegir ... Bueno, tal vez podría hacer un tipo, como lo hizo Microsoft para el plugin de plantillas jQuery (text/x-jquery- tmpl). – Christophe

4

Esto funciona con múltiples copias del mismo código de la página, así como con el código introducido de forma dinámica:

<script type="text/javascript" class="to-run"> 
(function(self){ 
    if (self == window) { 
     var script = document.querySelector('script.to-run'); 
     script.className = ''; 
     Function(script.innerHTML).call(script); 
    } else { 
     // Do real stuff here. self refers to current script element. 
     console.log(1, self); 
    } 
})(this); 
</script> 
+0

Me preocupa el soporte del navegador (querySelector), pero aparte de esto, ¡parece muy interesante! Dame algo de tiempo para entenderlo completamente ;-). Otra preocupación que tengo es que querySelector podría devolver otra secuencia de comandos en la misma página, y la secuencia de comandos actual nunca se ejecutará. – Christophe

3

Fuera de la caja: document.currentScript(no soportado por IE)

+0

¡Gracias! Desafortunadamente no es compatible con todos los principales navegadores. – Christophe

+0

@Christophe Puede rellenarlo o utilizar un relleno policlonal preexistente, pero tiene razón. –

+0

Hice una búsqueda rápida pero no pude encontrar un poliufre que funcione con IE11. – Christophe

0

En muchos casos esta bien el trabajo (hud.js es el nombre de The Script):

var jsscript = document.getElementsByTagName("script"); 
for (var i = 0; i < jsscript.length; i++) { 
     var pattern = /hud.js/i; 
     if (pattern.test(jsscript[i].getAttribute("src"))) 
     { 
     var parser = document.createElement('a'); 
     parser.href = jsscript[i].getAttribute("src"); 
     host = parser.host; 
     } 

} 
0

también usted puede añadir el nombre de secuencia de comandos individuales dentro de ellos.

  • ya sea en el interior algunos js-script

    dataset['my_prefix_name'] = 'someScriptName' 
    
  • o en el interior HTML - en el guión < > etiqueta

    data-my_prefix_name='someScriptName' 
    

y próxima búsqueda apro piado uno por bucle más de document.scripts array:

... function(){ 
    for (var i = 0, n = document.scripts.length; i < n; i++) { 
     var prefix = document.scripts[i].dataset['my_prefix_name'] 
     if (prefix == 'whatYouNeed') 
      return prefix 
    } 
} 
Cuestiones relacionadas