2009-10-09 6 views
5

J'ai une table de données qui est générée dynamiquement avec Javascript. Toutes les quelques minutes, la page actualise les données en envoyant une requête Ajax, en récupérant les données du serveur et en remplaçant les données dans la table. Ceci est assez standard, et la table finit par ressembler à ceci:.IE rendu incorrect du contenu dynamique jusqu'à ce qu'un changement de feuille de style soit effectué

Cela fonctionne très bien si je produis les données en vidant la table et en ajoutant progressivement les lignes arrière en Cependant, ce tableau peut potentiellement avoir des milliers de lignes, et il peut potentiellement prendre autant de temps pour générer la table que le navigateur donne à l'utilisateur un "Ce script prend trop de temps à exécuter" des erreurs. J'ai donc réparé ceci en cassant la génération de la table en morceaux et en faisant un peu à la fois en utilisant setInterval.

Cela a bien fonctionné, mais comme la table peut prendre un certain temps à être totalement générée, j'ai essayé d'être intelligent et de faire un pseudo-double-buffering. J'ai une deuxième table qui a son display mis à none pour le cacher, et quand je re-générer la table j'ajoute les rangées à la table cachée un peu à la fois. De cette façon, les données existantes sont visibles pour l'utilisateur jusqu'à ce que la régénération de la table soit terminée, à quel point nous venons de le remplacer par notre nouveau contenu en une fois.

Je fais de mon remplacement avec la ligne de code suivante

$("#loading_area tbody").children().appendTo($("#unplanned tbody").empty()); 

Cela fonctionne très bien sur Firefox, Safari et Google Chrome. Mais sur IE, je reçois le texte suivant:

Ces lignes sont en fait pas vide - le contenu est là si je défilement horizontal assez:

Il semble que la première colonne est plus de 55 000 pixels de large! Et voici la partie vraiment bizarre: le contenu s'affiche correctement dès que je change quelque chose sur le style de la table. Donc, si je change la couleur de la police en vert, IE ré-affichera immédiatement la table, correctement.

Mais je ne peux pas faire le changement directement. Donc, si je dis

$("#unplanned").css("color", "green"); 

alors il ne se rend pas correctement; la couleur change, mais la première colonne reste 55 000 pixels de large. Mais si je fais la modification directement à la feuille de style

document.styleSheets[1].rules[3].style.color = "green"; 

puis il rend la table correctement. J'ai donc fini par corriger cela en faisant un changement de style aléatoire, en basculant la marge du bouton Développer/Réduire entre 1px et 0px, chaque fois que j'ai fini de disposer la table, et cela a fonctionné.

Mon problème est que lorsque j'essaie d'imprimer la page, les lignes sont vides, car le contenu de la page n'est pas correctement rendu à l'imprimante.

Donc, je vais essayer plus de supercherie, probablement juste en basculant quelle table est affichée et en échangeant leurs id s ou quoi que ce soit pour que cela fonctionne. Ma question est: que se passe-t-il ici?Cela semble être un bug dans IE; J'utilise IE8 mais cette même chose arrive sur IE6 et IE7. Je voudrais éviter de tomber dans cette fosse à l'avenir, mais je ne suis pas sûr de ce qui cause cela, donc je ne suis pas vraiment sûr de ce que je devrais éviter. Toute lumière que quelqu'un pourrait donner à ce sujet serait très appréciée.

EDIT: L'échange de la table affichée permet au problème de rendu de disparaître dans le navigateur sans avoir besoin d'un hack de feuille de style, mais le problème d'impression est toujours présent. En fait, le problème d'impression est là même lorsque la table est générée directement sans aucun show/hide ou tricherie d'éléments. Donc, je suis définitivement confus et je ne sais pas ce que je peux faire pour que ce problème disparaisse. Il se peut que je doive faire une page statique distincte juste pour imprimer si je ne peux pas comprendre cela.

+2

J'espère bien que vous aurez une réponse à cette question - j'ai rencontré quelque chose d'étonnamment similaire il y a environ un an. Je n'ai jamais découvert ce qui se passait. A dû ré-outiller ce que je faisais complètement cause de stinkin 'IE – Matt

Répondre

3

ne peut dire que sans un test, mais en général:

  • Assurez-vous que vous utilisez table-layout: fixed. IE est mauvais à deviner auto largeurs de colonne, surtout quand il y a des colspans impliqués. Il est également lent à deviner les largeurs quand il y a beaucoup de lignes. Sortez ceci des mains d'IE en définissant des tailles explicites pour chaque colonne avec une disposition de table fixe.

  • Évitez d'ajouter des lignes à des tables volumineuses. Quand vous dites children().appendTo() jQuery fait toujours chaque appendice à la fois, ce qui devient vite très lent. La meilleure chose que vous pouvez faire pour accélérer les manipulations de table est de définir le lot entier en une seule fois en utilisant innerHTML sur l'élément parent de la table. Bien sûr, la préparation de la chaîne HTML peut être gênante si vous voulez insérer des données (valeurs d'attribut et contenu), car il doit être protégé par HTML. Une solution de contournement consiste à écrire toutes les lignes à la fois avec des valeurs d'espace réservé, puis sur un second passage à remplir les données réelles en définissant .data sur les nœuds de texte et ainsi de suite. Vous devrez également rattacher tous les gestionnaires d'événements que vous mettez sur ces boutons à cette étape, sauf si vous utilisez Live. Je pense qu'en écrivant les lignes avec innerHTML, vous devriez être capable de l'accélérer suffisamment pour se débarrasser des mises à jour partielles basées sur le timeout (ce qui semblerait avoir de mauvaises conditions de course potentielles). Bien sûr, l'alternative basée sur le DOM serait de mettre à jour uniquement les lignes qui ont changé. Lorsque vous utilisez une disposition fixe, puisque les largeurs ne dépendent pas du contenu, vous pouvez diviser votre table en plusieurs tables les unes après les autres.Ils ressembleront à une table, mais vous pouvez traiter chaque table séparément, soit en écrivant son innerHTML en une seule fois, soit en ajoutant ses lignes sans la perte de performance DOM que vous obtenez en ayant des milliers de lignes dans une seule table.

+0

La définition de 'table-layout' à' fixed' a fait disparaître le problème. Vous avez ma gratitude éternelle, et je garderai votre autre conseil à l'esprit la prochaine fois que je ferai quelque chose comme ça. –

1

Vous pouvez simplement avoir deux éléments tbody dans votre table primaire. L'un serait utilisé pour l'affichage et l'autre pour la mise en mémoire tampon. De cette façon, vous pouvez ignorer l'ajout de l'autre tbody et supprimer simplement display.none du tampon pour l'afficher. Ma conjecture est que cela pourrait être un peu plus rapide et peut-être résoudre le problème dans IE.

Une autre méthode (truc?) Pour montrer ou éléments cachés dans une table, je l'ai appris est mise à positionabsolute sur une ligne ou tbody de le cacher, au lieu d'utiliser display. Cela le cache toujours, mais sans altérer la disposition de la table. Vous pourriez essayer de l'utiliser pour cacher le tampon.

Généralement, les tables sont l'un des éléments les plus originaux, même dans les navigateurs modernes. Faire quelque chose de avancé avec eux conduit généralement à ces petits maux de tête, alors bonne chance.

+0

Bonnes suggestions, mais est-il même légal d'avoir deux éléments 'tbody'? J'ai été surpris de voir cette suggestion. Et pourquoi placer la position à l'absolu cacher une rangée? Cela ne semble pas fonctionner pour moi. (J'avais l'habitude de considérer ma connaissance de HTML/CSS/Javascript assez avancée avant de commencer à plonger dans ce genre de choses!) –

+3

"Les rangées de table peuvent être regroupées en une tête de table, pied de table et une ou plusieurs sections de table" http://www.w3.org/TR/html4/struct/tables.html#h-11.2.3 – robertc

+1

'tbody' serait un élément plutôt inutile si vous ne pouviez en avoir qu'un seul. Son point est le regroupement des lignes dans une table. Quant à 'position: absolute', vous l'utilisez en combinaison avec, disons,' visibility: hidden' et un 'z-index' négatif si vous utilisez' display: none' crée des problèmes. Je suis flou sur les détails, mais je suis sûr que j'ai eu une telle situation plus d'une fois. – slikts

1

Avez-vous une largeur définie sur la table? Il me semble que si vous générez la table alors qu'elle est masquée, il se peut qu'elle ne prenne pas en compte la largeur de la fenêtre du navigateur utilisée normalement pour définir la largeur d'une table, de sorte qu'elle retombe au maximum.

+0

Oui, la largeur est définie sur 100% –

+1

Donc, si vous définissez un nombre spécifique de pixels, plutôt que quelque chose qui dépend de la taille de la fenêtre, avez-vous toujours le problème? – robertc

+0

Je n'ai pas eu l'occasion de le découvrir, car les excellents conseils de bibinc ci-dessus ont fait disparaître le problème. Mais je ne voudrais pas d'une largeur fixe = pixel, car le contenu est dynamique et cela doit être visualisé sur différentes tailles d'écran et il y a beaucoup de données donc j'ai vraiment besoin de toute la largeur de l'écran. Bien que si je rencontre de nouveau quelque chose comme ça, je vais essayer de définir une largeur de pixels fixe juste pour voir si cela change quelque chose - merci pour la suggestion. –

Questions connexes