Newsgroup: it.comp.lang.javascript
Titolo: Forzare il display di un div

Nell'implementazione di un set di API javascript ho utilizzato l'oggetto 
  XMLHttpRequest (per IE ActiveXObject("Microsoft.XMLHTTP") ) per la 
comunicazione con il server.
Alle volte questa comunicazione può essere un po' lenta quindi ho deciso 
di visualizzare box che dice di attendere il comletamento 
dell'operazione (altrimenti si mettono a cliaccare da tutte le parti).
Ho implementato il box con un div con position: fixed ... ect ect e vado 
ad impostare lo stile visualization a visible quando voglio visualizzarlo.
In tutto questo non ci sono problemi se non per il fatto che, pur 
ponendo lo stile a "visible" prima di eseguire la chiamata http tramite 
l'oggetto XMLHttpRequest, il div mi viene visualizzato in realtà quando 
l'esecuzione dello script è terminata e non appena posto a visible.
Il problema c'e' in mozilla ma non in IE (e va beh, sono implementazioni 
completamente diverse e non penso che questo tipo di comportamento sia 
stato standardizzato da W3C ma potrei sbagliarmi).
Ovviamente questo comportamento in Mozilla vanifica il mio sforzo di 
avvisare l'utente che deve attendere un po'.
Ora la domanda:
c'e' un modo per forzare il browser ad aggiornare la visualizzazione 
prima del termine dello script?
-Ema-

 prima del termine dello script?
Vado di frettissima e non so se ti ho capito bene.
Provo cosi' al volo: fai la chiamata asincrona (proprieta' async) e 
gestisci l'evento onreadystate (occhio che su ie ha piu' stati). La 
pagina rimane attiva e sotto il tuo controllo e quando il parsing del 
file xml e' completo fai quello che devi fare.


In effetti su questo punto sono stato un po' troppo "ermetico".
Quando dico che sto implementando delle API significa che sto 
implementando un set di oggetti e funzioni che devono fare una certa 
cosa e rispondere in un modo preciso. In particolare in questo caso devo 
implementare una funzione che prende dei parametri in input, interagisce 
con il server, ritorna il risultato del server al chiamante. Non è in 
mio potere cambiare il comportamento del chiamante ne tantomeno la 
specifica delle API visto che fanno parte di uno standard internazionale.
Altre idee?
Grazie comunque.
	-Ema-


Continuo a non capire. Da quel che leggo del tuo problema la mia 
parrebbe una soluzione.
Hai una API in js che utilizza chiamate xmlhttp. Se la chiamata e' 
sincrona tu non hai piu' il controllo del tuo programma finche' la 
risposta non e' stata ricevuta dal server e il parser non ha completato 
l'analisi del file.
Se la chiamata e' asincrona tu hai il controllo durante tutto il 
processo e ottieni quello che vuoi, o perlomeno quello che io ho capito.

 processo e ottieni quello che vuoi, o perlomeno quello che io ho capito.
La mia funzione semplificando un po' dovrebbe essere cosě:
function QualcosaGetParam( paramName ) {
   var httpRequest = CreaOggettoHttpRequest();
   MostraBoxAttesa();   // in IE Mostra subito in MOZ no
   httpRequest.open( "GET", 
"
http://misito/miapagina.pgp?parametro=
"+paramName, false );
   httpRequest.send( null );
   if( xmlhttp.status == 200 ) {
     try {
       var xmldoc = xmlhttp.responseXML;
       ....
       var value = xmldoc.getElementsByTagName("value").item(0).firstChild;
   }
   NascondiBoxAttesa();
   return value;
}
MostraBoxAttesa() non fa che mettere a visibile lo stile visibility di 
un div.
Il problema č che io devo tornare *value* in modo sincrono.
Ciao.
	-Ema-

 Forse non ho capito io ma mi pare di no.
Dunque io vedo due possibilita'.
La prima e' quella che ti dico dall'inizio: chiamata asincrona.
     - mostri il box di attesa
     - imposti il gestore di eventi
     - chiamata asincrona
     - quando il readystate ti comunica che tutto e' andato a buon fine
         - sparisce il div di attesa
         - fai quello che devi fare con il value
seconda possibilita' (che non mi piace affatto):
function pippo(){MostraBoxAttesa();setTimeout("faiChiamataXML()",1000);}

 Faser
Fai una open asincrona. A me server sincrona.
-Ema-

Andrea Scartabelli wrote:

Ma scusa... forse sono duro io, non te la prendere ... come faccio a 
tornare value in modo sincrono se il server me lo torna in modo 
asincrono? Esistono i semafori in javascript?
Come ho già detto non posso scegliere; la specifica dice che devo 
implementare una funzione che prende come parametro il nome della 
proprietà e torna il valore della proprietà stassa.
Le informazioni sono sul server.
E' una specifica che fa parte di uno standard. Non posso cambiarla! Gli 
oggetti che fanno la chiamata sono oggetti prodotti da terze parti e 
chiamano la mia funzione, passano il nome della proprietà e si aspettano 
  il valore come ritorno.
Ciao.
	-Ema-

  il valore come ritorno.
Io fino ad ora avevo capito che la funzione javascript sul client 
l'avresti scritta tu; questa avrebbe fatto una chiamata ad un componente 
server che ti avrebbe risposto con un valore da utilizzare nella pagina.
Visto che un componente server non chiama il client ma gli risponde, 
quanto dici ora qui sopra mi confonde ancora di piu'.
Sembrerebbe quindi che un altro codice js chiami la tua funzione js che 
a sua volta chiama il server?
Quale e' la necessita' di fare per forza la chiamata sincrona?
Credo di non avere capito proprio la situazione allora...

 Credo di non avere capito proprio la situazione allora...
Io devo implementare delle API javascript che vengono invocate da altri 
oggetti javascript. La specifica non parla di comunicazione con il 
server, io ho utilizzato SOAP ma potevo anche inventarmi un protocollo 
tutto mio per parlare con il server.
Le api javascript, che ovviamente girano sul client, sono la vera 
interfaccia con l'oggetto (per questa parte di specifiche). Anche il 
server l'ho scritto io (in PHP) o meglio ho scritto io la parte che 
comunica con le api javascript (tramite SOAP per l'appunto). Potevo fare 
la stessa consa con un applet o con ActiveX (ovviamente quest'ultima 
scelta avrebbe ristretto di molto i client possibili) ma javascript puro 
mi è parsa la scelta migliore (nella speranza che in un futuro prossimo 
anche gli altri browser mettano a disposizione l'oggetto XMLHttpRequest.
Se usi un fixed font dovresti vedere lo schema seguente:
----------      --------------      -------------
| Server |      | API        |      | Oggetto   |
| PHP +  |<---->| Javascript |<---->| chiamante |
| DB     |      |            |      |           |
----------      --------------      -------------
              |_____________________________________|
                                 |
                             Browser
Io faccio Server e API. Oggetto è fatto da terze parti e si aspetta che 
API abbia diversi metodi tra cui uno simile alla funzione citata. Anche 
altri metodi hanno lo stesso problema ma è chiaro che se risolvo per uno 
sono a posto.
Ciao e grazie in ogni caso.
	-Ema-

 sono a posto.
Ok, lo schema e' chiarissimo, ma non hai risposto alla domanda piu' 
importante: dov'e' la necessita' della chiamata sincrona?
Se e' la tua API, e non l'oggetto chiamante come mi pare di capire, a 
generare il "messaggio di attesa" ed il problema e' che mozilla non ti 
disegna subito il div, ti riproporrei le stesse soluzioni di prima.
Mi rifaccio allo stralcio di funzione che hai scritto precedentemente:
var httpRequest = CreaOggettoHttpRequest();
MostraBoxAttesa();   // in IE Mostra subito in MOZ no
httpRequest.open( 
"GET",
http://misito/miapagina.pgp?parametro=
"+paramName, false );
Mozilla non fa in tempo a disegnare il div e tu esegui subito dopo la 
chiamata xmlhttp.
Se la chiamata e' sincrona la tua API non fa piu' nulla finche' 
l'elaborazione non e' terminata (e mozilla non disegna il div), se e' 
asincrona il tuo programma mantiene il controllo e il box viene 
disegnato. Gestisci l'evento e quando e' tutto fatto fai sparire il div.
Caso due (quello brutto): ritarda di un tot la chiamata xml rispetto 
alla funzione che disegna il div di attesa.
Scusa se mi ripeto, ma non mi hai detto cosa non ti va bene in questo 
processo.

 
[CUT]
Ciao.
	-Ema-

 timeout, thread, abort etc etc.
No no. Molto più semplice. Non devo caricare url o simili. Devo solo 
leggere/scrivere parametri e valori sul server; ovviamente poi c'e' la 
gestione degli errori, stati etc etc.
Ciao.
	-Ema-

 prima del termine dello script?
Sempre il solito problema: Non dai al render engine il tempo di
"respirare", ergo non viene aggiornata la pagina.
Nel tuo caso, per dire al browser "ehy, prenditi un attimo di respiro",
prendendo un attimo il codice di Faser come canovaccio (sono un po' di
fretta), basta fare qualcosa del genere:
<script language="JavaScript" type="text/javascript">
function chiama() {
	var elAlert = document.getElementById("alert");
	var elOutput = document.getElementById("output");
 
	var myURL = "server.cfm"; //risponde dopo 3 secondi.
 
	var ricevi = function myScopeFunction(req){
		elAlert.style.visibility = "hidden"; //Nascondo DIV 
		elOutput.innerHTML += req.statusText;
	}
 
	elAlert.style.visibility = "visible"; //Mostro DIV
 
	setTimeout(function(){
		var req = new XMLHttpRequest();
		req.open("GET",myURL,false);
		req.send(null);
		ricevi(req);
		alert(0);
	},0);
}
</script>	
</head>
<body onload="chiama()">
TEST
<div id="alert" style="visibility: hidden;">
===================<br>
ATTENDERE<br>
==================
</div>
<div id="output"></div>
Ovviamente messa cosi' non e' il massimo della vita, ma e' giusto per farti
capire il concetto.
-- 
ZER0://coder.gfxer.web-designer/
~ "Massi' che e' uno standard, e' uno standard proprietario."
(Gio')
on air ~ "Videogames Radio"

 </script>	
[CUT]
Ho buttato un pezzo di codice indicativo di cosa devo fare nella 
discussione con Andrea.
Ciao.
	-Ema-

 semafori)
Non ho capito perche' ti impunti con questo discorso dei semafori; BTW il
discorso e' abbastanza semplice: Se non dai modo al render engine di
lavorare, non puoi avere modifiche visuali nella pagina. E questo mi pare
ovvio.
Quindi, se tu vuoi fare una chiama sincrona in questo modo, e non puoi
adottare nessuna delle soluzioni proposte, temo che si possa andare ben
poco lontano.
Leggasi: Se tu pretendi di fare avere una chiamata sincrona di questo tipo:
var myval=getValueFrom("xxxx");
alert(myval);
e in questa "getValueFrom" modifichi l'aspetto della pagina, facendo
*immediatamente* una richiesta sincrona, sperando che la modifica sia
renderizzata a schermo, la veggo buia.
A meno che non esista qualcosa tramite XPCOM che ti permetta di richiamare
il repaint, ma s'incomincia a chieder privilegi e permessi.
-- 
ZER0://coder.gfxer.web-designer/
~ "Compiere l'impossibile e' impresa che risiede nel cuore degli uomini"
(Mariners and generals)


 
Pensa che ho fatto le api in javascirpt e non con un'applet java proprio 
per evitare casini all'utente. Inoltre il mio codice al momento è 
identico per Mozilla (W3C) e IE salvo per la creazione dell'oggetto 
XMLHttpRequest.
Comunque potrebbe anche essere una strada in effetti.
Ciao.
	-Ema-

 	},0);
	/* Tu stai dicendo che quì ho req.responseXML ? */
	/* Se è così la prima volta che ti vedo ti offro una birra */


     /* Se è così la prima volta che ti vedo ti offro una birra */
       /* beh no req ovviamente no ma in ogni caso la chiamata http è 
completata? */


 attendere un po'...
In quel caso fai una richiesta asincrona. Oppure se dopo tot secondi il
server non ha risposto, con la pagina server side che ha chiamato fai un
flush dell'output buffer in modo la funzione riceva qualcosa che gli dica
di "attendere", mentre il server ancora elabora.
Una progress bar che indica il caricamento progressivo di recordset l'ho
fatta in questo modo.
-- 
ZER0://coder.gfxer.web-designer/
~ Una mente perversa e' un peccato sprecarla.
(A dirty mind is a terrible thing to waste)


 mi sà che Zero potrebbe bere a gratis per i prossimi 20 anni :-)
Eh.. da chi vado a batter cassa..? ^_^"
-- 
ZER0://coder.gfxer.web-designer/
~ "Nella vita uno raccoglie ciò che semina.
Ma per seminare bisogna chinarsi, e prenderlo nel culo un attimo."


 Se sei di Milano, puoi prenotarti! :-)
Sono di Firenze, ma attualmente vagabondeggio proprio a Milano, zona Fiera
(per esser piu' precisi, nei pressi di piazza Firenze, tanto per restare in
tema :) ).
-- 
ZER0://coder.gfxer.web-designer/
~ "Nei film americani, qualsiasi problema che venga considerato
sufficientemente catastrofico, puo' essere risolto facendo esplodere uno
o piu' ordigni nucleari" (ZER0 & Cosimo)


 Faser
-Ema-

 
Sono stato a Firenze circa 20 giorni fa. La prossima volta ti faccio un 
fischio.
-Ema-

 -Ema-
Riassumendo ... non c'e' soluzione al problema cosě come posto da me.
Bisona usare atre tecnologie lato client tipo Java, ActiveX, etc.
:-(
Per la versione attuale mi accontenterň di cambiare il cursore in 
clessidra (che pare si possa fare), per il futuro vediamo.
Ciao a tutti e grazie comunque.
-Ema-

 
Che dire... grazie. Non mi avete dato la soluzione perchè non c'e' e 
quindi mi avete risposto e mi avete risparmiato un po' di lavoro. 
Inoltre ho compreso bene una delle limitazioni del javascript che, in 
generale, penso di conoscere benino, ma la mia carenza di esperienza 
nella grafica .... beh ... basta così.
Ciao.
	-Ema-

 Faser
Ciao.
	-Ema-

 quindi lo volete impostare intervenendo sulle preferences del browser?
No,no.
-- 
ZER0://coder.gfxer.web-designer/
~ ..ma in effetti il concetto di WYSYWYG (quello che vedi e' quello che
ottieni) si applica ai computer malissimo, cosi' come si applica alle
donne... (The Real Programmer)

 generale, penso di conoscere benino, 
Non si finisce mai di imparare. JS, poi, e' un linguaggio estremamente
sottovalutato, con grandissime potenzialita'.
-- 
ZER0://coder.gfxer.web-designer/
~ "Lo dice il buon senso, ma il buon senso non e' uno standard".
(Jeffrey Zeldman)

Ok. se a qualcuno fregasse qualcosa ecco il meglio che sono riuscito a 
fare per il momento:
IE: IE presenta una funzionalità che altri browser non hanno: 
showModalDialog (mozilla ha avuto qualcosa di simile per qualche tempo 
ma pare che non fosse molto stabile come feature per cui è stata tolta)
Comunque con showModalDialog apro una finestra che punta ad una pagina 
in cui cui c'e' il codice che comunica con il server con 
l'XmlHttpRequest. A questo punto la chiamata, che sia sincrona o 
asincrono non mi cambia molto visto che il codice che ha chiamato la 
showModalDialog resta comunque in attesa.
In ogni caso faccio la chiamata asincrona e quando ottengo la risposta 
chiudo la window e nella window principale ho il risultato.
Questo è estattamente quello che mi serviva solo che funziona solo con IE.
geko: Il massimo che posso fare (con javascript ed in base alle 
informazioni raccolte, anche da voi) è intercettare tutti gli eventi per 
evitare che durante l'attesa l'utente prema inutilmente in giro, 
stampare un messaggio nella status della finestra (capirai chi la legge).
.....
if( window.document.all ) {	//IE
	// compute page position
	var args = new Object();
	args.sapi = this;
	args.func = "GetValue";
	args.param = param;
	result = showModalDialog( 	this.basepath + "/dialog.php",
					args,
					this.sStyle );
} else {
	slStopEvents(window.top);
	result = this.getValue( param );
	window.setTimeout(	function restartEvents() {
					slStartEvents(window.top);
				},
				300
			);
}
.....
dove
- slStopEvents: attiva la cattura e la cancellasione degli eventi
- slStartEvents: disattiva la cattura e la cancellasione degli eventi
- getValue è il metodo che esegue la chiamata *sincrona* al server, e 
dalla risposta del server ricava il valore da ritornare
dialog.php è invece:
function serverCommunication() {
	try {
	if( window.dialogArguments ) {
		switch( window.dialogArguments.func ) {
			case "GetValue":
				window.returnValue = window.dialogArguments.sapi.getValue( 
window.dialogArguments.param );
			break;
			case "SetValue":
				window.returnValue = window.dialogArguments.sapi.setValue( 
window.dialogArguments.param,
													window.dialogArguments.value
												);
			break;
			case "Finish":
				window.returnValue = window.dialogArguments.sapi.finish();
			break;
		}
	}
	} catch ( ex ) {
		alert( ex );
	}
 
	window.close();
}
window.onload = function() {
	window.setTimeout( serverCommunication, 50 );
}
Spero che possa essere utile a qualcuno.
Ciao.
	-Ema-

 if( window.document.all ) {	//IE
Brutto, brutto. Come ho detto piu' volte, il "browser sniffing" non e'
molto corretto ed infatti al giorno d'oggi si preferisce un piu' corretto
"object checking". Tant'e' che un check del genere, su browser che si
"spacciano" per IE, fallisce miseramente.
-- 
ZER0://coder.gfxer.web-designer/
~ Come devo regolare la stampante laser per stordire?
(How do I set a laser printer to stun?)
on air ~ "RIKKI - The Moon ~Utikisama~"

 corretto fare anche su IE).
Dalla documentazione 
(
http://www.mozilla.org/xpfe/xulref/windowref.html#open
)
- Pare che window.open possa prendere come parametro "modal" e non fanno 
accenni a restrizioni sulla sicurezza. Provando infatti non da security 
exception, anzi non da nessuna eccezione, solo non funziona mentre pare 
che prima della v. 1.3 funzionasse (io non ho provato)
- La successiva window.openDialog invece richiede che lo script sia 
signed ed in effetti provando ad eseguirla si ottiene un'eccezione di 
sicurezza: Error: uncaught exception: [Exception... "Security error" 
code: "1000" nsresult: "0x805303e8 (NS_ERROR_DOM_SECURITY_ERR)" 
location: "
http://localhost/TestPage1.html
 Line: 31"]
Ci sono alcune discussioni al riguardo ed a quanto pare il problema è 
legato soprattutto al fatto che, per come è strutturato il modello di 
windowing di Mozilla con poche righe di codice si potrebbero bloccare 
tutte le finestre del browser, la mail, le news, chatzilla etc. e questo 
non è considerato accettabile (e ci credo!)
In effetti i casi in cui si rende utile una cosa simile sono abbastanza 
pochi; forse anche perchè non è a disposizione ed in generale si pensa 
alla propria appicazione web senza queste funzionalità.
Ciao.
	-Ema-

 location: "
http://localhost/TestPage1.html
 Line: 31"]
Probabilmente parte con determinati privilegi abilitati o da una chrome.
-- 
ZER0://coder.gfxer.web-designer/
~ La vita e' una tempesta, ma prenderla nel culo e' un lampo.
(B. Grillo)

 non solleva alcuna eccezione.
Da qui 
http://www.mozilla.org/xpfe/xulref/windowref.html#open
 si legge 
per quanto riguarda la open:
modal - The window will be run modally. The call to window.open will not 
return until the user has dismissed the window. Note that modal implies 
dependent.
Questo è esattamente quello che penso io. Nel fatto che è modale (o 
dovrebbe esserlo) è simile a showModalDialog.
Ciao.
	-Ema-

 dovrebbe esserlo) è simile a showModalDialog.
Intendevo a livello pratico: Non viene sollevata nessuna eccezione, perche'
"funziona". Infatti puoi vedere da solo la differenza che c'e' nell'aprire
una finestra normale da una con "modal" specificato come parametro.
Il punto, e' che non e' "modale" nel senso stesso del termine.
Questo, intendevo.
-- 
ZER0://coder.gfxer.web-designer/
~ "Nella vita uno raccoglie ciò che semina.
Ma per seminare bisogna chinarsi, e prenderlo nel culo un attimo."
on air ~ "Hero's Song" by ZF

 
http://msdn.microsoft.com/security/default.aspx?pull=/library/en-us/dnwxp/html/xpsp2web.asp
Si. Grazie. Avevo letto anche un altro post a questo proposito qualche 
giorno fa. Penso tu ti riferisca alle limitazioni poste in generale alle 
popup ed al fatto che per default sono disabilitate. Penso/spero che gli 
utenti fra qualche anno avranno imparato ad abilitare i siti di cui si 
fidano. Certo per un po' di tempo sarà dura. In ogni caso penso che sia 
giusto.
Ciao.
	-Ema-