11548 sujets

JavaScript, DOM et API Web HTML5

Pages :
Salut,

Je charge dynamiquement des fichiers javascript externes en fonction des besoins de l'utilisateur, avec le DOM.
Mon problème c'est que je n'arrive pas à accéder aux variables et fonctions de ces fichiers, à partir de scripts déjà existants dans la page.
Apparemment c'est un problème de scope mais je n'arrive pas à trouver la solution, j'implore donc votre aide Smiley cligne

Merci !

PS : pour info l'import fonctionne parfaitement, ainsi que les scripts contenus, c'est juste un problème de "visibilité" entre les scripts (statiques et dynamiques).
Comment t'y prends-tu pour importer tes scripts ? Parce qu'il y a plusieurs façons de faire et toutes ne sont pas équivalentes.
Par exemple il y a des différences entre la visibilité des variables crées dans un eval, ou par la voie classique. Eval est en théorie considéré comme un bloc de fonction, donc toutes les variables crées avec le mot-clé var sont perdues, ainsi que tes fonctions suivant la façon dont elles ont été déclarées.
Hello,

Cela peut aussi dépendre de "l'ordre" dans lequel tes scripts sont insérés, et exécuté, entre ceux qui le sont directement dans la page et ceux qui tu insere par la suite avec window.onload (ou équivalent)
Hello,
QuentinC a écrit :
Eval est en théorie considéré comme un bloc de fonction, donc toutes les variables crées avec le mot-clé var sont perdues, ainsi que tes fonctions suivant la façon dont elles ont été déclarées.

Non. Smiley smile
J'ajoute le script à la balise head avec le DOM, au clic sur un bouton.

Le script externe contient ça :

alert('ok1');

var v = 'ok2';

function oui() {
	alert('oui');
}


J'ai bien alert('ok1') qui fonctionne, mais quand j'essaye d'accéder la variable v ou la fonction oui() à partir de la page html (par exemple dans par un script dans le body) il me dit que c'est undefined.
Modifié par jeyce (23 Oct 2007 - 04:31)
QuentinC a écrit :
Tu ne peux pas en dire plus s'il te plaît ?

Ben, il suffit d'un petit test. Smiley cligne
function fn() {
  eval("function fn2() {}\nvar i = 0;");
  alert(typeof fn2); // function
  alert(typeof i); // number
}
a écrit :
J'ai bien alert('ok1') qui fonctionne, mais quand j'essaye d'accéder la variable v ou la fonction oui() à partir de la page html (par exemple dans par un script dans le body) il me dit que c'est undefined.


Essaie de vérifier qu'ils s'executent bien dans le bon ordre, vu que normalement les définitions faites dans les fichiers js sont accesibles dans le reste de la page (encore heureux !)

Mets dans ton fichier .js un
alert("Un");

et dans le code de ta page, là où tu a besoin de ta variable un
alert("Deux");


C'est juste pour vérifier que Un arrive bien avant Deux
Julien Royer > Ah effectivement, autant pour moi, j'ai toujours cru que... désolé d'avoir dit une grosse connerie.
Voici l'exemple en ligne :
http://landoftrance.free.fr/loadjs/

Cette page charge "test.js" mais n'arrive pas à accéder à son contenu.


alert('ok1');

var v = 'ok2';

function oui() {
	alert('oui');
}

/*oui = function() {
	alert('oui');
}*/


Qui sera le plus fort à trouver la solution ? Smiley cligne

Merci.
Modifié par jeyce (27 Oct 2007 - 18:52)
jeyce a écrit :
Voici l'exemple en ligne :
http://landoftrance.free.fr/loadjs/

Cette page charge "test.js" mais n'arrive pas à accéder à son contenu.


alert('ok1');

var v = 'ok2';

function oui() {
	alert('oui');
}

/*oui = function() {
	alert('oui');
}*/


Qui sera le plus fort à trouver la solution ? Smiley cligne

Merci.

dans ta page tu fais :

loadScript("test.js", callback());
alert(v);
oui();


tu fais ton alert juste apres le chargement de ton script.
Mais comme le chargement de ton script est asynchrone avec le reste de la fonction, c'est normal que v n'existe pas.

verifie si ta fonction de callback est aussi valable pour les scripts.
jeyce a écrit :
Voici l'exemple en ligne :
http://landoftrance.free.fr/loadjs/

Cette page charge "test.js" mais n'arrive pas à accéder à son contenu.


alert('ok1');

var v = 'ok2';

function oui() {
	alert('oui');
}

/*oui = function() {
	alert('oui');
}*/


Qui sera le plus fort à trouver la solution ? Smiley cligne

Merci.

Yo,
Dans ta page, lorsque tu invoques loadScript, le deuxième paramètre callback(), ne sert strictement à rien étant donné que tu executes la fonction.

Dans un deuxième temps, tu fais
e.onload = callback
- chose qui ne marche pas IE, il faut utiliser onreadystatechange
Modifié par Shinuza (28 Oct 2007 - 03:11)
Gatsu35 > je vois pas trop ce que tu veux dire, si l'alert est exécutée, ça veut bien dire que le fichier est chargé.

Shinuza > je crois que t'as un peu fumé là Smiley cligne
Je te remets le code sous les yeux :

function loadScript(file, callback)
{
	var e = document.createElement("script");
	e.type="text/javascript";
	e.src = file;
	e.onload = callback;
	// IE 6 & 7
	e.onreadystatechange = function() {
		if (this.readyState == 'complete') {
			callback();
		}
	}
	document.getElementsByTagName("head")[0].appendChild(e);
}


Il y bien le onreadystatechange pour IE, et pour ta première réponse, la fonction callback() est passée en paramètre pour e.onload = callback donc ce paramètre n'est pas inutile.

Enfin bon pas de solution à l'horizon...
Modifié par jeyce (30 Oct 2007 - 03:43)
Modérateur
Salut, Smiley smile

Je ne te vois pas faire de requête pour accéder au contenu du fichier JS donc c'est normal. Smiley rolleyes

Je te laisse un exemple complet :

index.php
<?php

header('Content-type: text/html; charset=utf-8');

?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
                      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
	<head>
		<meta http-equiv="content-type" content="text/html; charset=utf-8" />
		<title>Exemple</title>
		<script type="text/javascript" src="script.js"></script>
	</head>
	<body>
	</body>
</html>


script.js
(function() { var Import = function() {}; var Ip = Import.prototype = {

	'tempoXHR': 2500,
	
	connect: function(oElem, sEvType, fn, bCapture) {
		return document.addEventListener ?
			oElem.addEventListener(sEvType, fn, bCapture):
			oElem.attachEvent ?
				oElem.attachEvent('on' + sEvType, fn):
				false;
	},

	bXHRSupport: (typeof XMLHttpRequest != "undefined"),

	bActiveXSupport: (window.ActiveXObject),

	aMSXML: ["Microsoft.XMLHTTP", "MSXML2.XMLHTTP", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP.4.0", "MSXML2.XMLHTTP.5.0", "MSXML2.XMLHTTP.6.0", "MSXML2.XMLHTTP.7.0"],

	createXHR: function() {
		if(Ip.bXHRSupport)
			return new XMLHttpRequest;
		else if(Ip.bActiveXSupport) {
			var iI = Ip.aMSXML.length;
			do {
				try {
					return new ActiveXObject(Ip.aMSXML[--iI]);
				}
				catch(oError) { }
			} while(iI > 0);
			throw new Error("L'objet oXHR n'a pas été créé");
		}
	},

	getXHR: function(oReq) {
		var oXHR = Ip.createXHR();
		var oData = oReq;
		oXHR.open(oData['method'], oData['url'], true);
		var oTimer = setTimeout(
			function() {
				if(oXHR)
					return oXHR.abort();
			},
			Ip.tempoXHR
		);
		oXHR.onreadystatechange = function() {
			if(oXHR.readyState == 4)
				if(oXHR.status && /200|304/.test(oXHR.status)) {
					clearTimeout(oTimer);
					oData['response'] = oData['response'] == 'xml' ?
						oXHR.responseXML:
						oXHR.responseText;
					if(oData['callback'])
						oData['callback'].call(Ip, oData['response']);
				}
		}
		oXHR.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
		return oXHR.send(null);
	},

	insertJS: function(oResponse) {
		var oScript = document.createElement('script');
		oScript.setAttribute('type', 'text/javascript');
		oScript.text = oResponse;
		document.getElementsByTagName('head')[0].appendChild(oScript);
		return Ip.testImport();
	},

	testImport: function() {
		maFonctionJS();
		alert(maFonctionJS.msg);
	},

	loadFile: function(sFile) {
		return Ip.getXHR(
			{
				'url': sFile,
				'method': 'get',
				'response': 'js',
				'callback': Ip.insertJS
			}
		);
	},

	init: function(sFile) {
		return Ip.connect(
			window,
			'load',
			function() {
				return Ip.loadFile(sFile);
			},
			false
		);
	}
};

var loadJSFile = new Import;
loadJSFile.init('test.js');

})();


test.js
function maFonctionJS() {
	maFonctionJS.msg = 'cool !';
	return alert('Script chargé');
}

Modifié par koala64 (30 Oct 2007 - 09:52)
jeyce a écrit :
Gatsu35 > je vois pas trop ce que tu veux dire, si l'alert est exécutée, ça veut bien dire que le fichier est chargé.

Shinuza > je crois que t'as un peu fumé là Smiley cligne
Je te remets le code sous les yeux :

function loadScript(file, callback)
{
	var e = document.createElement("script");
	e.type="text/javascript";
	e.src = file;
	e.onload = callback;
	// IE 6 & 7
	e.onreadystatechange = function() {
		if (this.readyState == 'complete') {
			callback();
		}
	}
	document.getElementsByTagName("head")[0].appendChild(e);
}


Il y bien le onreadystatechange pour IE, et pour ta première réponse, la fonction callback() est passée en paramètre pour e.onload = callback donc ce paramètre n'est pas inutile.

Enfin bon pas de solution à l'horizon...

Alors non j'ai pas fumé, et oui je vais te remettre ton propre code sous les yeux :


<script type="text/javascript">
	loadScript("test.js", callback()); // Ici callback est executé, le deuxième paramètre est d'une inutilité des plus avancée
	alert(v);
	oui();
</script>
Tu n'as peut-être pas compris ce qu'il a voulu dire mais cette ligne :
loadScript("test.js", callback()); // Ici callback est executé, le deuxième paramètre est d'une inutilité des plus avancée 

ne fait effectivement pas ce qu'il faut : enlève les parenthèses après callback, ça devrait aller mieux Smiley lol . Parce que sinon ta fonction est appelée immédiatement, pas au moment où tu voudrais qu'elle le soit.
QuentinC a écrit :
Tu n'as peut-être pas compris ce qu'il a voulu dire mais cette ligne :
loadScript("test.js", callback()); // Ici callback est executé, le deuxième paramètre est d'une inutilité des plus avancée

ne fait effectivement pas ce qu'il faut : enlève les parenthèses après callback, ça devrait aller mieux Smiley lol . Parce que sinon ta fonction est appelée immédiatement, pas au moment où tu voudrais qu'elle le soit.

Dans l'absolu ça peut servir, faut-il que la fonction renvoit quelque chose Smiley confus
Modérateur
Tiens ?! Smiley confuse En effet, on peut se passer d'Ajax... Je ne savais pas. Smiley sweatdrop
(function() { var Import = function() {}; var Ip = Import.prototype = {
	
	connect: function(oElem, sEvType, fn, bCapture) {
		return document.addEventListener ?
			oElem.addEventListener(sEvType, fn, bCapture):
			oElem.attachEvent ?
				oElem.attachEvent('on' + sEvType, fn):
				false;
	},

	insertJS: function(sSrc) {
		var oScript = document.createElement('script');
		oScript.type = 'text/javascript';
		oScript.src = sSrc;
		document.getElementsByTagName('head')[0].appendChild(oScript);
		if(window.addEventListener)
			oScript.onload = Ip.testImport;
		else
			oScript.onreadystatechange = function() {
				try {
					return Ip.testImport();
				} catch(e) {};
			}
	},

	testImport: function() {
		maFonctionJS();
		alert(maFonctionJS.msg);
	},

	init: function(sFile) {
		return Ip.connect( window, 'load', function() { Ip.insertJS(sFile); }, false);
	}
};

var loadJSFile = new Import;
loadJSFile.init('test.js');

})();
PS : readyState n'est pas géré sur cet élément; il faut passer par un try...catch

PS2 : Ce serait bien de voir comment ça se comporte sur d'autres navigateurs que Firefox ou IE... Smiley rolleyes
Modifié par koala64 (30 Oct 2007 - 11:33)
Pages :