Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript Object.create and IE8

I'm doing software development for SharePoint 2013. Part of this involves overriding SharePoint's file previewer (filepreview.debug.js becomes myfilepreview.debug.js). We've run into problems, however, with IE8. Everything works just fine in IE9.

The error thrown in IE8 causes an error on any site you visit within the site collection that our custom feature is activated on: "Object does not support this property or method"

After doing some research on this error, it would appear that IE8 simply does not support Object.create. This Mozilla Developer post seems to support this theory. I was more pressed to believe this when the issue was solved by adding this polyfill code before the line that was throwing the error:

if (typeof Object.create !== 'function') {
    Object.create = function (o) {
        function F() { }
        F.prototype = o;
        return new F();
    };
}

I guess that would make sense that it works because it mimics the functionality of Object.create which supposedly isn't supported in IE8.

However, this was confusing because SharePoint's file previewer javascript works just fine. Their javascript also uses Object.create. Even weirder, the section of code that was throwing the error in our javascript wasn't even our code -- it's SharePoint's. The entire javascript code up to then is actually the same as SharePoint's as well, except for a few lines.

Here's the default, up to the line in question:

function $_global_filepreview() {
RegisterSod("mediaplayer.js", "_layouts/15/mediaplayer.js");
RegisterSod("sp.publishing.resources.resx", "/_layouts/15/ScriptResx.ashx?name=sp.publishing.resources&culture=" + STSHtmlEncode(Strings.STS.L_CurrentUICulture_Name));
RegisterSodDep("mediaplayer.js", "sp.publishing.resources.resx");
previewBase = (function() {
ULS7RK:
    ;
    var filePreviewUniqueId = 0;

    return {
        init: function(ctxT, listItem, extension) {
            this.fpId = ++filePreviewUniqueId;
            this.fpDomId = "FilePreviewID-" + String(this.fpId);
            this.fpCtx = ctxT;
            this.fpExtension = extension;
            this.fpListItem = listItem;
        },
        getHtml: function() {
        ULS7RK:
            ;
            return ['<div class="js-filePreview-containingElement" id=', StAttrQuote(this.fpDomId), '>', this.getInnerHtml(), '</div>'].join("");
        },
        getDomId: function() {
        ULS7RK:
            ;
            return this.fpDomId;
        },
        getContainingElement: function() {
        ULS7RK:
            ;
            var containingElement = document.getElementById(this.fpDomId);

            Sys.Debug.assert(m$.isElement(containingElement), "Containing element has not been rendered yet.");
            return containingElement;
        },
        canRender: function() {
        ULS7RK:
            ;
            return true;
        },
        getLoadingIndicatorHtml: function(customStyle) {
            if (m$.isUndefined(customStyle)) {
                customStyle = "";
            }
            return ['<div class="js-filePreview-loading-image" style="width:', this.getWidth(), 'px; height:', this.getHeight(), 'px; line-height:', this.getHeight(), 'px; text-align:center; vertical-align:middle; display: inline-block; ' + customStyle + '">', '<img src="', "/_layouts/15/images/gears_anv4.gif", '" />', '</div>'].join("");
        },

        hideLoadingIndicator: function() {
        ULS7RK:
            ;
            var containingElement = document.getElementById(this.fpDomId);

            ((m$(containingElement)).find("div.js-filePreview-loading-image")).css({
                display: "none"
            });
        },

        getInnerHtml: function() {
        ULS7RK:
            ;
            return "";
        },
        getWidth: function() {
        ULS7RK:
            ;
            return null;
        },
        getHeight: function() {
        ULS7RK:
            ;
            return null;
        },
        onPostRender: function() {
        },
        onVisible: function() {
        },
        onHidden: function() {
        }
    };
})();
//**This is where the "fix" was added originally**
blankPreview = Object.create(previewBase); <--- error is thrown here

The only difference between the SharePoint javscript (above) and ours (up to this point) is we've removed these following two lines from the beginning, though adding them back still doesn't solve the issue:

RegisterSod("sp.publishing.resources.resx", "/_layouts/15/ScriptResx.ashx?name=sp.publishing.resources&culture=" + STSHtmlEncode(Strings.STS.L_CurrentUICulture_Name));
RegisterSodDep("mediaplayer.js", "sp.publishing.resources.resx");

So my question is: Why am I getting this error that Object.create isn't supported in IE8 while other uses of the same exact function in the default javascript work without issue?

EDIT: A user on another forum suggested I try registering my script via sod. I added this to my code without effect:

RegisterSod("MyFilepreview.debug.js", "_layouts/15/MyFilepreview.debug.js");
like image 517
tnw Avatar asked Jan 21 '13 14:01

tnw


2 Answers

Try debugging in IE and put breakpoints in SharePoint's default JavaScript file. Are you sure the instances of Object.create in the default JavaScript are actually being hit?

like image 53
wjhguitarman Avatar answered Nov 02 '22 15:11

wjhguitarman


They aren't using Object.create with proper arguments.

They use Object.create({name:value}) when it should be Object.create({name:{value:value}}).

So they probably defined their own Object.create and their code is used after yours so you already have your Object.create set when their code runs and they probably test for existence just like you do and assume it's their version that is there when in fact it's yours.

So check for a definition of Object.create in their code and check the order in which scripts are executed.

like image 3
xavierm02 Avatar answered Nov 02 '22 15:11

xavierm02