• User Attivo

    Problema critico con Javascript in Safari

    Allora... dato che ho contribuito in alcune discussioni penso di essermi guadagnato il diritto di esporre un mio problema... (ma quanto la fai lunga!!!)

    Quello che mi succede è +ttosto strano, e spero che qualcuno sappia darmi una dritta.
    Sto realizzando un piccolo giochino in asp e ajax. Il motore è semplicissimo, assomiglia a "carta forbici sasso" per capirci. Per questioni di spazio non posso postare il codice dato che stiamo parlando di diverse pagine... cmq

    La procedura è semplice:

    • Un giocatore seleziona il pezzo ("carta" "forbici" o "sasso"), a quel punto può confermare la sua scelta (il che chiama via ajax una funzione per memorizzare la mossa), quando entrambi i giocatori hanno fatto la loro mossa, sempre via ajax, viene eseguito un controllo letti i risultati, decretato chi vince e chi perde, e riposizionato il tutto per fare un altra mano.

    Ora, quando gioco con un Safari (la macchina è un Mac iBook G4) precisamente alla Terza mossa, quando premo sul pulsante "conferma" (che dovrebbe far partire la funzione javascript che manda la httpRequest) Safari crasha senza dare nessun messaggio... semplicemente si chiude (e poi al riavvio ti chiede di segnalare l'errore).

    Qualcuno ha qualche idea?

    Grazie a tutti per l'attenzione...


  • User Attivo

    Molto difficile capire senza vedere il codice...il problema potrebbe essere ovunque o comunque quel tipo di browser mi sa che non vede benissimo sto nuovo tipo di approccio (cioè ajax). Potrebbe avere qualche piccolo bug che esce fuori in casi particolari.
    Con firefox funziona tutto?


  • User Attivo

    Yes, cmq cerco di tagliare dal software le funzioni incriminanti, che almeno quelle dovrei riuscire a isolarle... Il fatto che sbrocchi solamente alla quarta iterazione mi lascia basito. Appena ho un attimo posto il codice.


  • User Attivo

    Ecco le porzioni di codice che suppongo essere incriminate... come prima ho fatto numerosi test su firefox, opera e IE senza riscontrare problemi mentre safari ad un certo momento di una delle iterazioni (nuovi test hanno portato risultati diversi, adesso arriva anche alla 6à iterazione (il momento non è mai lo stesso) si blocca per un attimo poi crusha...

    Date un occhiata al codice per vedere se c'é qualcosa di sbagliato...

    Il crush avviene indifferentemente in ciascuna delle fasi sotto descritte (a volte alla selezione del pezzo, a volte alla conferma del pezzo selezionato, a volte mentre attende che l'avversario selezioni il proprio pezzo, a volte quando vengono elaborati i risultati.)

    Per le chiamate XmlHttpRequest utilizzo questo codice cross-browser:

    
    function GetXmlHttpObject()
    { 
    var objXMLHttp=null
    if (window.XMLHttpRequest)
    {
    objXMLHttp=new XMLHttpRequest()
    }
    elseif (window.ActiveXObject)
    {
    objXMLHttp=new ActiveXObject("Microsoft.XMLHTTP")
    }
    return objXMLHttp
    } 
    
    

    Quando il giocatore seleziona una pedina eseguo questa funzione (che non dovrebbe dare problemi):

    
    function giocaPedina()
    {
    if(objIDGiocata!="0")
    {
    tornaPedinaCampo();
    }
    objPedinaSelezionata = new getObj(this.id);
     
    successiva = objPedinaSelezionata.obj.nextSibling;
     
    var destinazione;
     
    destinazione = new getObj("giocataGiocatore");
    destinazione.obj.appendChild(objPedinaSelezionata.obj);
    objPedinaSelezionata.obj.onclick = "";
    objPedinaSelezionata.obj.className = "pedinaGiocata";
     
    destinazione.style.display = "block"; 
     
    objIDGiocata = this.id;
     
    nascondiPedina()
    }
    
    

    Quando confermo la pedina selezionata utilizzo questa funzione:

    
    function confermaMossa()
    {
    if(objIDGiocata!=0&&(!blMosso))
    {
     
    blMosso = true;
     
    bloccaPezzi();
     
     
    /* Qui ho tagliato una serie di controlli che mi valorizzano la variabile 
       iPezzo a seconda del pezzo slezionato */
     
    xmlHttp=GetXmlHttpObject();
     
    if (xmlHttp==null)
    {
    alert ("Browser does not support HTTP Request");
    return
    }
    var url="eseguiMossa.asp";
    url=url+"?sid="+Math.random();
    url=url+"&pezzo="+iPezzo;   // Qui è dove metto la variabile iPezzo
    xmlHttp.onreadystatechange = mossaEffettuata; 
    xmlHttp.open("GET",url,true);
    xmlHttp.send(null);
     
    } 
    }
    
    

    Poi il sistema si mette in attesa che l'avversario esegua la sua mossa con questo codice:

    
    function mossaEffettuata() 
    { 
    if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete")
    { 
    var sResult;
    var aResult;
     
    sResult = xmlHttp.responseText
    aResult = sResult.split(",");
     
     
    if(parseInt(aResult[0])==3) 
    {
    /* Mette l'utente in attesa */
    objStato.obj.innerHTML = "In attesa che l'avversario effettui la sua mossa";
     
    window.setTimeout("waitMove();",5000);
     
    }
    else
    {
    /* Risoluzione dello scontro */
    objStato.obj.innerHTML = "Risultato dello scontro in elaborazione";
     
    /* Qui deve aggiornare il risultato nel server */
    alert("l'avversario ha mosso " + aResult[1] + " tu hai mosso " + iPezzo);
     
    elaboraScontro(aResult[1],iPezzo);
     
    }
     
    } 
    } 
    function waitMove()
    {
    if(playerMoved==0)
    {
    xmlHttp=GetXmlHttpObject();
     
    if (xmlHttp==null)
    {
    alert ("Browser does not support HTTP Request");
    return
    }
    var url="waitMove.asp";
    url=url+"?sid="+Math.random();
    xmlHttp.onreadystatechange = avversarioMosso; 
    xmlHttp.open("GET",url,true);
    xmlHttp.send(null);
    window.setTimeout("waitMove();",5000);
     
    }
    }
     
    function avversarioMosso() 
    { 
    if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete")
    { 
     
    playerMoved = parseInt(xmlHttp.responseText);
     
    if(playerMoved!=0) 
    {
    objStato.obj.innerHTML = "L'avversario ha schierato il suo pezzo !";
    /* Qui succede quello che deve succedere. 
    Ricordati che playerMoved contiene il pezzo selezionato dall'avversario */
    alert("l'avversario ha mosso " + playerMoved + " tu hai mosso " + iPezzo);
    elaboraScontro(playerMoved, iPezzo);
    }
     
    } 
    } 
    
    

  • User Attivo

    Io non vedo niente di errato nel codice. Secondo me si crea qualche condizione particolare che safari non riesce a gestire.
    Mi stai dicendo che anche solo chiamando la funzione giocapedina() va in crash?
    Perchè quando chiami quella non c'è in gioco nessuna chiamata ajax.
    Se è così non capisco dove possa essere il problema.
    Dovresti fare un debug manuale e commentare pezzi di codice che potrebbero essere critici e vedere se continua il crash.


  • User Attivo

    Si a volte anche con giocaPedina, ma dà come l'idea di aver accumulato qualche problema per poi scoppiare improvvisamente...

    Sarà una dura sessione di Debug sicuramente... dannato Safari...

    Per prima cosa dovrei staccare ajax e vedere se và cmq in "crush"? O mi conviene realmente isolare una riga alla volta??


  • User Attivo

    Comincia a staccare GetXmlHttpObject


  • User Attivo

    Allora FuSion (o chiunque abbia Safari) Ho tolto tutto.... e continua a darmi problemi. Il sistema crusha se io selezione all'incirca 3 o 4 pezzi in sequenza (anche rimettendoli a posto con tornaPedinaCampo()) e per ultimo la regina.... quando clicco su la regina mi stampa gli alert di avviso e poi crusha, senza mettere in rilievo la regina...

    Ecco il codice ripulito della pagina html:

    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="it" >
     <head>
     
      <title>Test per Safari che non funziona</title>
      <script src="partita2.js"></script>
     </head>
     <body>
       
      <div class="campo1True">
      
       <div id="pedineGiocatore" class="pedineGiocatore">
        <img class="pedina" title="Fante" alt="Fante" id="fante1True" src="images/fante1True.jpg">
        <img class="pedina" title="Fante" alt="Fante" id="fante2True" src="images/fante2True.jpg">
        <img class="pedina" title="Cavaliere" alt="Cavaliere" id="cavaliere1True" src="images/cavaliere1True.jpg">
        <img class="pedina" title="Cavaliere" alt="Cavaliere" id="cavaliere2True" src="images/cavaliere2True.jpg">
        <img class="pedina" title="Elefante" alt="Elefante" id="elefante1True" src="images/elefante1True.jpg">
        <img class="pedina" title="Elefante" alt="Elefante" id="elefante2True" src="images/elefante2True.jpg">
        <br />
        <img class="pedina" title="Regina" alt="Regina" id="reginaTrue" src="images/reginaTrue.jpg">
        <img class="pedina" title="Re" alt="Re" id="reTrue" src="images/reTrue.jpg">
        <img class="pedina" title="Raijin" alt="Raijin" id="raijinTrue" src="images/raijinTrue.jpg">
       </div>
       
       <br />
       
       <div id="giocataGiocatore" class="giocataGiocatore">
        <div id="comandiGiocatore" class="comandiGiocatore">
         <a style="cursor:hand;" onclick="tornaPedinaCampo()">Conferma</a><br />
         <a style="cursor:hand;" onclick="tornaPedinaCampo()">Annulla</a>
        </div>
       </div>
      
      </div>
      
     </body>
     
    <script language="javascript">
     impostaPulsanti('True');
    </script>
    </html>
    
    

    E qui il codice javascript ridotto all'osso (eppure continua a crushare) Il file si deve chiamare "partita2.js" per essere integrato. Ho anche staccato il css:

    
    var objPedinaSelezionata; // La pedina che viene selezionata
    var objIDGiocata; // L'id della pedina giocata, 0 se nessuna
    var successiva; // La pedina successiva a quella selezionata
    var blGiocatore; //"True" per il primo "False" per il secondo
    var comandi; // Div con i comandi del giocatore.
    function giocaPedina()
    {
    alert(objIDGiocata);
    if(objIDGiocata!="0")
    {
    tornaPedinaCampo();
    }
    objPedinaSelezionata = new getObj(this.id);
    alert(objPedinaSelezionata);
    successiva = objPedinaSelezionata.obj.nextSibling;
    alert(successiva);
    var destinazione;
    
    destinazione = new getObj("giocataGiocatore");
    alert(destinazione);
    destinazione.obj.appendChild(objPedinaSelezionata.obj);
    objPedinaSelezionata.obj.onclick = "";
    objPedinaSelezionata.obj.className = "pedinaGiocata";
    
    destinazione.style.display = "block"; 
    
    objIDGiocata = this.id;
    }
    function tornaPedinaCampo()
    {
    var destinazione;
    
    destinazione = new getObj("pedineGiocatore");
    destinazione.obj.insertBefore(objPedinaSelezionata.obj,successiva);
    
    objPedinaSelezionata.obj.onclick = giocaPedina;
    objPedinaSelezionata.obj.className = "pedina";
    
    var origine;
    
    origine = new getObj("giocataGiocatore");
    
    origine.style.display = "none";
    
    objIDGiocata = "0";
    }
     
    function impostaPulsanti(giocatore)
    {
    var objPedina;
    objPedina = new getObj("fante1" + giocatore);
    objPedina.obj.onclick = giocaPedina;
    
    objPedina = new getObj("fante2" + giocatore);
    objPedina.obj.onclick = giocaPedina;
    
    objPedina = new getObj("cavaliere1" + giocatore);
    objPedina.obj.onclick = giocaPedina;
    objPedina = new getObj("cavaliere2" + giocatore);
    objPedina.obj.onclick = giocaPedina;
    objPedina = new getObj("elefante1" + giocatore);
    objPedina.obj.onclick = giocaPedina;
    objPedina = new getObj("elefante2" + giocatore);
    objPedina.obj.onclick = giocaPedina;
    objPedina = new getObj("re" + giocatore);
    objPedina.obj.onclick = giocaPedina;
    objPedina = new getObj("regina" + giocatore);
    objPedina.obj.onclick = giocaPedina;
    objPedina = new getObj("raijin" + giocatore);
    objPedina.obj.onclick = giocaPedina;
    blGiocatore = giocatore;
    
    comandi = new getObj("comandiGiocatore");
    
    objIDGiocata = "0"; 
    }
     
     
    function getObj(name)
    {
    
    if (document.getElementById)
    {
    this.obj = document.getElementById(name);
    this.style = document.getElementById(name).style;
    }
    elseif (document.all)
    {
    this.obj = document.all[name];
    this.style = document.all[name].style;
    }
    elseif (document.layers)
    {
    this.obj = document.layers[name];
    this.style = document.layers[name];
    }
    }
    
    

    Prego chiunque abbia Safari di effettuare dei test per confermare se effettivamente seguendo la mia procedura crusha, e per aiutarmi ad identificare l'evidente baco di Safari...


  • User Attivo

    Nuovo update per chiunque possa aiutarmi... ho scambiato il ré con la regina, con il risultato che il sistema crusha quando clicco sul ré (invece che sulla regina)....

    deve essere qualcosa che riguarda la posizione del pezzo... con il primo pezzo dopo il <br /> safari crasha (ma solo dopo aver fatto scattare qualche pezzo)
    ho provato a mettere un <img> invisibile per ingannarlo ma Safari è + furbo di me e crusha lo stesso...

    Mi interessa scoprire perché questo accade, ma in mancanza di meglio se qualcuno mi può suggerire un modo per ingannare safari, ben venga.


  • User Attivo

    E' veramente molto strano ma come è ben evidente non è un errore di codice ma un bug di safari.
    Io comunque non ho installato safari quindi non ho provato il codice ma a sto punto, come dici anche tu, mi sa che devi trovare il modo per bypassare il bug.
    Prova a mettere un "div" al posto del br. Lo usi come a capo assegnandogli uno clear:both ed un margin.
    Ma ho l'impressione che non si risolva manco così.


  • User Attivo

    Ho messo un <div> con dentro un <br /> e voilà... Safari non crusha +...

    Lascio quindi questo commento: "se lavorate con javascript e manipolate immagini, per non far crushare safari non dovete mettere <br /> alla destra delle immagini..."

    Come faccio a chiudere il thread? Ad indicare che è risolto?


  • User Attivo

    Chi legge capisce da se che è concluso 😄
    Ad ogni modo mi è venuto un piccolo dubbio.
    Prova a mettere <br> e non <br/>