Nasze własne $(document).ready();

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: , ,

Komentarze: 3 do “Nasze własne $(document).ready();”

  1. 1 Jan Kraus

    W Prototype też można użyć czegoś podobnego:

    document.observe(‘dom:loaded’,function(){ // do something })

  2. 2 GreeN

    Jak zrobić aby funkcja window.load = function() { …

    działała w operze.

  3. 3 piecioshka

    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…”);
    });

Napisz komentarz



Wersja mobilna