Κάτι τρέχει με το window.onload

Κώδικας, πληροφορίες, ερωτήσεις και απαντήσεις σχετικές με την JavaScript.

Συντονιστές: WebDev Moderators, Super-Moderators

Απάντηση
Άβαταρ μέλους
skeftomilos
Script Master
Δημοσιεύσεις: 2888
Εγγραφή: 07 Ιαν 2005 07:22
Τοποθεσία: Αθήνα

Κάτι τρέχει με το window.onload

Δημοσίευση από skeftomilos » 28 Φεβ 2006 04:48

Η χρονιά που πέρασε έφερε πολλές και σημαντικές εξελίξεις στον τομέα του scripting στο Web, και η πιο σημαντική ίσως υπήρξε η ευρεία παραδοχή ότι ο διαχωρισμός συμπεριφοράς-περιεχομένου είναι καλό πράγμα. Με απλά λόγια πρέπει να γράφουμε τον JS κώδικα σε ξεχωριστό αρχείο από την HTML σελίδα. Αν αρνηθούμε να το κάνουμε οι φίλοι θα μας προδώσουν, ο/η σύζυγος θα μας απατήσει και - το σημαντικότερο - η γάτα μας θα γεννήσει παρδαλά γατάκια. Επειδή λοιπόν τα πράγματα είναι τόσο σοβαρά, είναι άμεση ανάγκη να μάθουμε πώς γίνεται αυτός διαχωρισμός στην πράξη. Η προφανής λύση είναι να εκμεταλλευτούμε το συμβάν window.onload:

Κώδικας: Επιλογή όλων

window.onload = function() {
  alert('Hello!')
}
Αυτός ο κώδικας μπορεί να μπει σε ξεχωριστό αρχείο με όνομα π.χ. script.js, τον οποίο θα συμπεριλάβουμε στη σελίδα γράφοντας στο τμήμα head:

Κώδικας: Επιλογή όλων

<script type="text/javascript" src="script.js"></script>
Φυσικά δεν αρκεί να εμφανίζουμε μηνύματα Hello, θέλουμε να κάνουμε τη σελίδα μας να αντιδρά και σε συμβάντα. Έστω ότι έχουμε στη σελίδα ένα κουμπί που να λέει Hello:

Κώδικας: Επιλογή όλων

<button onclick="alert&#40;'Hello!'&#41;">Say Hello</button>
Είπαμε πως πρέπει να διώξουμε αυτό τον κώδικα σε εξωτερικό αρχείο, κάτι που μπορεί να γίνει με τον τρόπο αυτό:

Κώδικας: Επιλογή όλων

window.onload = function&#40;&#41; &#123;
  document.getElementById&#40;'hello-button'&#41;.onclick = function&#40;&#41; &#123;
    alert&#40;'Hello!'&#41;
  &#125;
&#125;
Ταυτόχρονα πρέπει να αλλάξουμε τον HTML κώδικα έτσι:

Κώδικας: Επιλογή όλων

<button id="hello-button">Say Hello</button>
Βλέπετε ότι χρειάζεται να δώσουμε ένα id στο button, διαφορετικά θα είναι δύσκολο να το εντοπίσουμε για να του αποδώσουμε το συμβάν. Ο πιο ευθής και συνηθισμένος τρόπος να εντοπίζουμε το στοιχείο της σελίδας που μας ενδιαφέρει είναι η μέθοδος document.getElementById(). Υπάρχουν και άλλοι τρόποι, αλλά δε θα μας απασχολήσουν εδώ. Είναι πιο επείγον να καταλάβουμε τι ακριβώς κάνει ο κώδικας που γράψαμε, γιατί δεν είναι τόσο προφανής όσο φαίνεται.

Στην αρχή φορτώνεται η σελίδα, και στο διάστημα αυτό το κουμπί μας είναι νεκρό. Όσα κλικ και να κάνουμε πάνω του, αυτό δεν αντιδρά. Μόλις ολοκληρωθεί το φόρτωμα της σελίδας, θα τρέξει το συμβάν window.onload. Τότε γίνεται η σύνδεση της εσωτερικής ρουτίνας με το συμβάν onclick του κουμπιού. Προσοχή, η εσωτερική ρουτίνα δε θα τρέξει, μόνο η σύνδεση θα γίνει αυτή τη στιγμή. Από τώρα και στο εξής το κουμπί μας έχει ζωντανέψει. Αν το πατήσει κανείς θα τρέξει η εσωτερική ρουτίνα και θα εμφανιστεί το μήνυμα. Την αποκαλώ έτσι γιατί αυτή η ρουτίνα δεν έχει όνομα, είναι ανώνυμη. Αν την προτιμάτε επώνυμη τότε ο κώδικας θα πρέπει να γίνει έτσι:

Κώδικας: Επιλογή όλων

window.onload = function&#40;&#41; &#123;
  document.getElementById&#40;'hello-button'&#41;.onclick = sayHello
&#125;

function sayHello&#40;&#41; &#123;
  alert&#40;'Hello!'&#41;
&#125;
Όπως βλέπετε η τεχνική αυτή έχει ένα μειονέκτημα, τα στοιχεία της σελίδας μας δεν είναι εξαρχής συνδεδεμένα με τα συμβάντα τους αλλά η σύνδεση γίνεται αργότερα. Το μειονέκτημα αυτό είναι εγγενές με το διαχωρισμό JS-HTML και δε μπορούμε να το αποφύγουμε. Αν είναι ζωτικής σημασίας να μην αφήσουμε κάποιο στοιχείο ανενεργό ούτε για ένα δευτερόλεπτο τότε δεν έχουμε άλλη επιλογή από την inline JavaScript, και να ρισκάρουμε τη συμφορά με τα παρδαλά γατάκια που αναφέρθηκε προηγούμενα.

Για πόσο διάστημα θα παραμείνουν αδρανή τα στοιχεία της σελίδας μας; Εξαρτάται από το μέγεθος της σελίδας και την ταχύτητα σύνδεσης του επισκέπτη. Δυστυχώς τα πράγματα είναι πολύ άσχημα γιατί στο μέγεθος του HTML κώδικα πρέπει να προστεθεί και το μέγεθος των γραφικών της σελίδας. Το window.onload δε θα τρέξει αν πρώτα δε φορτωθεί εντελώς και το τελευταίο γραφικό. Μάλιστα δε θα τρέξει καθόλου αν ο χρήστης σταματήσει το φόρτωμα της σελίδας με το κουμπί Stop. Όλοι οι scripters του κόσμου ονειρεύονται ένα συμβάν onDomLoad που να τρέχει μόλις φορτωθεί η HTML, αλλά τέτοιο πράγμα προς το παρόν δεν υπάρχει και πρέπει να βολευτούμε με ό,τι έχουμε. Μία λύση είναι να γράψουμε λίγο κώδικα στο τέλος του HTML εγγράφου, κάτω και από το tag κλεισίματος </html>:

Κώδικας: Επιλογή όλων

...
</html>
<script type="text/javascript">
  window_load&#40;&#41;
</script>
Πιθανότατα κανένας browser του κόσμου τούτου δεν πρόκειται να διαμαρτυρηθεί για την invalid HTML μας, αλλά βλέπω την εγκυμονούσα γάτα μου και καταλαβαίνετε την ανησυχία μου, ας μην προκαλούμε λοιπόν τη μοίρα μας καλύτερα.

Η μόνη άλλη λύση που μοιάζει να υπάρχει είναι να ενεργοποιήσουμε κάποιον timer που ανά τακτά διαστήματα να ελέγχει για την ύπαρξη του στοιχείου που μας ενδιαφέρει, και να του αποδίδει τότε το σχετικό συμβάν. Στην περίπτωσή μας θα πρέπει να κάνουμε κάτι τέτοιο:

Κώδικας: Επιλογή όλων

var timer = setInterval&#40;function&#40;&#41; &#123;
  if &#40;document.getElementById&#40;'hello-button'&#41;&#41; &#123;
    document.getElementById&#40;'hello-button'&#41;.onclick = function&#40;&#41; &#123;
      alert&#40;'Hello!'&#41;
    &#125;
    clearInterval&#40;timer&#41;
  &#125;
&#125;, 500&#41;
Αυτό θα μας εξασφαλίσει ότι το κουμπί μας δε θα παραμείνει ανενεργό για περισσότερα από 500 msec. Φυσικά μπορούμε να μειώσουμε αυτό το μεσοδιάστημα και έχω δει αρκετούς να ορίζουν interval 10 msec, αλλά κατά τη γνώμη μου δεν είναι ευγενική συμπεριφορά. Μην ξεχνάμε ότι υπάρχει και το tabbed browsing, και ότι έναν επισκέπτης μπορεί συστηματικά να διακόπτει το φόρτωμα πατώντας το Stop γιατί τα γραφικά δεν τον πολυενδιαφέρουν. Ας μην επιβαρύνουμε το σύστημά του με μερικές χιλιάδες εκτελέσεις συμβάντων ανά δευτερόλεπτο.

Το τίμημα αυτής της τεχνικής είναι όπως καταβαίνετε ότι ο κώδικας αρχίζει να μοιάζει με σπαγκέττι. Η δουλειά του JavaScripter είναι ήδη αρκετά απαιτητική και χωρίς την ανάγκη να φροντίζει για όλη αυτή τη γραφειοκρατία. Υπάρχουν κάμποσες διαθέσιμες JS βιβλιοθήκες που μπορούν να απλοποιήσουν αρκετά την κατάσταση, και μια απ' αυτές είναι η Yahoo! UI Library. Αντί να κάνω το σωστό και να σας περιγράψω πώς δουλεύει, θα προτιμήσω να σπαταλήσω το χρόνο σας περιγράφοντας μία δική μου προσέγγιση. Πριν λίγες μέρες έγραψα μια mini βιβλιοθήκη που περιέχει δύο μεθόδους, την progressiveElementLoad και την progressiveListLoad. Στο παράδειγμα που εξετάσαμε θα μπορούσε να χρησιμοποιηθεί η progressiveElementLoad ως εξής:

Κώδικας: Επιλογή όλων

progressiveElementLoad&#40;'hello-button', function&#40;element&#41; &#123;
  element.onclick = function&#40;&#41; &#123;
    alert&#40;'Hello!'&#41;
  &#125;
&#125;&#41;
Η σύνδεση του συμβάντος θα γίνει το αργότερο μισό δευτερόλεπτο μετά το κατέβασμα του κουμπιού. Για να μη σας κουράζω άλλο όσοι ενδιαφέρεστε μπορείτε να δείτε ένα πιο πλήρες demo που χρησιμοποιεί στον server την System.Threading.Thread.Sleep για να προκαλέσει τεχνιτή καθυστέρηση. Τα links αρχικά είναι κόκκινα, και ενώ κατεβαίνει η σελίδα χρωματίζονται με ένα διαφορετικό χρώμα το καθένα:

- Live Demo

Αν αποφασίσετε να χρησιμοποιήσετε τον κώδικα, κάντε το με δική σας ευθύνη. Το μόνο αντάλλαγμα που ζητάω είναι να μου δώσετε μία διεύθυνση για να έρθω να σας αφήσω χάρισμα ένα παρδαλό γατάκι. Σας παρακαλώ, έχει γεμίσει ο τόπος από δαύτα μέσα στο διαμέρισμα, και δε μπορώ πια ούτε ένα βήμα να κάνω χωρίς να κινδυνεύω να πατήσω κανένα. :)
The pure and simple truth is rarely pure and never simple. Ο μη νους δε σκέπτεται μη σκέψεις για το τίποτα.

Άβαταρ μέλους
cherouvim
Script Master
Δημοσιεύσεις: 3137
Εγγραφή: 13 Ιούλ 2005 22:56
Τοποθεσία: Athens, Greece
Επικοινωνία:

Κάτι τρέχει με το window.onload

Δημοσίευση από cherouvim » 28 Φεβ 2006 09:01

Sygharitiria!

To window.onload tha arhisei afou teliosoune ola ta images sto markup alla aneksartita apo to an teliosane ta fortomata olon ton background-image diloseon sto CSS?

Parepiptontos.. zito kai ta pardala gatakia!

Άβαταρ μέλους
skeftomilos
Script Master
Δημοσιεύσεις: 2888
Εγγραφή: 07 Ιαν 2005 07:22
Τοποθεσία: Αθήνα

Κάτι τρέχει με το window.onload

Δημοσίευση από skeftomilos » 28 Φεβ 2006 10:05

Αυτό ακριβώς κοιτούσα χτες γιατί είχα κι εγώ απορία τι γίνεται με τα background images. Οι browsers μοιάζουν να έχουν ασυνεπή συμπεριφορά. IE και Opera περιμένουν το φόρτωμα όλων των γραφικών πριν πυροδοτήσουν το onload, ενώ ο Firefox δε λαμβάνει υπόψη τα background images (Firefox 1.0.7). Μια άλλη αποκλίνουσα συμπεριφορά είναι ότι ο Opera πυροδοτεί το onload ακόμα και αν ο χρήστης πατήσει Stop.

Η αναφορά σε non standard features έχει μάλλον μηδενική πρακτική αξία, αλλά για χάρη της συζήτησης ας αναφέρω μερικά ακόμα πράγματα που μου έκαναν εντύπωση:
- Οι Firefox και Opera παρέχουν μέθοδο window.stop() που διακόπτει προγραμματιστικά το φόρτωμα της σελίδας.
- Ο IE και μόνο αυτός παρέχει το συμβάν window.document.onstop που πυροδοτείται αν πατηθεί το Stop.
- Ο IE παρέχει επίσης το συμβάν img.onabort που τρέχει αν πατηθεί το Stop ενώ φορτώνει μία εικόνα.

Και κάτι ενδιαφέρον. Όλοι οι browsers εμφανίζουν προοδευτικά μία εικόνα ενώ φορτώνεται, όχι όμως αν είναι εικόνα background. Σε αυτή την περίπτωση περιμένουν να φορτωθεί ολόκληρη πριν την εμφανίσουν. Αυτό ίσως είναι επιχείρημα υπέρ της αποφυγής των μεγάλων background images.
The pure and simple truth is rarely pure and never simple. Ο μη νους δε σκέπτεται μη σκέψεις για το τίποτα.

Άβαταρ μέλους
cherouvim
Script Master
Δημοσιεύσεις: 3137
Εγγραφή: 13 Ιούλ 2005 22:56
Τοποθεσία: Athens, Greece
Επικοινωνία:

Κάτι τρέχει με το window.onload

Δημοσίευση από cherouvim » 28 Φεβ 2006 11:09

Poly kali erevna.

Exeis dikio gia ta background images. Enas tropos gia na proideaso ton hristi einai na dino ena background-color shetiko me tin eikona i opoia prokeite na emfanistei.

Opote se mia selida me background: #fff; tha valo se kapio ligo pio skouro element background: #ddd url(bg.png) no-repeat; etsi oste na vaftei amesos i periohi me to anihto gri (#ddd) kai meta na emfanistei i eikona. Fysika to effect afto oute kan synagonizete to <img tag me ena progressive JPG 3/5 levels opou apo ta prota kiolas bytes exeis aisthisi tou ti tha epakolouthisei.


Άβαταρ μέλους
Basilakis
PHP Moderator
Δημοσιεύσεις: 8574
Εγγραφή: 17 Νοέμ 2003 13:03
Τοποθεσία: Womans' Brain
Επικοινωνία:

Κάτι τρέχει με το window.onload

Δημοσίευση από Basilakis » 09 Μαρ 2006 20:50

Έπαθα την πλάηκα μου. Πραγματικά όμως. Άρε skeftomile.. Πάλυ δύσκολο βράδυ θα περάσω... Και θα είναι πάνω απο τον υπολογιστή... Για να τα ψάξουμε και εμείς τώρα αυτά... Συγχαρητήρια ;)

Άβαταρ μέλους
ALKIVIADES
Honorary Member
Δημοσιεύσεις: 1322
Εγγραφή: 07 Απρ 2005 03:39

Κάτι τρέχει με το window.onload

Δημοσίευση από ALKIVIADES » 10 Μαρ 2006 18:02

Πολύ ενδιαφέρον άρθρο και απλά γραμμένο, μπράβο :wink:

Απάντηση

Επιστροφή στο “JavaScript και Frameworks”

Μέλη σε σύνδεση

Μέλη σε αυτήν τη Δ. Συζήτηση: Δεν υπάρχουν εγγεγραμμένα μέλη και 1 επισκέπτης