DOM manipulation tip

Εστω ότι έχουμε ένα μεγάλο html πίνακα, ας πούμε 500 γραμμές x 3 στήλες = 1500 κελιά και θέλουμε να αλλάξουμε δυναμικά με javascript τα περιεχόμενα όλων των κελιών.

Υπάρχουν δύο τρόποι:

Ο προφανής: Δίνουμε ένα μοναδικό id σε κάθε <td>και αλλάζουμε την τιμή του κάθε κελιού απευθείας με κάτι τέτοιο:

document.getElementById("cellId").innerHTML="something";

Και ο «κουλός«:  Δινουμε ένα μοναδικό id σε κάθε <tr> και αλλάζουμε την τιμή του κάθε κελιού κάνοντας reference στο <tr>, δηλαδή:

document.getElementById("rowId").cells[n].innerHTML="something";

Ο «κουλός» τρόπος εκτελείται στο μισό χρόνο και στον ΙΕ και στον Mozilla. Λεπτομέρεια που ορισμένες φόρες κυριολεκτικά κάνει τη διαφορά! 

Advertisements

14 Σχόλια

  1. Paris Apostolopoulos on

    μπούλη καλο το tip δεν το ήξερα thanks!:) mpoulides rulez!

    Παρόλα αυτά νομίζω ότι ο τίτλος είναι λίγο οff topic. Μιας και το tip είναι απλό DOM manipulation (HTML) με Javascript! συμφωνείς;

    Μια απλή υπόθεση όσο αναφορά την διαφορά στην ταχύτητα που μπορεί να είναι κοτσάνα. To td ειναι παιδί του tr λογικά στο δένδρο όταν θα το αναζητήσεις με το td -id λογικά αυτός να μην υλοποιεί γρήγορα το ψάξιμο για να το βρει στο δένδρο με την μία-ή να looparei σε άσχετα πράγματα μέχρι να το βρει. Απο την άλλη το reference του td από το tr ίσως να ‘φορτώνει’ on the background και το array (cells) και να μην διατρέχει items μέχρι να βρει αυτό που θέλει..ή κάτι τέτοιο..αν πεις ότι έτσι και αλλιώς όλα στην μνήμη ίσως η λέξη φορτώνει να μην είναι σωστή..αλλά κάτι τέτοιο σκέφτομαι!

    ευχαριστώ!

  2. mpoulis on

    Σχετικά με τον τίτλο: Στις περιπτώσεις που θα σου φανεί χρήσιμο αυτό το tip κατά 90% θα παίζει και κάποιο http request που θα τραβάει κάποια στοιχεία με τα οποια θα γεμίζεις τον πίνακα. Αρα πρακτικά ο όρος AJAX δεν είναι off-topic.
    Αλλα επειδή το post είναι πολύ τεχνικό και εξειδικευμένο θα συμφωνήσω ότι ο τίτλος θα πρέπει να είναι λιγότερο γενικός οπότε αλλάζει άμεσα.

    Προσπάθησα να σκεφτώ κι εγώ πως μπορεί να εξηγείται και ίσως να συμβαίνει κάτι πιο απλό. Στην πρώτη περίπτωση ψάχνει κάθε φορά σε 2000 items ενώ στη δεύτερη περίπτωση σε 500 συν ένα «καρφωτό» reference (0,1,2,3 κλπ).

  3. Paris Apostolopoulos on

    ναι μάλλον υπερβολικός ο όρος off topic – δεκτό 🙂

    για τον λόγο ναι αυτό προσπάθησα να περιγράψω αλλά μάλλον με κάλυψες με μια πρόταση 😀

    respect!

    η αλήθεια είναι ότι είμαι λιγο της παλιάς σχολής και μάλλον addictive του server side development – πάντα το κοίταζα το θέμα ..πως να πω..κάπως..οφείλω να ομολογήσω ότι το να γράφω JScrit δεν είναι και απο τα αγαπημένα μου – addictive στις strongly typed..μάλλον χα χα!

  4. akindynos on

    Για μένα αυτονόητη λύση θα ήταν κάτι σαν:
    var tab = document.getElementById(‘table-name’);
    var cells = tab.getElementsByTagName(‘TD’);
    υπό την προϋπόθεση βέβαια πως δεν τίθεται θέμα nested tables.

    Μάλιστα αυτή η πρόσέγγιση, ας την πω bytagname, σε Mozilla τρέχει χοντρικά σε μισό χρόνο από την κουλή. Εντυπωσιακό;

    Δυστυχώς σε IE7 τα πράγματα είναι λιιιιγο διαφορετικά. Δηλαδή εντελώς χάλια. Στη μηχανή του IE7 η ταχύτερη επίδοση της bytagname είναι χειρότερη από την αργότερη επίδοση της *προφανούς*.

    Απογοήτευση, ε; Αν ενδιαφέρει το θέμα αξίζει μια ματιά σε μια cross browser λύση, που είναι και πιο ευέλικτη γιατί μπορείς να ζητήσεις όλα τα elements με tag τάδε και class δείνα οπότε αντιμετωπίζεται και η περίπτωση των nested tables
    http://www.robertnyman.com/2005/11/07/the-ultimate-getelementsbyclassname/

    Στον IE7 αποδίδει μεσοβέζικα, δηλαδή στο συγκεκριμένο παράδειγμα η ταχύτητα είναι μεταξύ πραφανούς και κουλ. Αλλά στον Mozilla αποδίδει βέλτιστα.

  5. akindynos on

    Έκανα ένα λαθάκι 🙂

    Με την getElementsByClassName και οι δύο μηχανές αποδίδουν εξίσου γρήγορα! Δηλαδή στο μισό της κουλ! (το λαθάκι ήταν ότι χρησιμοποίησα παλιότερη έκδοση της συνάρτησης)

  6. mpoulis on

    akindynos, την bytagname δεν τη βλέπω και τόσο αυτονόητη γιατί σε αυτές τις περιπτώσεις συνήθως εμφανίζεις tabular data οπου κάθε row είναι ένα record.

    Στην προφανή το element id του καθε td θα είναι κάπως έτσι: RECORDID_fieldname

    Στην κουλ ας πούμε ότι το element id του καθε tr θα είναι σκετο το RECORDID και θα αναφέρεσαι στα πεδία (στηλες) με 0,1,2 κλπ

    Στην bytagname πως θα αναφέρεσαι με ένα σχετικά clean τροπο; Εντάξει μπορείς να υπολογίζεις ότι αν έχεις π.χ. 4 στηλες το πρωτο td του πρωτου row θα είναι το 0, το τρίτο td του δευτερου row θα είναι το 6 κ.ο.κ. Το κάνεις όμως πολύπλοκο, θα αναγκαστείς να γράψεις και μία function που θα κάνει τις αναγκαίες μετατροπές, να την καλείς συνέχεια, στο τέλος ίσως χάσεις αυτό που κέρδισες.

    Αλλά ο πιο ωραίος απ’ όλους μας είναι ο Robert Nyman. Thanks για το url.

  7. cheaplog on

    Δε ξέρω τι είναι το «something» αλλά εφόσον είναι κείμενο, υπάρχει και το innerText / textContent.

  8. Vaggelis on

    Μπούλη,

    την prototype υποθέτω ότι την έχεις δοκιμάσει. Αν ναι από πλευράς απόδοσης πώς σου φαίνεται;

    Ασχολήθηκα λίγο μαζί της, τις τελευταίες μέρες και έχει αρκετά κομψό τρόπο να επιστρέφει τα παιδιά ενός Element (μέθοδος ImmediateDescendants)σαν array από Elements. Αυτό άμεσα λύνει και το πρόβλημα των nested tables αλλά και επεκτείνει τη λειτουργία και σε divs.

    Είναι όμως το ίδιο γρήγορη;

  9. mpoulis on

    @cheaplog
    To something μπορεί να είναι κείμενο σκέτο ή με html. Σωστή η παρατηρηση για τα innerText / textContent αλλά επειδή αντιστοίχως είναι IE/Mozilla specific αποφεύγω να τα χρησιμοποιώ εκτός και αν δεν μπορώ να κάνω διαφορετικά.

    @vaggelis
    Την prototype όχι μόνο δεν την έχω δοκιμάσει αλλά δεν ξέρω καν τι είναι. Δεν στελνεις κανενα url;

  10. cosmix on

    Η χρήση του ‘DOM’ και του ‘innerHTML’ στην ίδια πρόταση είναι διασκεδαστική. Η ειρωνία είναι πως παρ’ότι η υποστήριξη για το karaproprietary™ innerHTML υφίσταται σε όλους τους browsers, τα προβλήματα που πρακτικά απορρέουν από τη χρήση του δεν έχουν καμία σχέση με την θέση του ως de facto και όχι de jure πρότυπο, αλλά το ότι ο μοναδικός browser στον οποίο δε συμπεριφέρεται — σε κάποιες περιπτώσεις — όπως είναι αναμενόμενο είναι ο IE.

    Ίσως η καλύτερη λύση είναι να κάνεις encapsulate τον σωστό τρόπο διαχείρισης του δέντρου ώστε να έχεις τόσο την ευελιξία (και ευκολία έκφρασης) του innerHTML και την ορθότητα του createElement/createTextNode. Υπάρχουν ήδη αρκετές προσπάθειες, μια εκ των οποίων (όχι απαραίτητα καλής απόδοσης, αλλά αρκετά καθαρή) είναι το Builder που συμπεριλαμβάνεται στη βιβλιοθήκη script.aculo.us (η οποία με τη σειρά της ‘εξαρτάται’ από την prototype που ανέφερε ο Βαγγέλης).

    Στο προκείμενο τώρα: Εαν προγραμματίζεις αρκετά σε JavaScript (ή/και χρησιμοποιείς τεχνικές AJAX) θαρρώ πως οπωσδήποτε αξίζει να ρίξεις μια ματιά στο prototype καθώς και το script.aculo.us. Η πρώτη είναι ιδιαίτερα καλογραμμένη (και κάνει σημαντική χρήση closures), αν και αρκετά μεγάλη. Θα τη βρείς εδώ. Η δεύτερη αφορά κυρίως τη διεπαφή με τον χρήστη και προσφέρει εφφέ, δυναμικά widgets κλπ. Το script.aculo.us θα το βρείς εδώ.

    Τα €0.02 μου.

  11. Vaggelis on

    Η prototype είναι μια ωραιότατη βιβλιοθήκη που κάνει τη ζωή των Javascript developers πιο εύκολη. Πάνω σε αυτή έχουν χτιστεί άλλες βιβίοθήκες όπως το scriptaculous και τα moofx.

    http://www.prototypejs.org/ (Το link που λέγαμε)

    ένα trivial παραδειγματάκι:
    π.χ.

    $('mpoulis').addClassName('red_bold').show();

    Σου διαλέγει ένα Element (π.χ. div) με id mpoulis και του προσθέτει (έχει δεν έχει) μια κλάση red_bold και το κάνει visible 🙂

    Έστω:

    Kiwi, banana and apple.


    $('first').replace('kiwibananaapple');

    Αλλάζει τον κώδικα των elements με id ‘first’ με αυτόν που είναι όρισμα στη συνάρτηση replace 🙂

    Πώς σου φαίνεται;

  12. Vaggelis on

    ouch… το WordPress έκανε Parse τον κώδικά μου…

  13. mpoulis on

    Cosmix το post είχε κρατηθεί από το wordpress.
    Βαγγέλη και cosmix, thanks για τις πληροφορίες. Χαζεύω το documentation της prototype και πραγματικά έχει πολύ «ψωμί».

  14. Vaggelis on

    Αγαπητέ Μπούλη,

    πρώτα διάβασε και μπες στο πνεύμα της prototype και στη συνέχεια αφού έχεις καταλάβει τί συμβαίνει προχώρα άμεσα (όπως προτείνει και ο cosmix) σε κάτι όπως moofx ή scriptaculous


Σχολιάστε

Εισάγετε τα παρακάτω στοιχεία ή επιλέξτε ένα εικονίδιο για να συνδεθείτε:

Λογότυπο WordPress.com

Σχολιάζετε χρησιμοποιώντας τον λογαριασμό WordPress.com. Αποσύνδεση / Αλλαγή )

Φωτογραφία Twitter

Σχολιάζετε χρησιμοποιώντας τον λογαριασμό Twitter. Αποσύνδεση / Αλλαγή )

Φωτογραφία Facebook

Σχολιάζετε χρησιμοποιώντας τον λογαριασμό Facebook. Αποσύνδεση / Αλλαγή )

Φωτογραφία Google+

Σχολιάζετε χρησιμοποιώντας τον λογαριασμό Google+. Αποσύνδεση / Αλλαγή )

Σύνδεση με %s

Αρέσει σε %d bloggers: