02 dicembre 2008

Recuperare un oggetto Javascript senza problemi (in popup, frame, etc..)

Chiunque ami o odi Javascript può trovarsi ad un problema del tipo : "Litigare con la gerarchia degli oggetti oggetti del documento per poterne individuare uno" come ad esempio window.parent.window.opener.document..... A volte questo lavoro è talmente arduo da indurre il programmatore a ridurre la propria pazienza in brandelli.
La perdita di tempo può notevolmente aumentare quando ad esempio si utilizzano popup o frame.
Però una soluzione esiste....

Il sottoscritto non adora dover incorrere 2 volte nello stesso problema, così mi sono creato una funzione alla quale dare in pasto il nome dell'oggetto da recuperare e il nome del primo oggetto non nullo da cui far partire la nostra ricerca.
Ecco il codice :
function takeObject(){                                                             
objReceived = searchElement("window","objtoFind");
if (objReceived == null){
alert ('non trovato');
}else{
alert(objReceived.value);
}
}

var ArrayFramesToJump = ["onbeforeunload","onafterprint","top",
"location","parent","offscreenBuffering","frameElement",
"onerror","screen","event","clipboardData","onresize","defaultStatus",
"onblur","window","onload","onscroll","screenTop","onfocus","Option",
"length","onbeforeprint","frames","self","clientInformation","external",
"screenLeft","opener","onunload","document","closed","history","Image",
"navigator","status","onhelp","name"];

String.prototype.endsWith = function(str)
{return (this.match(str+"$")==str)}

Array.prototype.contains = function (element) {
for (var i = 0; i < this.length; i++) {
if (this[i] == element) {
return true;
}
}
return false;
}


function searchElement (lastNotNull,divName){

eval ("var last = "+lastNotNull+";");
// DEBUG : alert(lastNotNull);
if (last){
// document (non posso concatenare 2 document)
if (!lastNotNull.endsWith("document")){
eval("var docum = "+lastNotNull+".document;");
if (docum!=null){
if (docum.getElementById(divName)!=null){
alert (lastNotNull+".document.getElementById('"+divName+"')");
return docum.getElementById(divName);
}else{
var objReceived = searchElement(lastNotNull+".document",divName);
if (objReceived !=null){
return objReceived;
}
}
}
}
// parent (evito di avere 2 parent per non incorrere in problemi ma
// potenzialmente è possibile che ce ne siano 2)
eval("var par = "+lastNotNull+".parent;");
if (lastNotNull.indexOf('parent') == -1){
if (par!=null){
var objReceived = searchElement(lastNotNull+".parent",divName);
if (objReceived !=null){
return objReceived;
}
}
}
// window (non posso concatenare 2 window
eval("var windo= "+lastNotNull+".window;");
if (!lastNotNull.endsWith("window")){
if (windo!=null){
var objReceived = searchElement(lastNotNull+".window",divName);
if (objReceived !=null){
return objReceived;
}
}
}
// opener
eval("var ope= "+lastNotNull+".opener;");
if (ope!=null){
var objReceived = searchElement(lastNotNull+".opener",divName);
if (objReceived !=null){
return objReceived;
}
}

// tutti i frame fratelli
if (lastNotNull.endsWith("parent")){
eval("var frameset= "+lastNotNull+".frames;");
if (frameset){
// se esiste il frameset
for (var framecurr in frameset) {
if (!ArrayFramesToJump.contains(framecurr)){
var currframeObj = frameset[framecurr];
if (currframeObj!=null){
// se ho intercettato il frame
var objReceived = searchElement(lastNotNull+".frames['"+framecurr+"']",divName);
if (objReceived !=null){
return objReceived;
}
}
}
}
}
}
}
return null;
}

// richiamo la funzione
takeObject();


Come si può notare la funzione esegue ricorsivamente la ricerca dell'oggetto, senza ingappare in loop infiniti visto che in Javascript ad esempio è possibile utilizzare window.window oppure window.parent.window.parent.
Il risultato è il riferimento all'oggetto nel caso venga trovato o null per un esito negativo della ricerca.
Spero sia utile a farvi risparmiare un sacco di tempo.

Nessun commento: