Toon posts:

[Javascript/Prototype] rijen verbergen wil niet lukken in IE

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik ben bezig met een functie die door middel van het aanvinken van een checkbox, een aantal rijen verbergt in een tabel.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
<table>
  <tr class="oud">
    <td>Dit is een rij die verborgen kan worden</td>
    <td>Lalala</td>
  </tr>
  <tr>
    <td>Deze rij blijft staan</td>
    <td>Lalala</td>
  </tr>
  <tr class="oud">
    <td>Dit is een rij die verborgen kan worden</td>
    <td>Lalala</td>
  </tr>


Het is de bedoeling dat dit via JavaScript gebeurd, daarbij maak ik gebruik van het Prototype Javascript Framework. Hiermee kan ik met behulp van de volgende functie alles met de class "oud" in een array stoppen.

code:
1
2
3
<script type="text/javascript">
  var elementList = document.getElementsByClassName("oud");
</script>


Waarna ik met behulp van de volende code alles met de class "oud" kan verbergen:
code:
1
2
3
4
5
<script type="text/javascript">
for ( keyVar in elementList ) {
  Element.hide(elementList[keyVar]);
}
</script>


Onder Firefox (1.5.0.1) en Opera (8.53) werkt dit (bijna) perfect. (Hij doet het onder Firefox maar wel met een error.) Onder Internet Explorer (6 en 7) werkt dit echter helaas niet, hij geeft dan de fout 'style' is leeg of geen object. Deze lijkt op de error die ik krijg in Firefox:

code:
1
2
3
Error: element.style has no properties
Source File: scripts/prototype.js
Line: 860


Het ligt dus aan prototype, nou heb ik even op de Scriptaculous wiki gekeken (die framework gebruik ik ook namelijk) (Link: http://wiki.script.aculo.us/scriptaculous/show/Element.hide)
maar daar wordt ik niks wijzer van, ik heb daarna maar geprobeerd om in CSS verschillende display-waarden te geven aan deze class ( display: table-row; ) maar ook dit heeft niet geholpen.

Heeft iemand een idee hoe ik dit kan oplossen? Mocht iemand zich afvragen wat Prototype is, kijk dan hier: http://prototype.conio.net/

code:
1
2
3
4
5
6
  hide: function() {                                          // Line 857
    for (var i = 0; i < arguments.length; i++) {     // Line 858
      var element = $(arguments[i]);                  // Line 859
      element.style.display = 'none';                 // Line 860 
    }
  },

  • Gonadan
  • Registratie: Februari 2004
  • Nu online

Gonadan

Admin Beeld & Geluid, Harde Waren
Probeer eens om een CSS stijl 'oud' aan te maken met wat nutteloze settings :)

Look for the signal in your life, not the noise.

Canon R6 | RF 24-70 f/2.8 L | 50 f/1.8 STM | 430EX II
Sigma 85 f/1.4 Art | 100-400 Contemporary
Zeiss Distagon 21 f/2.8


Verwijderd

Topicstarter
Gonadan schreef op vrijdag 24 maart 2006 @ 17:33:
Probeer eens om een CSS stijl 'oud' aan te maken met wat nutteloze settings :)
Dat had ik al gedaan ;)
... ik heb daarna maar geprobeerd om in CSS verschillende display-waarden te geven aan deze class ( display: table-row; ) maar ook dit heeft niet geholpen. ...

[ Voor 3% gewijzigd door Verwijderd op 25-03-2006 00:46 ]


Verwijderd

Topicstarter
Erg raar, ik probeerde in plaats van een "for ( keyVar in elementList ) ", "for (count = 0; count < elementList.length; count++)" te gebruiken, en nou doet hij het wel... erg vreemd! Dit is toch gewoon hetzelfde?

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:58

crisp

Devver

Pixelated

Verwijderd schreef op zaterdag 25 maart 2006 @ 01:09:
Erg raar, ik probeerde in plaats van een "for ( keyVar in elementList ) ", "for (count = 0; count < elementList.length; count++)" te gebruiken, en nou doet hij het wel... erg vreemd! Dit is toch gewoon hetzelfde?
for-in constructs nemen ook prototyped methods mee:
JavaScript:
1
2
3
Array.prototype.foo = function() { alert('foo'); }
var a = new Array(), keyVar;
for (keyVar in a) alert(keyVar + ': ' + a[keyVar]);


een beetje stom dat Prototype in z'n methods niet eerst checked of het argument wel een HTML element is.

[ Voor 13% gewijzigd door crisp op 25-03-2006 12:41 ]

Intentionally left blank


Verwijderd

Dus dan zou je zo alle element moeten krijgen en niet de prototyped method;
code:
1
2
3
4
5
for ( keyVar in elementList ) {
  if( !isNaN(keyVar) ) {
    Element.hide(elementList[keyVar]);
  }
}

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:58

crisp

Devver

Pixelated

Verwijderd schreef op zaterdag 25 maart 2006 @ 14:23:
Dus dan zou je zo alle element moeten krijgen en niet de prototyped method;
code:
1
2
3
4
5
for ( keyVar in elementList ) {
  if( !isNaN(keyVar) ) {
    Element.hide(elementList[keyVar]);
  }
}
nee, want stel nu dat je een dergelijke array hebt:
JavaScript:
1
2
3
var a = new Array();
a['foo'] = 'bar';
a['woei'] = 'foo';

Wat je moet doen is expliciet kijken of iets een prototyped method is:
JavaScript:
1
if (!Array.prototype[keyVar]) { }

of nog mooier via hasOwnProperty:
JavaScript:
1
if (a.hasOwnProperty(keyVar)) { }

note dat oudere browser hasOwnProperty niet ondersteunen, maar dat valt te fixen :P
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
if (!Object.prototype.hasOwnProperty)
{
    Object.prototype.hasOwnProperty = function(property)
    {
        try
        {
            var prototype = this.constructor.prototype;
            while (prototype)
            {
                if (prototype[property] == this[property])
                {
                    return false;
                }
                prototype = prototype.prototype;
            }
        }
        catch (e) { }

        return true;
    }
}


Maar in dit geval zou nmm de hide method in Prototype type-checking moeten doen: type moet 'object' zijn en een style-property hebben. Iets als dit dus:
JavaScript:
1
2
3
4
5
6
7
  hide: function() {
    for (var i = 0; i < arguments.length; i++) {
      var element = $(arguments[i]);
      if (element && typeof element == 'object' && element.style)
        element.style.display = 'none';
    }
  },

Dat valt onder defensief programmeren.

Probleem met libraries als Prototype is echter dat je er naar mijn mening niet aan moet beginnen als je te weinig kennis van javascript hebt, en er geen behoefte meer aan hebt als je wel genoeg kennis van javascript hebt :P

[ Voor 18% gewijzigd door crisp op 25-03-2006 14:39 ]

Intentionally left blank


Verwijderd

Maar je weet toch al dat elementList een lijst met elementen is, dus elementList kan nooit die array zijn die jij als voorbeeld geeft.
En daarom zijn alleen de nummers elementen...

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:58

crisp

Devver

Pixelated

Verwijderd schreef op zaterdag 25 maart 2006 @ 15:05:
Maar je weet toch al dat elementList een lijst met elementen is, dus elementList kan nooit die array zijn die jij als voorbeeld geeft.
En daarom zijn alleen de nummers elementen...
In deze situatie wel, maar ik trek het wat generieker en geef wat best-practices tips.
En als je al weet dat je gewoon de numerieke elementen moet hebben dan zou ik gewoon zoiets doen:
JavaScript:
1
2
3
4
5
var el, i = 0;
while ((el = elementList[i++]))
{
  Element.hide(el);
}

Maar dan nog raad ik type-checking aan in de hide method, zeker in een generieke library misstaat dat niet.

[ Voor 4% gewijzigd door crisp op 25-03-2006 15:16 ]

Intentionally left blank


Verwijderd

Topicstarter
Bedankt iedereen, ik heb het nu dus werkend gekregen, maar het vervelende is, dat als ik een tabel heb met zo'n 600 items die verborgen moeten worden, en het onder IE wil gaan verbergen, het meer dan 10 seconden duurt voordat hij al deze rijen verborgen heeft (Firefox is daar al een stuk sneller mee met slechts 2 seconden, maar ik weet dat de bezoekers van mijn website nog steeds vooral Internet Explorer gebruiken).

Wat mij dus handig leek, is dat er een manier was om via JavaScript de display waarde van de class "oud" te veranderen. Ik weet wel dat de functie style.setProperty bestaat maar zover ik weet werkt dit alleen met DOM elementen (zoals Prototype dus ook doet volgens mij met getElementsByClassName, hij zet alle DOM elementen met de class "oud" in een array).

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:58

crisp

Devver

Pixelated

Dit gaat toch wel aardig rap:
JavaScript:
1
2
3
4
5
6
7
8
9
10
function verberg()
{
    var table = document.getElementById('mytable');
    var rows = table.getElementsByTagName('tr');
    var i = 0;
    while ((row = rows[i++]))
    {
        if (row.className == 'oud') row.style.display = 'none';
    }
}

Intentionally left blank


Verwijderd

Topicstarter
crisp schreef op zondag 26 maart 2006 @ 23:06:
Dit gaat toch wel aardig rap:
JavaScript:
1
2
3
4
5
6
7
8
9
10
function verberg()
{
    var table = document.getElementById('mytable');
    var rows = table.getElementsByTagName('tr');
    var i = 0;
    while ((row = rows[i++]))
    {
        if (row.className == 'oud') row.style.display = 'none';
    }
}
Ook met 600 rijen in Internet Explorer? Dit doet in feite hetzelfde als de andere manier, en duurt ook bij mij toch nog steeds zeker 10 seconden onder IE.

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:58

crisp

Devver

Pixelated

Verwijderd schreef op maandag 27 maart 2006 @ 09:00:
[...]


Ook met 600 rijen in Internet Explorer? Dit doet in feite hetzelfde als de andere manier, en duurt ook bij mij toch nog steeds zeker 10 seconden onder IE.
Ja, in een tabel met 600 rijen was het verbergen een kwestie van milliseconden.
Dit is niet hetzelfde als wat Prototype doet; getElementsByClassName is generieker en een stuk duurder; het gaat sowieso alle elementen af (niet enkel TR's) en gebruikt een reguliere expressie om te testen op className - iets wat niet nodig is als je vantevoren weet dat je elementen maar 1 class hebben.

Intentionally left blank

Pagina: 1