Toon posts:

FireFox 1.5 render probleem

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik probeer een grid te ontwikkelen, waarbij de table header absolute is gepositioneerd. Deze header is een aparte table, en de data zit ook in een losse table. De cellen van de header, moeten dus handmatig op de gewenste breedte worden gebracht waarbij de celbreedte in het data gedeelte bepalend is voor de cellen van de header.

Waar ik tegenaan loop is dat in IE 6 standards mode, en Opera 9 het geheel perfect wordt geschaald maar FireFox 1.5 er een potje van maakt. Wat me verder opvalt is dat er wel heel vreemde waardes terugkomen van zowel FireFox als Opera met betrekking tot clientWidth. clientWidth zou de viewport van het element moeten returnen, en niet de offsetWidth - (borders+padding). Op zich is dit niet een probleem omdat ik de waardes niet gebruik, maar het viel me wel op. Misschien is mijn definitie van clientWidth te veel geeikt op wat IE er onder verstaat, namelijk het aantal pixels zichtbare gedeelte van een element zonder scrollbar.

Als ik kijk naar de offsets die worden verkregen dan kloppen deze wel in alle browsers. De offset die terugkomt is netjes opgehoogd met 2, omdat er een border links en een border rechts van het cell element zit.

Het wordt echter pas echt bizar als ik de code die is gegenereerd naar een los document plak, daar exact dezelfde stylesheet op los laat, en FireFox opeens wel de boel goed renderd. Ben ik dus op een bug gestuit waarbij het renderen niet goed gaat als via Javascript de elementen worden gewijzigd?

De cellen krijgen wel de goede breedte als het door Javascript wordt gewijzigd, maar als niet de table een width krijgt.

this.grid.header.table.style.width = offset + 'px';

Alleen heeft FireFox een width nodig op een table om overflow:hidden te kunnen gebruiken op een cell. Dus ik kan niet zonder, en op zich zou dit ook geen probleem moet zijn want dezelfde source in een testcase doet het wel goed met een breedte op de table.

De code verantwoordelijk voor het resizen waarbij grid.sizes en precalculated array is met offsetWidths van de cellen in de data table. Elke cell krijgt de offsetWidth uit de array, en om boxmodel issues te voorkomen krijgen ook de data cellen waarmee de array initieel is gevuld, ipv hun oude width hier hun originele offsetWidth als nieuwe width. De css voor alle cellen is identiek, behalve dat de header een backgroundimage krijgt.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
view_details.prototype.redraw = function(){
    
                    // resize data cells
    var cells = this.grid.rows[0].cells;
    for(var i=0;i<cells.length;i++){
        cells[i].element.style.width = this.grid.sizes[i] + 'px';
    }   
    
                    // resize header cells
    var offset = 0;
    cells = this.grid.header.cells;
    for(var i=0;i<cells.length;i++){
        cells[i].element.style.width = this.grid.sizes[i] + 'px';
                        offset += cells[i].element.offsetWidth;
    }   
    
                    // resize tables zodat overflow hidden gebruikt kan worden
    this.grid.table.style.width = offset + 'px';
    this.grid.header.table.style.width = offset + 'px';
                    
                    // zet breedte van header parentNode
    this.grid.header.element.style.width = this.grid.element.clientWidth + 'px';
};


De html die wordt gegenereerd:

code:
1
<div class="detail"><table style="margin-bottom: 200px; width: 561px;" class="data" border="0" cellspacing="0"><colgroup span="5"><col><col><col><col><col></colgroup><tbody><tr><td style="width: 286px;"><nobr>This is a long string which should cause an overflow</nobr></td><td style="width: 37px;"><nobr>580KB</nobr></td><td style="width: 83px;"><nobr>XML Document</nobr></td><td style="width: 91px;"><nobr>29-Nov-02 19:31</nobr></td><td style="width: 19px;"><nobr>xml</nobr></td></tr></tbody></table></div><div style="overflow: hidden; width: 1000px;" class="header-wrap"><table style="width: 561px;" class="header" border="0" cellspacing="0"><tbody><tr><td style="width: 286px;">Name2</td><td style="width: 37px;">Size</td><td style="width: 83px;">Type</td><td style="width: 91px;">Last Modified</td><td style="width: 19px;">Extension</td></tr></tbody></table></div>


In de demos onder zijn er aan de rechterkant de berekende waardes getoond. De clientWidth is hier opvallend in zowel FireFox als Opera.

En het resultaat live:

http://www.mschopman.demon.nl/grid/

En als de gegenereerde sourcecode die indien niet gegenereerd wel door FireFox goed wordt getoond:

http://www.mschopman.demon.nl/grid/testcase.htm

[ Voor 15% gewijzigd door Verwijderd op 14-01-2006 17:59 ]


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Het table layout model is wel anders dan het boxmodel ;)
Als je pixel-precisie wilt kan je denk ik het beste ook gebruik maken van table-layout:fixed - dat lijkt je probleem hier ook op te lossen :)

Intentionally left blank


  • djluc
  • Registratie: Oktober 2002
  • Laatst online: 20-02 15:44
Misschien snap ik het niet helemaal maar waarom zitten die headers niet gewoon in de thead van de tabel?

Verwijderd

Topicstarter
Crisp, beide layouts van de table staan op fixed. Ik denk ook niet dat daar het probleem zit, omdat de gegenereerde code in een losse html pagina het wel goed doet onder FireFox. Ik vermoed dat FireFox over zijn nek gaat op het moment dat je via Javascript de waardes gaat toewijzen.

De css die op dit gedeelte van toepassing is. Border-collapse is uitgeschakeld omdat je dit a) in alle browsers een andere uitwerking heeft, en b) omdat je zo nooit een border-left of border-right kunt definieren voor een outset effect.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
.detail{
    position:relative;
    overflow:auto;
    height:300px;
    width:1000px;
}
.detail{
    padding-top:20px;
}

.grid{
    position:relative;
}
.grid table{
    /*border-collapse:collapse;*/
    table-layout:fixed;

}


.grid td{
    border:1px solid #c0c0c0;
    /*padding:1px 5px;*/
    padding:0;
    white-space:nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.grid div.header-wrap{
    position:absolute;
    top:0px;
    left:0px;
    height:19px;
    overflow:hidden;
    background-image:url('colheadbg.gif');  
}
.grid div.header-wrap table.header{
    height:19px;
}


Djluc, ik zal even wat meer records toevoegen, dan wordt het idee wat duidelijker van het grid.

[ Voor 56% gewijzigd door Verwijderd op 14-01-2006 18:09 ]


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Verwijderd schreef op zaterdag 14 januari 2006 @ 18:06:
Crisp, beide layouts van de table staan op fixed. Ik denk ook niet dat daar het probleem zit, omdat de gegenereerde code in een losse html pagina het wel goed doet onder FireFox. Ik vermoed dat FireFox over zijn nek gaat op het moment dat je via Javascript de waardes gaat toewijzen.
mmz, je hebt gelijk. Markant is dat zodra ik de Edit CSS sidebar open ik Ff opeens de header opnieuw zie renderen met de juiste afmetingen. Het lijkt dus inderdaad wel op een (re)renderbugje.

Wat je zou kunnen proberen is om die renderslag te forceren, bijvoorbeeld door 'm even op display:none te zetten oid...

Intentionally left blank


Verwijderd

Topicstarter
Je bedoelt voor het renderen de header op display:none zetten, dan de waardes toekennen, dan de header weer op display:block zetten om zo een redraw in de Gecko engine te forceren?

edit:

Zojuist geprobeerd, het is nog grappiger: bij display:none wordt geen enkele width declaratie meegenomen, en bij display:block is elke cell zijn offsetWidth breedte :X :P

Bij visibility hidden/visible nog steeds incorrecte breedtes.

Wat me ook opvalt is dat de overflow hidden eigenlijk genegeerd wordt. De laatste column zou een overflow moeten forceren. Die wordt dus niet uitgevoerd als Javascript de breedte van de column zet. Die overflow is er wel in de testcase met de gegenereerde sourcecode http://www.mschopman.demon.nl/grid/testcase.htm. :)

Ik denk dat ik maar eens in bugzilla een kijkje ga nemen of er hiervoor iets is aangemeld. Ik zag al dat de lijst met bugs rondom tables echt enorm is

https://bugzilla.mozilla....t=render+javascript+table

En die clientWidth, is mijn interpretatie nu verkeerd of gaan zowel FireFox als Opera hier de fout in? Dit klopt volgens mij ook niet :?

Opera heeft ook moeite met overflow zag ik, de tekst mag blijkbaar over de border van een cell lopen :P

[ Voor 96% gewijzigd door Verwijderd op 14-01-2006 18:35 ]


Verwijderd

Topicstarter
Ik had eerst zoiets van, FF1.5 is gewoon foobar. Echter, het begon me totaal te irriteren en ik moest en zou het werkend krijgen. Nu ... na heel wat uurtjes debugging, en gedoe heb ik het volgende moeten constateren:

a) Voordat je cell widths gaat zetten met JavaScript moet je zorgen dat de table in kwestie al de breedte heeft die het gaat krijgen. IE en Opera doen het wel goed.

Dit is zowiezo lastig, omdat je de table wilt gaan sizen met de som van de cell offsetWidths. Die weet je niet als je de cel nog niet de width hebt gegeven. Niet erg handig dus.

b) Zet geen width op col elementen, FF1.5 berekend ze niet correct. Zet ze op de eerste row in de table, en het gaat wel goed. IE en Opera doen het wel goed.

c) Zodra je een padding-left of padding-right gaat definieren gaat FireFox stuiteren. Zelf als je cells*padding bij de table width optelt. Wederom geen problemen met Opera en IE.

Nu alleen dus nog punt c, .. maar wat een werk moet je er in steken.

[ Voor 11% gewijzigd door Verwijderd op 16-01-2006 20:47 ]


  • djluc
  • Registratie: Oktober 2002
  • Laatst online: 20-02 15:44
Ik zie dat je inderdaad die records hebt toegevoegd maar ik zie het nut nog steeds niet, kan je het vertellen? Ben wel benieuwd aangezien je hier zoveel tijd in steekt.

  • faabman
  • Registratie: Januari 2001
  • Laatst online: 08-08-2024
@gordijnstok: probeer je nu functionaliteit die al gewoon in firefox zit na te maken?

Wanneer je bij de volgende structuur je tbody een beperkte hoogte en overflow:auto meegeeft dan rendert firefox een scrollbar wanneer de hoogte va de rijen buiten de height valt...

HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<table>
 <thead>
  <tr>
   <th>kopje</th>
   <th>kopje</th>
   <th>kopje</th>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td>celletje</td>
  </tr>
  <!-- en hier nog een hoop extra rijen -->
 </tbody>
</table>


voorbeeldje

[ Voor 57% gewijzigd door faabman op 16-01-2006 21:13 . Reden: lekker zin gebakken :D ]

Op zoek naar een baan als Coldfusion webdeveloper? Mail me!


Verwijderd

Topicstarter
De bedoeling is een grid, met meerdere views op een enkele dataset. Dus dat je kunt schakelen tussen list, details, thumbs, preview zonder dat daarvoor een reload hoeft plaats te vinden. Waarbij de views met een grid/list vorm resizable , sortable en movable headers hebben, en waarbij elke cell een listener kan hebben zodat de content kan reageren op acties, bijvoorbeeld de context van de content aanpassen naar gelang de cellbreedte.

De content moet ook scrollbaar zijn met een fixed header. De enige manier om dit crossbrowser te bereiken is om een los element te synchronizeren omdat IE overflow auto/scroll toepast op alle cellen als je deze toewijst aan de tbody.

De grafische gedeeltes zijn multithreaded zodat het geheel goed blijft performen. Als je selecties worden dus ook meegenomen, als je gaat switchen en blijven gewoon actief.

Dan moet er nog een livegrid achtige functionaliteit in maar die is an sich niet zo lastig als een simpele tabel resizen omdat elke browser weer anders reageert.

.. dat wordt de bedoeling en dan moet het ook crossbrowser ook ...

echter dan moet FireFox wel meewerken, nog zoiets banaals:

Als ik in onderstaande code hier de gecommente lijn ga enablen, gaat FireFox de columns compleet niet meer voorzien van overflow 8)7 Gewoon een getter aanroepen en assignen aan een private var, .. dus dat lijkt me een concurrency issue

//var offsetWidth = cells[j].element.firstChild.offsetWidth;

Kortom, .. die 1.5 is wat mij betreft echt een zooitje.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
view_details.prototype.calculateByDataColumn = function(){
    this.start = new Date().getTime();
    
    var cells = this.grid.rows[0].cells;
    document.getElementById('sizes').innerHTML = "target width:<br>";
    for(var j=0;j<cells.length;j++){
        if(typeof this.grid.sizes[j] == 'undefined'){
            this.grid.sizes[j] = 0;
        }
        //var offsetWidth = cells[j].element.firstChild.offsetWidth;
        //this.grid.sizes[j] = parseInt(offsetWidth);
                
        this.grid.sizes[0] = 286;
        this.grid.sizes[1] = 37;
        this.grid.sizes[2] = 83;
        this.grid.sizes[3] = 91;
        this.grid.sizes[4] = 19;


        document.getElementById('sizes').innerHTML += j + ": " + this.grid.sizes[j] +"<br>";
    }
    
    
};

[ Voor 55% gewijzigd door Verwijderd op 16-01-2006 21:28 ]


  • djluc
  • Registratie: Oktober 2002
  • Laatst online: 20-02 15:44
Kon je met IE niet middels een lelijke hack, ik geloof een div in een tabel, dit scrollen alsnog voor elkaar krijgen?

Verwijderd

Topicstarter
Ja .. wat denk je dat ik heb gedaan? :P Voor FireFox moet je dan this.element.style.overflow = '-moz-scrollbars-none'; toevoegen :)

Maar ik heb zojuist nog maar een bug toegevoegd..
https://bugzilla.mozilla.org/show_bug.cgi?id=323664

Verwijderd

Topicstarter
Even een update, ik heb namelijk de oplossing gevonden. Overflow:hidden wordt door gecko genegeerd als je niet direct bij het genereren van het table element een width opgeeft.

Je verwacht dat als je op een later moment een width toepast op het table element dat hij de overflow regels zal respecteren maar niets is minder waar. Initieel dus op een willekeurige hoeveelheid px width zetten. Dit is in de laatste builds van FireFox nog niet opgelost.

code:
1
2
3
4
5
6
7
    this.table = document.createElement('table');
    this.table.className = 'data';
    this.table.setAttribute("cellSpacing","0");
    this.table.setAttribute("cellPadding","0");
    this.table.style.width = '0px'; // necessary for Gecko, or else overflow:hidden is ignored
    
    this.element.appendChild(this.table);

Verwijderd

Topicstarter
Het was uiteindelijk een zware bevalling. Zowel tussen de browsers, als tussen de doctypes zat flinke verschillen in zowel IE, Opera als Gecko. Opera is nog steeds een zorgenkindje, omdat Opera het renderen niet helemaal jofel uitvoert.

Die moet ik nu helaas met de volgende constructie een duw geven:
this.grid.header.element.style.display='none';
this.grid.header.element.style.display='block';

Ik zeg, tel de variaties...
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
view_details.prototype.redraw = function(){
    this.start = new Date().getTime();

    //this.grid.table.style.width = 'auto';
    //this.grid.header.table.style.width = 'auto';
        
    var isQuirks = document.compatMode == 'BackCompat' ? true : false;
    var isOperaQuirks = document.compatMode == 'QuirksMode' ? true : false;

    var adjustToBoxModel = false;
    if(window.getComputedStyle || isQuirks){
        adjustToBoxModel = true;
    }
    
        
    var boxModelCellAdjustment = [];
    cells = this.grid.header.cells;
    for(var i=0;i<cells.length;i++){
        var cell = cells[i];
        // determine padding and border for boxmodel compensation
        if(adjustToBoxModel){
            boxModelCellAdjustment[i] = cell.getComputedStyle('padding-left') + cell.getComputedStyle('padding-right') + cell.getComputedStyle('border-left-width') + cell.getComputedStyle('border-right-width');
        }
        
        if(isQuirks){
            // IE Quirksmode
            if(document.all){
                cell.element.style.width = (this.grid.sizes[i]+boxModelCellAdjustment[i]) + 'px';
            // Gecko Quirksmode
            }else{
                cell.element.style.width = this.grid.sizes[i] + 'px';
            }
        }else{
            cell.element.style.width = this.grid.sizes[i] + 'px';
        }
                
        // determine padding and border for boxmodel compensation
        if(adjustToBoxModel){
            boxModelCellAdjustment[i] = cell.getComputedStyle('padding-left') + cell.getComputedStyle('padding-right') + cell.getComputedStyle('border-left-width') + cell.getComputedStyle('border-right-width');
        }
    }   
    

    // UPDATE BODY
    var tableWidth = 0;
    var boxModelTableAdjustment = 0;
    var c = this.grid.table.getElementsByTagName('colgroup')[0].childNodes;
    var i = c.length;

    while(i--){
        if(adjustToBoxModel){
            // In IE quirksmode, the table width need to be increased with total cell padding and borderwidth
            // The cells itself, do not need to be adjusted with total cell padding and borderwidth
            if(isQuirks){
                // IE and Gecko quirks
                c[i].style.width = this.grid.sizes[i]+boxModelCellAdjustment[i] + 'px';
                tableWidth += this.grid.sizes[i];
                
            // W3C Boxmodel
            }else{
                c[i].style.width = (this.grid.sizes[i] + boxModelCellAdjustment[i]) + 'px';
                tableWidth += this.grid.sizes[i];
            }
            
            // Adjustment for header table width
            boxModelTableAdjustment += boxModelCellAdjustment[i];
        
        // IE standards mode
        }else{
            c[i].style.width = this.grid.sizes[i] + 'px';
            tableWidth += this.grid.sizes[i];
        }
    }
    
    // IE in quirks mode needs an auto value as table width, 
    // or else resizing headers look really bad and all columns move
    if(isQuirks){
        // IE and Gecko quirks
        this.grid.table.style.width = 'auto';
        this.grid.header.table.style.width = 'auto';
    }else{
        if(navigator.userAgent.indexOf('Opera') == -1){
            this.grid.table.style.width = tableWidth + 'px';
            this.grid.header.table.style.width = (tableWidth+boxModelTableAdjustment) + 'px';
        }
    }
    this.grid.header.element.style.width = this.grid.element.clientWidth + 'px';
    
    var renders = document.getElementById('renders');
    renders.value = (new Date().getTime() - this.start) / 1000 + ' ms';
    document.getElementById('debug').value = document.getElementById('listview').innerHTML;
};

[ Voor 8% gewijzigd door Verwijderd op 02-04-2006 22:22 ]

Pagina: 1