Skip to content Skip to sidebar Skip to footer

Angularjs 1.3 Page Won't Load In Ie8

As an angular user, I too shudder at the title of this question, due to the fact that IE8 is evil incarnate and should be put down like a rabid dog. that being said, I was wonderin

Solution 1:

There is a way, though it's a bit rough. Below is the code you need to load before angular and your app may run. This is a collection of shims/polyfills, mostly from Mozilla Developer Network some by me.

Please note, that this only allows AngularJS to run, it doesn't update the JS runtime of IE8. So things like somePromise.catch(...) won't work, you must write somePromise["catch"](...).

if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function(searchElement) {
        if (this.length === 0) {
            return -1;
        }
        var n = 0;
        if (arguments.length > 1) {
            n = Number(arguments[1]);
            if (isNaN(n)) {
                n = 0;
            } elseif (n !== 0 && n !== Infinity && n !== -Infinity) {
                n = (n > 0 || -1) * Math.floor(Math.abs(n));
            }
        }
        if (n >= this.length) {
            return -1;
        }
        var k = n >= 0 ? n : Math.max(this.length - Math.abs(n), 0);
        while (k < this.length) {
            if (k inthis && this[k] === searchElement) {
                return k;
            }
            ++k;
        }
        return -1;
    };
}

if (!Array.prototype.filter) {
    Array.prototype.filter = function(fun/*, thisArg*/) {
        if (this === undefined || this === null) {
            thrownewTypeError();
        }

        var t = Object(this);
        var len = t.length >>> 0;
        if (typeof fun !== 'function') {
            thrownewTypeError();
        }

        var res = [];
        var thisArg = arguments.length >= 2 ? arguments[1] : void0;
        for (var i = 0; i < len; i++) {
            if (i in t) {
                var val = t[i];
                if (fun.call(thisArg, val, i, t)) {
                    res.push(val);
                }
            }
        }
        return res;
    };
}

if (!Array.isArray) {
    Array.isArray = function(arg) {
        returnObject.prototype.toString.call(arg) === '[object Array]';
    };
}

if (!Array.prototype.every) {
    Array.prototype.every = function(callbackfn, thisArg) {
        'use strict';
        var T, k;
        if (this == null) {
            thrownewTypeError('this is null or not defined');
        }
        var O = Object(this);
        var len = O.length >>> 0;
        if (typeof callbackfn !== 'function') {
            thrownewTypeError();
        }
        if (arguments.length > 1) {
            T = thisArg;
        }
        k = 0;
        while (k < len) {

            var kValue;

            if (k in O) {
                kValue = O[k];
                var testResult = callbackfn.call(T, kValue, k, O);
                if (!testResult) {
                    returnfalse;
                }
            }
            k++;
        }
        returntrue;
    };
}

if (!Object.create) {
    Object.create = (function() {
        varObject = function() {};
        returnfunction (prototype) {
            if (arguments.length > 1) {
                thrownewError('Second argument not supported');
            }
            if (typeof prototype != 'object') {
                thrownewTypeError('Argument must be an object');
            }
            Object.prototype = prototype;
            var result = newObject();
            Object.prototype = null;
            return result;
        };
    })();
}

if (!Array.prototype.forEach) {
    Array.prototype.forEach = function(fun /*, thisArg */) {
        if (this === void0 || this === null)
            thrownewTypeError();

        var t = Object(this);
        var len = t.length >>> 0;
        if (typeof fun !== "function")
            thrownewTypeError();

        var thisArg = arguments.length >= 2 ? arguments[1] : void0;
        for (var i = 0; i < len; ++i) {
            if (i in t)
                fun.call(thisArg, t[i], i, t);
        }
    };
}

if (!String.prototype.trim) {
    String.prototype.trim = function() {
        returnthis.replace(/^\s+|\s+$/gm, '');
    };
}

(function() {
    //$http uses onload instead of onreadystatechange. Need shimming as IE8 doesn't have onload.if (newXMLHttpRequest().onload === undefined) {
        var orig = XMLHttpRequest.prototype.send;
        XMLHttpRequest.prototype.send = function() {
            var self = this;
            if (!this.onreadystatechange && this.onload) {
                this.onreadystatechange = function() {
                    if (self.readyState === 4) {
                        self.onload();
                    }
                };
            }
            orig.apply(self, arguments);
        };
    }
})();

if (!Date.now) {
    Date.now = function() {
        returnnewDate().getTime();
    };
}

if (!Function.prototype.bind) {
    Function.prototype.bind = function(oThis) {
        if (typeofthis !== "function") {
            thrownewTypeError("Function.prototype.bind - what is trying to be bound is not callable");
        }
        var aArgs = Array.prototype.slice.call(arguments, 1),
            fToBind = this,
            fNOP = function() {
            },
            fBound = function() {
                return fToBind.apply(thisinstanceof fNOP && oThis
                        ? this
                        : oThis,
                    aArgs.concat(Array.prototype.slice.call(arguments)));
            };

        fNOP.prototype = this.prototype;
        fBound.prototype = newfNOP();

        return fBound;
    };
}

if (!Object.keys) {
    Object.keys = function(object) {
        var keys = [];
        for (var o in object) {
            if (object.hasOwnProperty(o)) {
                keys.push(o);
            }
        }
        return keys;
    };
}

if (!Object.getPrototypeOf) {
    Object.getPrototypeOf = function(object) {
        return object.__proto__ || object.constructor.prototype;
    };
}

If you have angular-bootstrap, you also need to "patch" the angular.min.js file, because angular-boostrap uses {in: someCondition}, but because of the older JS runtime the in keyword is reserved and will fail in the code generation.

Find: var e=(b?"s":'((l&&l.hasOwnProperty("'+a+'"))?l:s)')+"."+a;

Replace: var e=(b?"s":'((l&&l.hasOwnProperty("'+a+'"))?l:s)')+"['"+a+"']";

Solution 2:

Per the comments on the question, and Zenorbi's answer, Angular 1.3 does NOT load correctly in IE8 anymore. It was never designed to continue working in IE8, so this should not come as a surprise.

I actually came up with a simple workaround that will make page load times slightly slower for any IE8 users which is an acceptable loss for me.

using this code, I can simply load 1.3 by default, and if any IE8 users load the page, it will simply load angular 1.2 directly afterwards, simply overwriting any duplicated code:

<scripttype="text/javascript"src="target/libraries/angular.min.js"></script><!--[if lt IE 9]>
<script type="text/javascript" src="target/libraries/angular-1.2.min.js"></script>
<![endif]--><scripttype="text/javascript"src="target/libraries/angular-route.min.js"></script><!--[if lt IE 9]>
<script type="text/javascript" src="target/libraries/angular-route-1.2.min.js"></script>
<![endif]-->

note: This is terrible practice generally. If we were making a larger effort to support IE8 users, I would go with Zenorbi's answer, since it allows you to load only one version of angular.

Solution 3:

Based on answers from SamHuckaby and Zenorbi, i came up with acceptable solution which is a combination of their ideas and insights from this article IF Internet Explorer THEN Do Something Else (A How To...) by Phil Nash:

<!--[if !IE]>--><scriptsrc="/ui/resources/webjars/angularjs/1.4.0/angular.js"></script><scriptsrc="/ui/resources/webjars/angularjs/1.4.0/angular-route.js"></script><!--<![endif]--><!--[if gt IE 8]>
        <script src="/ui/resources/webjars/angularjs/1.4.0/angular.js"></script>
        <script src="/ui/resources/webjars/angularjs/1.4.0/angular-route.js"></script>
    <![endif]--><!--[if lt IE 9]>
        <script type="text/javascript" src="/ui/resources/lib/angularjs/1.2.28/angular.js"></script>
        <script type="text/javascript" src="/ui/resources/lib/angularjs/1.2.28/angular-route.js"></script>
    <![endif]--><scripttype="text/javascript"src="webjars/es5-shim/4.0.6/es5-shim.js"></script><scripttype="text/javascript"src="webjars/es6-shim/0.20.2/es6-shim.js"></script>

<!--[if !IE]>-->...<!--<![endif]--> - Conditional comment will be evaluated by IE, but the scripts within won't get loaded by IE and will get loaded by all other browsers

<!--[if gt IE 8]>...<![endif]--> - Conditional comment will be evaluated by IE and if greater than IE 8, scripts will get loaded

<!--[if lt IE 9]>...<![endif]--> - Conditional comment will be evaluated by IE and if less than IE 9, scripts will get loaded.

Both es5-shim and es6-shim should be put out of IE8 conditional comment block and checked by all browsers (and it's not expensive operation) as i recently found out that Safari has issues with String.prototype.startsWith()

Yeah we have some code duplication inside the first and the second conditional comment (and it can't be solved in a different way) but we have zero unwanted scripts loaded and we can close our task here.

Solution 4:

From Angular Developer Guide migration docs:

Note: AngularJS 1.3 is dropping support for IE8. Read more about it on our blog. AngularJS 1.2 will continue to support IE8, but the core team does not plan to spend time addressing issues specific to IE8 or earlier.

Solution 5:

Github user @fergaldoyle maintains a repo that combines shiming/polyfill and other patch strategies in order to maintain compatibility.

This could be a viable strategy for many solution providers

Post a Comment for "Angularjs 1.3 Page Won't Load In Ie8"