Search code examples
androidstylesheetonload

Why is the link element's onload attribute unreliable for android stock browsers?


       var style1 = document.createElement("link");
       style1.id = "rel";
       style1.rel = "stylesheet";
       style1.href = "http://www.mysite.com/css.css";
       style1.onload = function(){document.body.innerHTML+="fffffff";};
       document.getElementsByTagName("head")[0].appendChild(style1);

This code works in Chrome/Firefox, and yet stock browsers on my Froyo (2.3) and Jellybean (4.1) Android devices will print nothing. What's the problem? I'd like if I could execute some js onload of a link. Anything else would in my case amount to a hack. :/

The problem isn't innerHTML. Try it with alerts if you want (at your own peril).

Another answer mentions checking for this functionality by doing

var huh = 'onload' in document.createElement('link');

..but this is true in both stock browsers! wtf guys?


Solution

  • Android browser doesn't support "onload" / "onreadystatechange" events for element: http://pieisgood.org/test/script-link-events/
    But it returns:

    "onload" in link === true
    

    So, my solution is to detect Android browser from userAgent and then wait for some special css rule in your stylesheet (e.g., reset for "body" margins).
    If it's not Android browser and it supports "onload" event- we will use it:

    var userAgent = navigator.userAgent,
        iChromeBrowser = /CriOS|Chrome/.test(userAgent),
        isAndroidBrowser = /Mozilla\/5.0/.test(userAgent) && /Android/.test(userAgent) && /AppleWebKit/.test(userAgent) && !iChromeBrowser; 
    
    addCssLink('PATH/NAME.css', function(){
        console.log('css is loaded');
    });
    
    function addCssLink(href, onload) {
        var css = document.createElement("link");
        css.setAttribute("rel", "stylesheet");
        css.setAttribute("type", "text/css");
        css.setAttribute("href", href);
        document.head.appendChild(css);
        if (onload) {
            if (isAndroidBrowser || !("onload" in css)) {
                waitForCss({
                    success: onload
                });
            } else {
                css.onload = onload;
            }
        }
    }
    
    // We will check for css reset for "body" element- if success-> than css is loaded
    function waitForCss(params) {
        var maxWaitTime = 1000,
            stepTime = 50,
            alreadyWaitedTime = 0;
    
        function nextStep() {
            var startTime = +new Date(),
                endTime;
    
            setTimeout(function () {
                endTime = +new Date();
                alreadyWaitedTime += (endTime - startTime);
                if (alreadyWaitedTime >= maxWaitTime) {
                    params.fail && params.fail();
                } else {
                    // check for style- if no- revoke timer
                    if (window.getComputedStyle(document.body).marginTop === '0px') {
                        params.success();
                    } else {
                        nextStep();
                    }
                }
            }, stepTime);
        }
    
        nextStep();
    }
    

    Demo: http://codepen.io/malyw/pen/AuCtH