koddla

Yazılımcıları bilgi ile güçlendirir.

jQuery’nin $.ready() işlevinin saf JavaScript eşdeğeri

jQuery’nin harika .ready() işlevi hepimiz biliyoruz :

$('document').ready(function(){});

Ancak, bir kütüphane olmadan standart JavaScript ile yazılmış bir işlevi çalıştırmak istediğimi ve sayfa işlemeye hazır olur olmaz bu işlevi başlatmak istediğimi varsayalım. Bunun için hangi yaklaşım doğru olur?

Aşağıdakini yapabiliriz:

window.onload="myFunction()";

Veya body etiketi kullanabiliriz :

<body onload="myFunction()">

Veya her şeyden sonra sayfanın alt kısmında body‘nin içinde aşağıdaki betiği çalıştırabiliriz:

<script type="text/javascript">
    myFunction();
</script>

jQuery’ninki gibi bir veya daha fazla işlevi yayınlamanın tarayıcılar arası (eski/yeni) uyumlu yöntemi nedir?

Tüm tarayıcılar arası uyumluluğu sağlayan bir kütüphanenin yokluğunda yapılacak en basit şey, gövdenin sonundaki kodunuzu çağırmaktır. Bu, bir onload işleyicisinden daha hızlı yürütülür, çünkü bu, tüm görüntülerin yüklenmesini değil, yalnızca DOM’nin hazır olmasını bekler. Ve bu her tarayıcıda çalışır.

<!doctype html>
<html>
<head>
</head>
<body>
Your HTML here

<script>
// self executing function here
(function() {
   // your page initialization code here
   // the DOM will be available here

})();
</script>
</body>
</html>

Modern tarayıcılar için (IE9 ve daha yeni ve herhangi bir Chrome, Firefox veya Safari sürümü) herhangi bir yerden çağırabileceğiniz bir yöntem istiyorsanız (çağıran komut dosyasının nerede olduğu konusunda endişelenmeden) şöyle bir şey kullanabilirsiniz:

function docReady(fn) {
    // see if DOM is already available
    if (document.readyState === "complete" || document.readyState === "interactive") {
        // call on next available tick
        setTimeout(fn, 1);
    } else {
        document.addEventListener("DOMContentLoaded", fn);
    }
}    

Kullanım:

docReady(function() {
    // DOM hazır 
});

Tam tarayıcı uyumluluğuna ihtiyacınız varsa (IE’nin eski sürümleri de dahil) ve window.onload‘ı beklemek istemiyorsanız, bu durumda jQuery gibi bir kütüphanenin $(document).ready() yöntemini nasıl uyguladığına bakmalısınız. 

Öncelikle destekleniyorsa standardı dener:

document.addEventListener('DOMContentLoaded', fn, false);

bu işe yaramazsa aşağıdakine düşer;

window.addEventListener('load', fn, false )

veya IE’nin eski sürümleri için şunları kullanır:

document.attachEvent("onreadystatechange", fn);

bu işe yaramazsa da aşağıdakine düşer;

window.attachEvent("onload", fn);

Aşağıda düz javascript ile yazılmış jQuery .ready() fonksiyonunun tam yöntemi bulunuyor:

(function(funcName, baseObj) {
    // The public function name defaults to window.docReady
    // but you can pass in your own object and own function name and those will be used
    // if you want to put them in a different namespace
    funcName = funcName || "docReady";
    baseObj = baseObj || window;
    var readyList = [];
    var readyFired = false;
    var readyEventHandlersInstalled = false;

    // call this when the document is ready
    // this function protects itself against being called more than once
    function ready() {
        if (!readyFired) {
            // this must be set to true before we start calling callbacks
            readyFired = true;
            for (var i = 0; i < readyList.length; i++) {
                // if a callback here happens to add new ready handlers,
                // the docReady() function will see that it already fired
                // and will schedule the callback to run right after
                // this event loop finishes so all handlers will still execute
                // in order and no new ones will be added to the readyList
                // while we are processing the list
                readyList[i].fn.call(window, readyList[i].ctx);
            }
            // allow any closures held by these functions to free
            readyList = [];
        }
    }

    function readyStateChange() {
        if ( document.readyState === "complete" ) {
            ready();
        }
    }

    // This is the one public interface
    // docReady(fn, context);
    // the context argument is optional - if present, it will be passed
    // as an argument to the callback
    baseObj[funcName] = function(callback, context) {
        if (typeof callback !== "function") {
            throw new TypeError("callback for docReady(fn) must be a function");
        }
        // if ready has already fired, then just schedule the callback
        // to fire asynchronously, but right away
        if (readyFired) {
            setTimeout(function() {callback(context);}, 1);
            return;
        } else {
            // add the function and context to the list
            readyList.push({fn: callback, ctx: context});
        }
        // if document already ready to go, schedule the ready function to run
        if (document.readyState === "complete") {
            setTimeout(ready, 1);
        } else if (!readyEventHandlersInstalled) {
            // otherwise if we don't have event handlers installed, install them
            if (document.addEventListener) {
                // first choice is DOMContentLoaded event
                document.addEventListener("DOMContentLoaded", ready, false);
                // backup is window load event
                window.addEventListener("load", ready, false);
            } else {
                // must be IE
                document.attachEvent("onreadystatechange", readyStateChange);
                window.attachEvent("onload", ready);
            }
            readyEventHandlersInstalled = true;
        }
    }
})("docReady", window);

Kodun en son sürümü, https://github.com/jfriend00/docReady adresinde.

Kullanım:

// bir fonksiyon referansı verin
docReady(fn);

// isimsiz bir fonksiyon kullanın
docReady(function() {
    // code here
});

// bir fonksiyon referansı ve arguman verin.
// arguman fonksiyonun ilk argumanı olarak kullanılır
docReady(fn, context);

// isimsiz bir fonksiyon ve argüman kullanın
docReady(function(context) {
    // docReady'ye verilmiş argümanı burada kullanabilirsiniz
}, ctx);

Şimdi bu kodun nasıl çalıştığına bakalım;

  1. public olmayan durum değişkenlerine sahip olabilmemiz için bir IIFE (hemen çağrılan işlev ifadesi) oluşturun.
  2. Bir public fonksiyon oluşturun docReady(fn, context)
  3. docReady(fn, context) çağrıldığında ready() fonksiyonunun tetiklenip tetiklenmediğini kontrol edin. Eğer öyleyse, setTimeout(fn, 1) çağırın.
  4. Hazır işleyici tetiklenmediyse bu callback’i daha sonra çağırılacaklar listesine ekleyin.
  5. Sayfanın zaten hazır olup olmadığını kontrol edin. Öyleyse, tüm hazır işleyicileri yürütün.
  6. Belgenin ne zaman hazır olduğunu bilmek için olay dinleyicileri kurmadıysanız şimdi kurun.
  7. Eğer document.addEventListener varsa, .addEventListener() olayını hem "DOMContentLoaded" ve hem de "load" için ekleyin. “load” için güvenlik sebebiyle yedek olarak ekledik, normalde gerekli olmamalıdır.
  8. Eğer document.addEventListener yoksa o zaman .attachEvent() ile "onreadystatechange" ve "onload" olayları için olay işleyicilerini ekleyin.
  9. onreadystatechange olayında document.readyState === "complete" olup olmadığını kontrol edin ve öyleyse, tüm hazır işleyicileri tetiklemek için bir fonksiyon çağırın.
  10. Diğer tüm olay işleyicilerinde tüm hazır fonksiyonları tetiklemek için bir fonksiyon çağırın.
  11. Tüm hazır işleyicileri çağırma işlevinde, zaten tetiklenip tetiklenmediğimizi görmek için bir durum değişkenini kontrol edin. Eğer varsa, hiçbir şey yapmayın. Henüz çağrılmadıysak, hazır işlevler dizisinde dolaşın ve her birini eklendikleri sırayla çağırın. Çağırılanları ayırt etmek için bir kural ayarlayın, böylece hiçbir zaman birden fazla çalıştırılmasınlar.
  12. Fonksiyon dizisini temizleyin.

docReady() ile çağırılan fonksiyonların çağırıldıkları sıraya çalışıtırılmaları garanti edilir.

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Back to top