11548 sujets

JavaScript, DOM et API Web HTML5

bonjour,
j'ai une fonction (nommée tree_toggle) qui effectue un xmlhttprequest pour remplir un div dans la page principale
cette page ouvre un popup et j'aimerais que lors d'un action dans le popup (ici dans le onclick d'un bouton du popup) cela lance la fonction tree_toggle dans la page principale.

le probleme qui se pose : la fonction est bien lancée mais j'obtiens une erreur javax :
ERROR !
URL = /obj/node/?id=4
Error = [Exception... "Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIXMLHttpRequest.status]" nsresult: "0x80040111 (NS_ERROR_NOT_AVAILABLE)" location: "JS frame ::  http://10.42.0.1:2000/xml.js  :: load_cb :: line 53" data: no]


après des recherches sur google, il semble que cela soit du au contexte d'execution dans lequel mon script est lancé :
la page principale est a la racine du serveur web, le popup a /obj/popup/ et la zone a chargée /obj/node/ donc si la fonction est executée par la page principale (l'utilisateur clique sur un bouton dans celle ci) ca marche, mais si ca viens du popup cela ne marche pas.

Quelqu'un aurait une idée ? ou meme la solution ? Smiley smile
Modifié par Cactusbone (12 Jul 2005 - 16:11)
ouais c une appli un peu complexe donc je met pas tout mais voila un bout du javascript

function ajax(url, fonction) {
	var xmlhttp=false;
	/*@cc_on @*/
	/*@if (@_jscript_version >= 5)
	// JScript gives us Conditional compilation, we can cope with old IE versions.
	// and security blocked creation of the objects.
	 try {
		xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
	 } catch (e) {
		try {
		 xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
		} catch (E) {
		 xmlhttp = false;
		}
	 }
	@end @*/
	if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
		xmlhttp = new XMLHttpRequest();
	}

	try {
		xmlhttp.open("GET", url);

		if (fonction != null) {
			xmlhttp.onreadystatechange = function() {
				if (xmlhttp.readyState == 4) {
					fonction(xmlhttp);
				}
			};
		}
	
		xmlhttp.send(null);
	} catch (e) {}

	if (fonction == null)
		return false;
}

function load(url, element_id, display) {
	var element = document.getElementById(element_id);
	if (display)
		element.style.display = display;
	element.innerHTML = '<div class="loading">Loading ...</div>';
	
	function load_cb(xmlhttp){
		try {
			if (xmlhttp.status == 200) {
				element.innerHTML = xmlhttp.responseText;
				xmlhttp = null;
			}
			else {
				element.innerHTML = '<div class="loading">' +
					'ERROR !<br>' +  
					'Status = ' + xmlhttp.status + '<br>' +  
					'URL = ' + url + '<br>' +  
					'Answer = ' + xmlhttp.responseText + '<br>' +  
					'</div>';
			}
		} catch (e) {element.innerHTML ='<div class="loading">' +
					'ERROR !<br>' +  
					'URL = ' + url + '<br>' +  
					'Error = ' + e + '<br>' +  
					'</div>';}
	}
	ajax(url, load_cb);
}
function tree_toggle(id, url) {
	open_obj = document.getElementById(id + '_open');
	close_obj = document.getElementById(id + '_close');
	child_obj = document.getElementById(id + '_child');
	if (open_obj.style.display != 'none') {
		load(url, id + '_child', 'block');
		if (child_obj.innerHTML == null || child_obj.innerHTML == '') {
			close_obj.style.background = 'none';		
			open_obj.style.background = 'none';
		} else {
			open_obj.style.display = 'none';		
			close_obj.style.display = 'inline';
		}
	}  else {
		close_obj.style.display = 'none';
		open_obj.style.display = 'inline';
		child_obj.style.display = 'none';
	}		
}

function tree_toggle_by_id(id) {
	if(id=="")
		return;

	var d = true;
	if(window.opener) {
		if(window.opener.document.getElementById(id)) {
			d = false;
			window.opener.tree_toggle_by_id(id);
		}
	}

	if(d==true)
	{
		elem = document.getElementById(id);
		if(elem) {
			var txt = elem.firstChild.firstChild.href;
			if(txt.indexOf("javascript:",0)==0)
				txt = txt.substring(11, txt.length);
			if(txt.indexOf("tree_toggle('",0)==0) {
				txt = txt.substring(13, txt.length-2);
				vars = txt.split("','");
				tree_toggle(vars[0],unescape(vars[1]));
				tree_toggle(vars[0],unescape(vars[1]));
			}
			else
				eval(txt);
		}
	}
}


le popup fait un tree_toggle_by_id avec l'id qui va bien, et le test au sein de la fenetre principale aussi. sauf que dans le 1er cas ca marche pas et dans le 2eme ca marche.
Re,

d'abord,


 if (fonction != null) {
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {
fonction(xmlhttp);
}


je testerais la validité de la fonction de callback comme ceci


 if (typeof fonction == "function") {


sinon je crois comprendre que tu veuilles juste activer une fonction de la fenêtre mère. Dans ce cas fais une fonction de callback dans la popup qui appellera la fonction de la fenêtre mère.

Enfin, ça demande de regarder de plus près ^^
merci pour la validation, je le met tout de suite Smiley smile

sinon, la fonction tree_toggle_by_id(id) fait deja office de fonction de callback ... si elle est dans le popup elle apelle window.opener.tree_toggle_by_id(id);

moi ce qu'il me faut c'est faire en sorte que la fonction soit executée dans le contexte javascript lié a la fenetre principale ... mais je ne suis pas sur que ca soit le cas ou pas actuellement ...
Modifié par Cactusbone (07 Jul 2005 - 13:31)
non, ce n'est pas le meme probleme, mes fonctions sont bien executées et je n'ai pas de soucis pour contacter la fenetre mère ou le popup. le probleme est que xmlhttp n'as pas accès (sous firefox) au domaine complet mais seulement aux sous domaines, et l'url du popup est dans un sous domaine, l'url que xmlhttp tente de charger est dans un autre sous domaine , et ma page principale est a la racine du domaine, il faudrais que le js qu'execute la popup utilise le contexte d'execution de la fenetre principale car c'est visiblement ce qui génère l'erreur xmlhttp.
j'ai fini par reussir a le faire fonctionner : il faut faire une closure dans la page principale qui appelle une fonction settimeout :

function tree_toggle_delayed(id) {
	setTimeout("tree_toggle_by_id('"+id+"')",500);
	return(true);
}
var tree_toggle_by_id_closure;
function createClosures() {
	tree_toggle_by_id_closure = tree_toggle_delayed;
}

window.onload = createClosures;


et la fonction tree_toggle_by_id est maintenant :

function tree_toggle_by_id(id) {
	if(id=="")
		return;

	var d = true;
	if(window.opener) {
		if(window.opener.document.getElementById(id)) {
			d = false;
			window.opener.tree_toggle_by_id_closure(id);
		}
	}
...
}


merci a tous pour votre aide Smiley cligne
si l'on ne met pas le timeout ca ne marche pas
la closure permet en théorie d'associer le contexte d'execution courant a une fonction. ce qui permet d'utiliser ce contexte plus tard ... mais visiblement ca ne fonctionne bien qu'avec le settimeout Smiley cligne