type - ¿Utiliza javascript para inyectar referencias de scripts según sea necesario?
script type= text/javascript src= (6)
Tengo una función JS que de vez en cuando se puede usar en algunas páginas. Depende de otro archivo JS (swfObject.js), pero me gustaría evitar tener que incluir este archivo por todas partes, ya que es una solicitud desaprovechada la mayor parte del tiempo.
En cambio, me gustaría crear una función genérica que pueda inyectar una referencia de script en la página DOM según sea necesario, de modo que si se llama a esta función, buscará la secuencia de comandos y, si no existe, la cargará.
Estoy bastante seguro de que esto es posible (y no voy a usar document.write), pero antes de aventurarme en territorio inexplorado, ¿alguien ha hecho esto antes, y si es así, algún apuntador?
EDITAR: Ok, lo intenté, y funciona en IE6 y FF, todavía no he probado otros navegadores.
Aquí está mi código (Rev 2.0, ahora con devoluciones de llamada opcionales):
function loadJSInclude(scriptPath, callback)
{
var scriptNode = document.createElement(''SCRIPT'');
scriptNode.type = ''text/javascript'';
scriptNode.src = scriptPath;
var headNode = document.getElementsByTagName(''HEAD'');
if (headNode[0] != null)
headNode[0].appendChild(scriptNode);
if (callback != null)
{
scriptNode.onreadystagechange = callback;
scriptNode.onload = callback;
}
}
y en el método con una dependencia:
var callbackMethod = function ()
{
// Code to do after loading swfObject
}
// Include SWFObject if its needed
if (typeof(SWFObject) == ''undefined'')
loadJSInclude(''/js/swfObject.js'', callbackMethod);
else
calbackMethod();
¿Alguna sugerencia?
Si quieres tu código en la siguiente línea y quieres escribir algo como:
if (iNeedSomeMore){
Script.load("myBigCodeLibrary.js"); // includes code for myFancyMethod();
myFancyMethod(); // cool, no need for callbacks!
}
Existe una forma inteligente de inyectar dependencias de script sin necesidad de devoluciones de llamadas . Simplemente tiene que extraer el script mediante una solicitud AJAX sincrónica y evaluar el script a nivel global.
Si usa Prototype, el método Script.load se ve así:
var Script = {
_loadedScripts: [],
include: function(script){
// include script only once
if (this._loadedScripts.include(script)){
return false;
}
// request file synchronous
var code = new Ajax.Request(script, {
asynchronous: false, method: "GET",
evalJS: false, evalJSON: false
}).transport.responseText;
// eval code on global level
if (Prototype.Browser.IE) {
window.execScript(code);
} else if (Prototype.Browser.WebKit){
$$("head").first().insert(Object.extend(
new Element("script", {type: "text/javascript"}), {text: code}
));
} else {
window.eval(code);
}
// remember included script
this._loadedScripts.push(script);
}
};
Si está utilizando un marco de nivel superior como JQuery, puede verificar la función $.getScript(url, callback)
.
Verifique la utilidad YUI Loader. Es un javascript muy práctico y discreto para cargar scripts a pedido.
Aquí hay un enlace a un ejemplo que utiliza scripts que no son YUI:
http://developer.yahoo.com/yui/examples/yuiloader/yl-addmodule.html
Ninguno de estos métodos, incluido document.writing a script tag, funciona si el script en sí tiene un document.write.
Escribí un módulo simple que automatiza el trabajo de importar / incluir scripts de módulo en JavaScript. Pruébalo y por favor, ¡deja un comentario! :) Para una explicación detallada del código, consulte esta publicación en el blog: http://stamat.wordpress.com/2013/04/12/javascript-require-import-include-modules/
// ----- USAGE -----
require(''ivar.util.string'');
require(''ivar.net.*'');
require(''ivar/util/array.js'');
require(''http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js'');
ready(function(){
//do something when required scripts are loaded
});
//--------------------
var _rmod = _rmod || {}; //require module namespace
_rmod.LOADED = false;
_rmod.on_ready_fn_stack = [];
_rmod.libpath = '''';
_rmod.imported = {};
_rmod.loading = {
scripts: {},
length: 0
};
_rmod.findScriptPath = function(script_name) {
var script_elems = document.getElementsByTagName(''script'');
for (var i = 0; i < script_elems.length; i++) {
if (script_elems[i].src.endsWith(script_name)) {
var href = window.location.href;
href = href.substring(0, href.lastIndexOf(''/''));
var url = script_elems[i].src.substring(0, script_elems[i].length - script_name.length);
return url.substring(href.length+1, url.length);
}
}
return '''';
};
_rmod.libpath = _rmod.findScriptPath(''script.js''); //Path of your main script used to mark the root directory of your library, any library
_rmod.injectScript = function(script_name, uri, callback, prepare) {
if(!prepare)
prepare(script_name, uri);
var script_elem = document.createElement(''script'');
script_elem.type = ''text/javascript'';
script_elem.title = script_name;
script_elem.src = uri;
script_elem.async = true;
script_elem.defer = false;
if(!callback)
script_elem.onload = function() {
callback(script_name, uri);
};
document.getElementsByTagName(''head'')[0].appendChild(script_elem);
};
_rmod.requirePrepare = function(script_name, uri) {
_rmod.loading.scripts[script_name] = uri;
_rmod.loading.length++;
};
_rmod.requireCallback = function(script_name, uri) {
_rmod.loading.length--;
delete _rmod.loading.scripts[script_name];
_rmod.imported[script_name] = uri;
if(_rmod.loading.length == 0)
_rmod.onReady();
};
_rmod.onReady = function() {
if (!_rmod.LOADED) {
for (var i = 0; i < _rmod.on_ready_fn_stack.length; i++){
_rmod.on_ready_fn_stack[i]();
});
_rmod.LOADED = true;
}
};
_.rmod = namespaceToUri = function(script_name, url) {
var np = script_name.split(''.'');
if (np.getLast() === ''*'') {
np.pop();
np.push(''_all'');
}
if(!url)
url = '''';
script_name = np.join(''.'');
return url + np.join(''/'')+''.js'';
};
//you can rename based on your liking. I chose require, but it can be called include or anything else that is easy for you to remember or write, except import because it is reserved for future use.
var require = function(script_name) {
var uri = '''';
if (script_name.indexOf(''/'') > -1) {
uri = script_name;
var lastSlash = uri.lastIndexOf(''/'');
script_name = uri.substring(lastSlash+1, uri.length);
} else {
uri = _rmod.namespaceToUri(script_name, ivar._private.libpath);
}
if (!_rmod.loading.scripts.hasOwnProperty(script_name)
&& !_rmod.imported.hasOwnProperty(script_name)) {
_rmod.injectScript(script_name, uri,
_rmod.requireCallback,
_rmod.requirePrepare);
}
};
var ready = function(fn) {
_rmod.on_ready_fn_stack.push(fn);
};
Considera usar require.js . Esto podría necesitar una nueva revisión de su framework de frontend, pero vale la pena. Con require, puede hacer lo siguiente en su fileUsedOccasionally.js
:
define([''swfObject'', ''someOtherDependency''], function (swfObject, someOtherDependency) { // you can now use swfObject as a JS object! you can call it whatever you want // you''ll have to write a swfObject.js to wrap it with require // but that''s trivial });