Question

I'm extremely puzzled by this one and I don't understand if it's a SharePoint issue or a javascript issue.

I've used this flow many times and it's the first time that I observe this behaviour.

Here is my scenario :

  • I created a User Custom Action that executes my custom javascript file (on every site collection page)
  • My javascript file is as follow. As you can see there's a shitload of (rather ugly) redundancy in checking that things are not loaded twice or to make sure that they are actually loaded. I did that because I was failing to understand what's wrong.

var MyNameSpace = MyNameSpace || {};

MyNameSpace.MyModule = MyNameSpace.MyModule || {

DoTheThings : function(attempt)
{
    if (attempt > 20) {
        alert("Failed to locate the SP logo on the page.");
    }

    var logo = document.querySelector("#siteIcon");
    if (logo) {
        alert("logo located!")
    } else {
        setTimeout(function () {
            MyNameSpace.MyModule.DoTheThings(attempt+1);
        }, 50);
    }
},


WaitJQuery : function(attempt) {
    //test if jQuery is here.
    if (typeof jQuery === "undefined") {
        if (attempt > 20) {
            alert("ERROR! jQuery is not loaded! It should be loaded by now. Contact the administrators.");
        } else {

            setTimeout(function () {
                MyNameSpace.MyModule.WaitJQuery(attempt+1);
            }, 50);
        }
    } else {
        jQuery.noConflict(); //avoid conflicts with SharePoint's Ajax

        //Do the things
        jQuery(document).ready(function () {
            MyNameSpace.MyModule.DoTheThings();
        });

    }
},

ExecuteWhenSPBodyLoaded : function()
{   
    //If we don't wait/force sp.js loading, we don't have the client object model or useful stuff
    SP.SOD.executeFunc('sp.js', 'SP.ClientContext', 
        function(){
            MyNameSpace.MyModule.WaitJQuery(0);
        });
}

};

//SCRIPT ENTRY POINT
//Watch out for SharePoint's "Minimal Download Strategy" and for its loading sequence.
//This is the SharePoint equivalent of "document.ready" or jQuery's $()
if (ExecuteOrDelayUntilScriptLoaded && _spBodyOnLoadFunctionNames) {
    _spBodyOnLoadFunctionNames.push("MyNameSpace.MyModule.ExecuteWhenSPBodyLoaded");
} else {
    console.error("MyModule" + " : Bad loading sequence");
}

so now here is for the weird behaviour:

  • Firstly, the whole .js script is executed twice and I can't explain why. Maybe it's because there's an iframe or something like that on the page, therefore sharePoint considers this page as two actual pages, and therefore runs the UCA twice?
  • secondly, the second time the script gets executed, all the previously set variables become undefined. jQuery is undefined. MyNameSpace is undefined. I never reach the point (despite my "attempts" construct) when jQuery is defined. But it's not only jQuery that's failing. At second execution, the script is even failing to find MyNamespace. Even if I strip everything from my script and keep only the bare minimum, the second time the script even fails to locate elements using document.getElementById.

In which weird javascript scope do I find myself?

Was it helpful?

Solution

After investigation, there was an iframe on the page. There was a hidden CEWP containing a video player (don't ask me why the iframe would be rendered even though the WP was hidden). The whole Silverlight embedded chebang was being hidden there.

And apparently, inside the iframe, the javascript scope was not the same at all (even our corporate jQuery, loaded through the AdditionalPageHeader page component, seemed to be configured to not load in there).

This explains that. The Custom Action was executed a second inside that iframe, as SharePoint considers it an entirely different page render.

Licensed under: CC-BY-SA with attribution
Not affiliated with sharepoint.stackexchange
scroll top