Nasze własne $(document).ready();
- Mateusz Żeromski | 2008-12-08 | javascript
Czasem, lecz bardzo rzadko się zdarza iż musimy wykonać operację taką samą jak $(document).ready() tylko bez użycia jQuery. Wydawałoby się to banalne, czyli zastosowanie window.onload, tylko z jedną drobną różnicą. Operacja ready() wykonuje się po wczytaniu html’a, a window.onload – po załadowanu witryny. Takie akcje są zazwyczaj przydatne w sytuacji gdy nasze skrypty będą uruchamiane na wielu różnych witrynach www i nie mamy pewności, czy włączając jQuery nie popsujemy fukcjonalności tej stronki (np może być już tam użyta biblioteka prototype itp itd) a dodatkowo jQuery to dodatkowe 15 kb.
Słowem wstępu
Ta wersja skryptu jak i wszystkie, które zamieszczam na blogu nie nadają się do użycia produkcyjnego – są zbyt mało dopracowane i mało zaawansowane, zawierają sporo ograniczeń, posiadam u siebie wersje produkcyjne, lecz nauka nie polega na ślepym kopiowaniu wszystkiego :)
Zaczynamy
Na początek musimy napisać skrypt do rozpoznawania przeglądarki, temat jest oklepany więc wykorzystujemy skrypcik ze strony http://www.quirksmode.org/js/detect.html. Wygląda on tak
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 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | var BrowserDetect = { init: function () { this.browser = this.searchString(this.dataBrowser) || "An unknown browser"; this.version = this.searchVersion(navigator.userAgent) || this.searchVersion(navigator.appVersion) || "an unknown version"; this.OS = this.searchString(this.dataOS) || "an unknown OS"; }, searchString: function (data) { for (var i=0;i<data.length;i++) { var dataString = data[i].string; var dataProp = data[i].prop; this.versionSearchString = data[i].versionSearch || data[i].identity; if (dataString) { if (dataString.indexOf(data[i].subString) != -1) return data[i].identity; } else if (dataProp) return data[i].identity; } }, searchVersion: function (dataString) { var index = dataString.indexOf(this.versionSearchString); if (index == -1) return; return parseFloat(dataString.substring(index+this.versionSearchString.length+1)); }, dataBrowser: [ { string: navigator.userAgent, subString: "Chrome", identity: "Chrome" }, { string: navigator.userAgent, subString: "OmniWeb", versionSearch: "OmniWeb/", identity: "OmniWeb" }, { string: navigator.vendor, subString: "Apple", identity: "Safari", versionSearch: "Version" }, { prop: window.opera, identity: "Opera" }, { string: navigator.vendor, subString: "iCab", identity: "iCab" }, { string: navigator.vendor, subString: "KDE", identity: "Konqueror" }, { string: navigator.userAgent, subString: "Firefox", identity: "Firefox" }, { string: navigator.vendor, subString: "Camino", identity: "Camino" }, { // for newer Netscapes (6+) string: navigator.userAgent, subString: "Netscape", identity: "Netscape" }, { string: navigator.userAgent, subString: "MSIE", identity: "Explorer", versionSearch: "MSIE" }, { string: navigator.userAgent, subString: "Gecko", identity: "Mozilla", versionSearch: "rv" }, { // for older Netscapes (4-) string: navigator.userAgent, subString: "Mozilla", identity: "Netscape", versionSearch: "Mozilla" } ], dataOS : [ { string: navigator.platform, subString: "Win", identity: "Windows" }, { string: navigator.platform, subString: "Mac", identity: "Mac" }, { string: navigator.platform, subString: "Linux", identity: "Linux" } ] }; BrowserDetect.init(); |
Po wykonaniu tego kodu, mamy dostępny obiekt BrowserDetect oraz wartość która nas interesuje BrowserDetect.browser
Funkcje zwracające ready() dla różnych przeglądarek
Tutaj również muszę zaznaczyć, iż wykorzystałem części kodu z biblioteki jQuery z procedury ready() :). Zwróćcie uwagę jak bzdurne są procedury rozpoznania załadowania treści w IE, Operze i Safari
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 | function IEContentLoaded (w, fn) { // If IE is used, use the trick by Diego Perini // http://javascript.nwbox.com/IEContentLoaded/ var d = w.document, done = false, // only fire once init = function () { if (!done) { done = true; fn(); } }; // polling for no errors (function () { try { // throws errors until after ondocumentready d.documentElement.doScroll('left'); } catch (e) { setTimeout(arguments.callee, 50); return; } // no errors, fire init(); })(); // trying to always fire before onload d.onreadystatechange = function() { if (d.readyState == 'complete') { d.onreadystatechange = null; init(); } }; } function SafariContentLoaded(){ if ( document.readyState != "loaded" && document.readyState != "complete" ) { setTimeout( arguments.callee, 50 ); return; } load(); } function OperaContentLoaded(){ for (var i = 0; i < document.styleSheets.length; i++) if (document.styleSheets[i].disabled) { setTimeout( arguments.callee, 0 ); return; } load(); } |
Oraz funkcja load()
1 2 3 4 | function load(){ alert(a); a=a+1; } |
Tajemniczy switch :)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | switch(BrowserDetect.browser){ case 'Firefox': document.addEventListener( "DOMContentLoaded", load, false ); break; case 'Explorer': IEContentLoaded(window, load); break; case 'Safari': SafariContentLoaded(); break; case 'Opera': OperaContentLoaded(); break; default: window.onload = load(); break; } |
Jak widać w powyższym kodzie rozpoznaje ready() tylko dla Firefoxa, explorera, Safari i Opery. A dla wszystkich innych przeglądarek wykorzystuję zwyczajne window.onload.Ostatecznie otrzymujemy skrypcik który bez jakiejkolwiek komprecji waży niecałe 4 kb.
Podsumowanie
Patrząc na to co zrobiłem to jednak Ameryki nie odkryłem, tylko wykorzystałem już istniejące kody i połączyłem w jedną całość nie używając jQuery. Teoretycznie przedstawiony przezemnie kod nie powinien mieć praktycznego zastosowania, ze względu na objętośc kodu, poniważ wszystko to co przedstawiłem na blogu udało mi się zmieścić w niecałym 1KB, jednakże chciałem przedstawić jak bzdurne jest rozpoznawanie akcji ready() bez używania jQuery, oraz że coś takiego się da zrobić pisząc własny js.
Aha i tak wiem w jQuery jest to lepiej napisane – bo produkcyjnie :)
Tagi: detekcja, javascript, jquery
1 Jan Kraus 2009-02-09 14:21:56
W Prototype też można użyć czegoś podobnego:
document.observe(‘dom:loaded’,function(){ // do something })
2 GreeN 2009-12-13 19:03:59
Jak zrobić aby funkcja window.load = function() { …
działała w operze.
3 piecioshka 2011-08-19 16:43:20
ajajaj, ale tu dużo kodu ;(
@GreeN: opera podobnie jak IE on+…. ale:
utils = this.utils || {};
utils.event = utils.event || {};
utils.event.add = (function(){
var doc = document;
return function(target, eventType, callback) {
if (target.attachEvent) {
utils.event.add = function(target, eventType, callback) {
target.attachEvent(„on” + eventType, callback);
};
} else if (target.addEventListener) {
utils.event.add = function(target, eventType, callback) {
target.addEventListener(eventType, callback, false);
};
}
utils.event.add(target, eventType, callback);
};
})();
utils.event.add(window, „load”, function(){
document.write(„page is loaded…”);
});