2010-08-29 7 views
0

J'ai un problème étrange seulement dans Chrome en utilisant un iframe mais travaillant dans tous les autres navigateur commun. Le problème: Si je tape IFRAME puis j'appuie sur le bouton pour envoyer, ça marche bien, le focus sur l'IFRAME et le curseur BLINK.Problème avec Google Chrome et Javascript. Guru nécessaire!

Mais si je tape et que j'appuie sur ENTRÉE pour appeler la fonction de gestionnaire d'événements, la mise au point revient mais le curseur disparaît. Et puis, si vous allez dans une autre fenêtre et que vous retournez, le curseur apparaîtra. Cela se produit uniquement dans Chrome. J'ai fait la page d'exemple pour montrer le problème en action. Cliquez sur le lien ci-dessous pour voir.

MISE À JOUR: J'ajouté le code aussi ci-dessous

var editorFrame = 'myEditor' 

function addFrame() { 

    var newFrame = new Element('iframe', { 
     width: '520', 
     height: '100', 
     id: editorFrame, 
     name: editorFrame, 
     src: 'blank.asp', 
     class: 'myClass' 
    }); 

    $('myArea').appendChild(newFrame); 

    window.iframeLoaded = function() { 
     // this is call-back from the iframe to be sure that is loaded, so can safety attach the event handler 

     var iframeDoc, UNDEF = "undefined"; 
     if (typeof newFrame.contentDocument != UNDEF) { 
      iframeDoc = newFrame.contentDocument; 
     } else if (typeof newFrame.contentWindow != UNDEF) { 
      iframeDoc = newFrame.contentWindow.document; 
     } 
     if (typeof iframeDoc.addEventListener != UNDEF) { 
      iframeDoc.addEventListener('keydown', keyHandler, false); 
     } else if (typeof iframeDoc.attachEvent != UNDEF) { 
      iframeDoc.attachEvent('onkeydown', keyHandler); 
     } 
    }; 
} 

function resetContent() 
{ 
    var myIFrame = $(editorFrame); 

    if (myIFrame) myIFrame.contentWindow.document.body.innerHTML=''; 
} 

function setEditFocus() 
{ 

    var iFrame = document.frames ? document.frames[editorFrame] : $(editorFrame); 
    var ifWin = iFrame .contentWindow || iFrame; 

    ifWin.focus(); 

} 

function send() 
{ 
    resetContent(); 
    setEditFocus(); 
} 

function keyHandler (evt) { 

    var myKey=(evt.which || evt.charCode || evt.keyCode) 

    if (myKey==13) { 

     if (!evt) var evt = window.event; 

     evt.returnValue = false; 

     if (Prototype.Browser.IE) evt.keyCode = 0; 

     evt.cancelBubble = true; 

     if (evt.stopPropagation) evt.stopPropagation(); 

     if (evt.preventDefault) evt.preventDefault(); 

     send(); 

    } 
} 

Dans la page HTML

<body onload="addFrame()"> 

<div id="myArea"></div> 
<input id="myButton" type="button" value="click me to send [case 1]" onclick="send()"> 

Pour rendre plus facile à comprendre le problème que j'ai créer une page spécifique à reproduire le problème avec l'exemple complet et la source inclus.

Vous pouvez voir ici en utilisant Google Chrome: example of the problem

je vraiment besoin de votre aide parce que j'ai essayé de résoudre ce problème pendant plusieurs jours sans chance. Et toutes les suggestions, astuces et solutions de contournement sont bien acceptées.

Merci d'avance.

+1

S'il vous plaît créer un exemple minimal qui reproduit votre problème réel qui est assez petit pour coller ici. Il est difficile de voir ce que vous essayez d'atteindre et quel est votre problème. :) – bzlm

+0

@bzlm Ops, je pensais que c'était mieux de voir le problème en action non? Btw je vais poster ici le code aussi :) –

+0

c'est assez dur - OP a fait un très bon exemple qui démontre le problème. –

Répondre

3

Je ne suis pas vraiment sûr de la cause du problème, car il y a des fois où donnera le focus à l'élément correctement, bien que la plupart du temps ce n'est pas le cas. Vous ne devriez pas avoir besoin de faire la mise au point car la mise au point n'est pas perdue lorsque vous appuyez sur la touche. Si vous omettez l'appel setEditFocus(), vous remarquerez qu'il fonctionne toujours correctement dans tout sauf Chrome, qui semble offensé que vous avez supprimé tout le contenu dans le corps.

Lorsque vous définissez contenteditable, chaque navigateur définit la innerHTML de l'élément de document iframe body être quelque chose de différent:

Browser   | innerHTML 
----------------------------- 
Internet Explorer | '' 
Opera    | '<br>\n' 
Firefox   | '<br>' 
Chrome/Safari  | '\n' 

Si vous n'êtes pas attendre de voir ce genre de choses supplémentaires lorsque vous analysez le contenu plus tard, vous voudrez peut-être l'enlever dès le début dans addFrame().

j'ai pu « régler » le problème en procédant comme suit:

Tout d'abord, mettre à jour le gestionnaire d'événements afin que nous puissions revenir false en elle et empêcher Opera de générer une page HTML pour le plaisir quand nous appelons getSelection() plus tard .. .

function addFrame() { 
    ... 
    window.iframeloaded = function() { 
     ... 
     if (typeof iframeDoc.addEventListener != UNDEF) { 
      iframeDoc.addEventListener('keypress', keyHandler, false); 
     } else if (typeof iframeDoc.attachEvent != UNDEF) { 
      iframeDoc.attachEvent('onkeypress', keyHandler); 
     } 
    } 
} 

Edit: Suppression de la fonction originale en faveur du nouveau inclus ci-dessous

Enfin, le retour de la false k Ils pressent le gestionnaire pour résoudre le problème d'Opera mentionné ci-dessus.

function keyHandler (evt) { 
    var myKey=(evt.which || evt.charCode || evt.keyCode) 

    if (myKey==13) { 
     ... 
     return false; 
    } 
} 

J'avais initialement fait ce syockit suggéré, mais je l'ai trouvé faisait des choses étranges avec la taille de caret dans Chrome, cette méthode qui semble éviter (bien que Firefox est encore un peu hors ...). Si vous ne vous souciez pas de cela, définir le innerHTML pour être non vide est probablement une solution plus facile.

Notez également que vous devez utiliser className au lieu de class dans l'objet que vous passez à new Element(), puisque IE semble considérer comme un mot réservé et dit qu'il est une erreur de syntaxe.

Édition: Après avoir joué avec, la fonction suivante semble fonctionner de manière fiable dans IE8/Firefox/Chrome/Safari/Opera pour votre cas de test plus avancé. Malheureusement, j'ai dû inclure la détection du navigateur de Prototype pour rendre compte de Opera, puisque tout semble le même en ce qui concerne le JavaScript, le comportement réel nécessite un code différent qui est en conflit avec les autres navigateurs, et je n'ai pas pu trouver un meilleur moyen de les différencier.

Voici la nouvelle fonction, qui met l'accent sur le contenu modifiable de l'iframe, et fait en sorte que s'il y a déjà du contenu là-dedans, que le caret est déplacé à la fin de ce contenu:

function focusEditableFrame(frame) { 
    if (!frame) 
     return; 

    if (frame.contentWindow) 
     frame = frame.contentWindow; 

    if (!Prototype.Browser.Opera) { 
     frame.focus(); 

     if (frame.getSelection) { 
      if (frame.document.body.innerHTML == '') 
       frame.getSelection().extend(frame.document.body, 0); 
      else 
       frame.getSelection().collapseToEnd(); 
     } else if (frame.document.body.createTextRange) { 
      var range = frame.document.body.createTextRange(); 

      range.moveEnd('character', frame.document.body.innerHTML.length); 
      range.collapse(false); 
      range.select(); 
     } 
    } else { 
     frame.document.body.blur(); 
     frame.document.body.focus(); 
    } 
} 

Mise à jour setEditFocus() (Pas vraiment nécessaire maintenant, mais comme vous l'avez déjà):

function setEditFocus() 
{ 
    focusEditableFrame($(editorFrame)); 
} 
+0

oh vous êtes un vrai GURU et l'explication est si claire! Comme la dernière fois tu m'aides beaucoup et tes suggestions résout le problème en CHROME!En réalité, le code que je poste est extrapolé de ma source qui est plus grande parce que le chat peut être fermé, réouvert et plus encore si votre travail fonctionne bien mais je dois donner le focus dans les mêmes cas et en FF, IE donc j'ai besoin ajouter une condition dans 'la fonction setEditFocus'. J'ai donc ajouté une condition comme 'si (Prototype.Browser.Gecko || Prototype.Browser.IE || Prototype.Browser.Opera) {ifWin.focus();} else {... votre code}' Opera ne fonctionne pas comme bien btw :(Suggestions? –

+0

@Luka - J'ai testé le code que j'ai posté dans Firefox, IE, Opera, et Chrome (et Safari, juste parce que), donc vous ne devriez pas avoir besoin d'ajouter la condition, car cela fonctionne comme Je ne l'ai pas écrit quand vous l'ajoutez au reste de votre code, ou –

+0

je vous laisse travailler beaucoup :) mais vous êtes tellement bon !! J'ai créé un nouvel exemple où vous pouvez voir votre code en action, allez ici 'http: // under.bestqm.com/test/iframe2.asp' et essayez d'appuyer sur les boutons dans l'ordre, vous verrez que l'accent ne fonctionne pas en FF (bouton 2). BTW lorsque vous appuyez sur Entrée (en tant que premier problème), il fonctionne bien (à la fois dans Chrome et FF) comme je le souhaitais et grâce à votre code. Le problème dans ce cas est que je dois donner l'accent dans de nombreux cas à l'IFRAME comme l'exemple en utilisant le bouton 2. –

0

Très rapidement, pouvez-vous essayer d'ajouter des points-virgules à la fin des lignes dans votre fonction send()? Et voyez si cela fonctionne.

function send() { 
    resetContent(); 
    setEditFocus(); 
} 
+0

merci pour votre suggestion, mais cela ne laisse pas le travail aussi bien, les points-virgules n'ont aucun effet. Je vous invite à cliquer sur le lien ci-dessus pour voir le problème en action en utilisant Chrome –

1

Vous savez comment j'ai résolu celui-ci? En resetContent(), remplacer '' avec ' ':

if (myIFrame) myIFrame.contentWindow.document.body.innerHTML=' '; 

Si cela fonctionne, bien. Ne demandez pas pourquoi, cependant, il pourrait s'agir d'un de ces problèmes de Webkit avec l'objet Range, enregistrez un bug si vous voulez.

+0

merci pour votre conseil, ressembler à "l'oeuf de Colombo" :) mais toujours avoir un problème avec cette suggestion dans un autre navigateur –

Questions connexes