6

I have this simple piece of code:

<script type="text/javascript" src="AnotherLibrary.js" />
<script type="text/javascript">     
    SP.SOD.executeFunc('sp.js', 'SP.ClientContext', function() {
        debugger;
        functionInAnotherLibrary("some data");
    });
</script>

Can anyone tell me why this only executes when I close IE, reopen it and then browse to the page? Any subsequent refreshes don't execute the code at all.

I have tried a number of different methods including SP.SOD.executeOrDelayUntilScriptLoaded, SP.SOD.loadMultiple and even in desperation setTimeout but nothing works.

Dave
  • 106
  • 1
  • 4

2 Answers2

4

Edit to reflect two scenarios for handling MDS

So, this has become one of those lovely 'it depends' answers...

In the general case (yours):

Because you're using MDS, you need to use a ScriptLink control somehwere on your page (by modifying the page source directly, perhaps using SPD or VS -- no content or script editor web parts though).

According to one of the only coherent articles I've found about MDS in the MSDN Dev Center (that is, not on an individual's blog page)

Including CSS and JavaScript files using HTML style and script tags is not supported in MDS.

The way to add your script in a ScripLink control is something like this:

<SharePoint:ScriptLink language="javascript" name="~site/SiteAssets/testModule.js" runat="server" />

Note that the 'name' property is the path to the file using a URL token (more info on those can be found here). Without the URL token, the ScriptLink control will want to look in _layouts and your local language folder.

To make the script load each time you navigate to the page, you still need to use RegisterModuleInit...

Here is my sample js file that will do a console.log each time you navigate to the page:

function foo() {
   console.log('foo called');
}

ExecuteOrDelayUntilBodyLoaded(function() {
   RegisterModuleInit('/mySite/SiteAssets/testModule.js', foo);
   foo();
});

You can also use the ScriptBlock control if you want to add script to your page in-line but still have MDS recognize it needs to run it when the page loads:

<SharePoint:ScriptBlock runat="server" >
    // Your JavaScript code here.
</SharePoint:ScriptBlock>

Something to note: You may need to make some adjustments to your page, depending on how you edit it to insert the ScriptLink in order to remove a"Revert to Template" message, you can find answers on that here and here: Remove "The current page has been customized from its template.".

In the Client Side Rendering (CSR) case:

You use the RegisterModuleInit function to register your function with the MDS manager after you use a content item's JSLink property to reference the js file. This scenario has been covered in other answers on this site (such as my own to: Client-side rendering (JS Link) status changes in sharepoint list) and in various blogs around the internet, good examples include:

"Register CSR-override on MDS enabled SharePoint 2013 site" - Sridhar Raghunathan

"The correct way to execute JavaScript functions in SharePoint 2013 MDS enabled sites" - Wictor Wilén

John-M
  • 5,930
  • 3
  • 18
  • 36
  • Unfortunately that doesn't seem to work either. I have updated the code above so it's more clear what I'm doing. When I try what you suggest the code fails complaining that functionInAnotherLibrary does not exist. This function is using SP.Utilities.Utility further down the line and if I don't put in executeFunc it complains about it not existing. I have tried putting in executeFunc in various parts of the code and it doesn't call the function at all in every case. – Dave Nov 13 '14 at 11:07
  • Ah, well it's difficult to tell you were trying to use the SP.Utilities namespace because your original question only showed you trying to run debugger and a generic line about do stuff :) Editted to reflect some research I've been doing today, still need to test later, but 'should' work! – John-M Nov 13 '14 at 17:11
  • Thanks for all the research. I really appreciate it. I've used both ScriptLink and script tags and neither work. I've tried this with no success along with many other suggestions. I will try these ones you've posted tomorrow and see what happens. Sorry for not posting my full code, it's quite long and most of it is irrelevant. I didn't realise that executeFunc required me to make a call to anything in SP.Utilities given that it doesn't even get that far. – Dave Nov 13 '14 at 18:08
  • Made another correction to keep re-running each time you navigate the page... works on SharePoint Online.. (ScriptLink plus RegisterModuleInit) – John-M Nov 13 '14 at 18:17
  • I am using SharePoint:ScriptLink to include JS file on SP2013 MySiteHost. I have tried various path but I cannot make it works. Do you have advice? – Mark L Feb 06 '15 at 03:43
0

Try this

SP.SOD.executeFunc('sp.js', 'SP.ClientContext', function () {});
SP.SOD.executeOrDelayUntilScriptLoaded(someFunction,"sp.js");

function someFunction {
    alert('loaded');
}
Amal Hashim
  • 28,306
  • 5
  • 31
  • 61