FF 1.5 -> Problème de css dans la balise <iframe>

HTML5, CSS3, Javascript, support des mobiles... Que penser de votre site ? Vous manquez d'informations pour la construction d'un site qui puisse s'afficher correctement partout ? C'est un problème simple, un peu complexe ? Venez ici !
Répondre
priz
Arias
Messages : 7
Inscription : 04 déc. 2005, 23:06

FF 1.5 -> Problème de css dans la balise <iframe>

Message par priz »

Bonjour,
j'ai un soucis avec la nouvelle version de Firefox, ce dernier n'interprète plus les feuilles de styles dans une balise iframe, lorsque son contenu est généré en javascript.
Seul le sélecteur universel (*) est pris en compte, le reste est complétement ignoré.

Code : Tout sélectionner

<html><body>
<iframe width="200" height="100" id="iframe"></iframe>
<script>
<!--
var iframe=document.getElementById('iframe').contentDocument;
iframe.open();
iframe.write('<html><head><style>*{ color:red }H1{ color:green }</style></head><body><h1>test</h1></body></html>');
iframe.close();
//-->
</script>
</body></html>
martin
Varan
Messages : 1074
Inscription : 21 janv. 2004, 16:23

Message par martin »

Au pif, essaie de mettre ton script dans une fonction, et de lancer celle ci sur l'évenement onload du body de la page principale.
priz
Arias
Messages : 7
Inscription : 04 déc. 2005, 23:06

Message par priz »

C'est un bon pif, effectivement cela va mieux, mais cela reste un peu aléatoire.

Code : Tout sélectionner

<html><head>
<script>
<!--
function loadContent(id){
  var iframe=document.getElementById(id).contentDocument;
  iframe.open();
  iframe.write('<html><head><style>*{ color:red }H1{ color:green }</style></head><body><h1>test</h1></body></html>');
  iframe.close();
}
//-->
</script>
</head><body onload="loadContent('iframe')">
<iframe width="200" height="100" id="iframe"></iframe>
</body></html>
c'est bien lu la première fois, mais si on actualise la page ou si on vide le cache, c'est n'importe quoi. C'est encore plus flagrant avec une feuille
de style externe :

Code : Tout sélectionner

<html><head>
<script>
<!--
function loadContent(id){
  var iframe=document.getElementById(id).contentDocument;
  iframe.open();
  iframe.write('<html><head><link rel="stylesheet" href="http://www.geckozone.org/forum/templates/geckozone/geckozone.css" type="text/css" /></head><body><h1 class="explaintitle">test</h1></body></html>');
  iframe.close();
}
//-->
</script>
</head><body onload="loadContent('iframe')">
<iframe width="200" height="100" id="iframe"></iframe>
</body></html>
Je me demande si il n'y a pas un problème de cache.
martin
Varan
Messages : 1074
Inscription : 21 janv. 2004, 16:23

Message par martin »

toujours au pif, garde la fonction et teste 2 autres choses (que tu peux éventuellement cumuler ):

* lance la fonction toujours sur le onload, mais par un setTimeout, même avec un temps de 1 milliseconde.

* ajoute la feuille de style via le DOM aprés avoir créer le contenu de base. C'est à dire iframe.contentWindow.document.createElement("link"), puis lui ajouter les attributs, puis appendChild sur le head. (j'espère être clair...)
Invité

Message par Invité »

j'ai l'impression que l'on chauffe :

Comme j'aime les choses compliquées, j'ai commencé par la deuxième solution : création d'une feuille de style avec le DOM. Malheureusement même avec un temporisateur cela ne donne rien il s'en fout complètement.

J'ai ensuite essayé la première solution : idem rien à faire.

Par contre j'ai mis un temporisateur de 1ms sur l'ouverture, l'écriture et la fermeture du document html, et là surprise ! il affiche tout correctement.
Par contre revers de la médaille le navigateur continue à être en mode "chargement" et du coup il n'execute plus rien en javascript.

Je vais essayer de voir ou se situe le problème : si c'est à l'ouverture, à l'écriture ou à la fermeture.
Je penche pour la fermeture, qui serait trop rapide.
Je teste et je te tiens au courant.
priz
Arias
Messages : 7
Inscription : 04 déc. 2005, 23:06

Message par priz »

Je commence à mieux saisir le bug :

Contrairement à ce que je croyais la feuille de style est bien appliquée avec les classes et les identifiants. Seul les sélecteurs faisant appel à des balises sont ignorés. Ce qui suggère qu'il y a un problème d'application des feuilles de styles sur l'arborescence du DOM lors de l'insertion du document dans la balise "iframe". C'est comme si, au moment de la création de l'iframe, celle-ci n'était pas prête à recevoir immédiatement du contenu.

Pour résoudre partiellement le problème, l'insertion du contenu de l'iframe doit être séparé de la création de la balise iframe. Bref, mettre un temporisateur (setTimeout) de 1ms entre le moment où la balise est créée et le moment où l'on insert son contenu.

Le problème est résolu partiellement car le simple rafraichissement de la page provoque de nouveau le bug.

J'essaye de voir si il y a une parade.
martin
Varan
Messages : 1074
Inscription : 21 janv. 2004, 16:23

Message par martin »

bon, une autre idée toujours au pif :D :
garde la fonction qui crée l'iframe et son contenu, mais sans le style.
Ce contenu doit contenir lui même un petit script de nouveau déclenché par le onload, mais du body interne. Ce script chargerait la feuille de style.

En fait je suis intérêssé par la solution, je me rend compte que j'ai un script qui a le même problème. Là j'ai pas le temps d'essayé, je pars 2 jours, mais je suivrai de loin si tu trouves...
Invité

Message par Invité »

Cela se précise, j'ai enfin des erreurs javascript cohérentes lors du rafraichissement :
Erreur : Propriété « behavior » inconnue. Déclaration abandonnée.
Fichier source : http://www.geckozone.org/forum/template ... kozone.css
Ligne : 572
Bon ça on s'en fout, c'est pas un pauvre behavior qui peut poser problème. Par contre, vu qu'il est appelé à la fin cela prouve que la feuille de style a bien été analysée jusqu'au bout.
Erreur : uncaught exception: Permission refusée d'obtenir la propriété HTMLDocument.write
Ah, ça c'est beaucoup plus intéressant : ceci expliquant cela. pour une raison que j'ignore l'iframe est bloqué en écriture.
Erreur : Fin de fichier inattendue durant la recherche de « , » ou « { ». Jeu de règles ignoré suite à un mauvais sélecteur.
Fichier source : http://www.geckozone.org/forum/template ... kozone.css
Ligne : 1
Erreur : Fin de fichier inattendue durant la recherche de Fermeture } d'un jeu de règles invalide.
Fichier source : http://www.geckozone.org/forum/template ... kozone.css
Ligne : 1
Conséquence de l'empêchement d'écriture, le fichier css à l'air d'être mal "parsé" car à la fameuse ligne 1 c'est juste un commentaire et même avec une autre feuille de styles, cela donne les mêmes erreurs. [/code]
Invité

Message par Invité »

En fait pour résoudre complètement le problème il suffit d'augmenter le setTimeout afin que l'on puisse avoir les droits d'écrture mais cela ne me plait qu'à moitié car cela doit dépendre de la machine et de l'os.

Code : Tout sélectionner

<html><head>
<script>
<!--
function initIframe(id){
  var textarea=document.getElementsByTagName('textarea')[0];
	var iframe=document.createElement(id);
	iframe.setAttribute('id',id);
	iframe.setAttribute('width',textarea.offsetWidth);
	iframe.setAttribute('height',textarea.offsetHeight);
	textarea.parentNode.appendChild(iframe);
	textarea.style.setProperty('display','none',null);
	setTimeout('loadContent("'+id+'")',3);
}
function loadContent(id){
  var iframedoc=document.getElementById(id).contentDocument;
  iframedoc.open();
  iframedoc.write(document.getElementsByTagName('textarea')[0].value);
  iframedoc.close();
}
window.onload=function(){ initIframe('iframe'); }
//-->
</script>
</head><body>
<textarea cols="90" rows="10"><html><head><link rel="stylesheet" href="http://www.geckozone.org/forum/templates/geckozone/geckozone.css" type="text/css" /></head><body id="BODY"><h3>test</h3></body></html></textarea>
</body></html>
J'essaye ta piste.
priz
Arias
Messages : 7
Inscription : 04 déc. 2005, 23:06

Message par priz »

Cela commence à être pas mal, j'arrive à me débarrasser partiellement du setTimeout en insérant la feuille de style à la fin de la lecture de la fenêtre de l'iframe.

Code : Tout sélectionner

<html><head>
<script>
<!--
var id='iframe';
function initIframe(){
  var textarea=document.getElementsByTagName('textarea')[0];
	var iframe=document.createElement(id);
	iframe.setAttribute('id',id);
	iframe.setAttribute('width',textarea.offsetWidth);
	iframe.setAttribute('height',textarea.offsetHeight);
	textarea.parentNode.appendChild(iframe);
	textarea.style.setProperty('display','none',null);
	setTimeout('loadContent("'+id+'")',1);
}
function loadContent(){
  var textarea=document.getElementsByTagName('textarea')[0];
	var iframedoc=document.getElementById(id).contentDocument;
	var iframewin=document.getElementById(id).contentWindow;
	iframewin.onload=function(){ insertCSS() }
  iframedoc.open();
  iframedoc.write(textarea.value);
  iframedoc.close();
}
function insertCSS(){
	var link=document.createElement('link');
	link.setAttribute('rel','stylesheet');
	link.setAttribute('type','text/css');
	link.setAttribute('href','http://www.geckozone.org/forum/templates/geckozone/geckozone.css');
	document.getElementById(id).contentDocument.getElementsByTagName('head')[0].appendChild(link);
}
window.onload=function(){ initIframe(); }
//-->
</script>
</head><body>
<textarea cols="90" rows="10"><html><head></head><body><h3>test</h3></body></html></textarea>
</body></html>
l'inconvénient c'est que le l'iframe s'affiche sans feuille de styles le temps que le contenu du document soit lu et que la feuille de styles soit appliquée.
priz
Arias
Messages : 7
Inscription : 04 déc. 2005, 23:06

Message par priz »

Je vais choisir la solution du setTimeout sans le onload, mais en mettant une valeur de 10ms juste pour cette version de Firefox (encore une rustine de plus) en espérant que ce bug sera résolu dans la prochaine mise à jour de firefox.
martin
Varan
Messages : 1074
Inscription : 21 janv. 2004, 16:23

Message par martin »

Ok, de retour.
J'ai résolu mon problème, symptômes similaires, mais en fait la cause était autre (pour info, une ligne que j'avais oubliée de commenter, qui passait le designMode à On inutilement une 2e fois, çà bloquait en partie le script avec firefox 1.5 alors que cette erreur passait avec 1.0.7).
Je vais choisir la solution du setTimeout sans le onload, mais en mettant une valeur de 10ms
Je m'excuse, mais j'aime pas. Comment tu fais pour déterminer une valeur qui passera chez tout le monde ? Ce n'est pas parce sur ta machine 10 ms convient que c'est le cas ailleurs.
Utiliser le onload a plus de sens, puisque visiblement on a besoin d'avoir le DOM chargée avant de pouvoir faire d'autres actions.
(Au passage il me semble que firefox a un événement du genre "onDOMLoad", je ne sais plus comment il s'appelle...)
Une autre solution dans certains cas similaires, est de recourir à une fonction récursive, du genre :

Code : Tout sélectionner

function toto() {
  if (!win.document && !win.document.body) {
    setTimeout(toto, 1);
    return;
  }
 action1();
 ...
}
En tout cas, en reprenant ton exemple, je te propose uje solution qui semble bien fonctionner :

Code : Tout sélectionner

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
        "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Document sans titre</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

<script>
<!--
function initIframe(){
  var textarea = document.getElementsByTagName('textarea')[0];
  var iframe = document.createElement('iframe');
  iframe.setAttribute('id','iframe');
  iframe.setAttribute('width',textarea.offsetWidth);
  iframe.setAttribute('height',textarea.offsetHeight);
  textarea.parentNode.appendChild(iframe);
  textarea.style.display = 'none';

  var iframedoc = document.getElementById('iframe').contentWindow.document;
  iframedoc.open();
  iframedoc.write(textarea.value);
  iframedoc.close();
  
  var link = iframedoc.createElement('link');
  link.setAttribute('rel','stylesheet');
  link.setAttribute('type','text/css');
  link.setAttribute('href','http://www.geckozone.org/forum/templates/geckozone/geckozone.css');
  iframedoc.getElementsByTagName('head')[0].appendChild(link);
}

window.onload=initIframe;
//-->
</script>
</head>
<body>
<textarea cols="90" rows="10"><html><head></head><body><h3 class="quote">test</h3></body></html></textarea>
</body>
</html>
j'ai changé contentDocument en contentWindow.document pour que IE soit content et compatible.
Invité

Message par Invité »

Ah je connaissais pas onDOMload, c'est bon à savoir.
Sinon je suis bien d'accord pour le setTimeout mais je n'ai pas encore trouvé d'autre solution. :oops:

Je comprends plus rien :
Lorsque j'essaye ton exemple ça marche, j'essaye avec un autre document et une autre feuille de style ça marche aussi. J'essaye avec ma feuille de style et mon document, il affiche plus les styles :evil:

Je regarde ce week-end à tête reposée la différence entre tout ce bordel.
martin
Varan
Messages : 1074
Inscription : 21 janv. 2004, 16:23

Message par martin »

je précise juste le nom exact de l'événement, que j'ai retrouvé, c'est DOMContentLoaded (et pas "DOMLoad" que j'avais inventé).
Mais c'est pas standard, spécifique à gecko, donc pas malin à utiliser tel quel pour des scripts sur le web...
Répondre

Qui est en ligne ?

Utilisateurs parcourant ce forum : Aucun utilisateur inscrit et 2 invités