I've recently switched to using LABjs
to load scripts in SharePoint Webparts (2010). The main reason for this was to avoid loading the same library (like jquery
and jquery.ui
) to the page more than once if multiple Webparts were added to the same page. This way, each of them can specify its dependencies individually, without needing to police which other Webparts have been, or might be added.
Both LABjs
and an another file, which contains the script chains, are loaded via <script>
tags at the bottom of the Webpart's markup.
9 times out of 10, the Javascript executes without any issues. Every once in a while though, an exception will be thrown, stating TypeError: $(...).button is not a function
.
This occurs even if there is only one Webpart on the page and seems to be browser independent (Tested in FireFox 38, Chrome 43 and IE 11/IE 8 forced by page).
The chain looks like this (edited for clarity):
$LAB.setOptions({Debug:true})
.script("../js/jquery-1.11.3.min.js").wait()
.script("../js/jquery-migrate-1.2.1.min.js").wait()
.script("../js/jquery-ui.min.js").wait()
.script("../js/core.js")
.wait(function(){
jQuery(function() {
init(); // The jQuery UI .button() call
});
})
.script("../js/jquery.multiselect.min.js").wait()
.script("../js/jquery.multiselect.filter.min.js")
.script("../js/rte/jquery.rte.js").wait()
.script("../js/rte/jquery.rte.tb.js")
.script("../js/rte/jquery.ocupload-1.1.4.js")
.wait(function () {
jQuery(function() {
// Some DOM-dependant code lives here
});
});
This is what the debugger outputs (also edited for clarity):
start script load (ordered async): ../js/jquery-1.11.3.min.js
start script load (ordered async): ../js/jquery-migrate-1.2.1.min.js
start script load (ordered async): ../js/jquery-ui.min.js
start script load (ordered async): ../js/core.js
start script load (ordered async): ../js/jquery.multiselect.min.js
start script load (ordered async): ../js/jquery.multiselect.filter.min.js
start script load (ordered async): ../js/rte/jquery.rte.js
start script load (ordered async): ../js/rte/jquery.rte.tb.js
start script load (ordered async): ../js/rte/jquery.ocupload-1.1.4.js
script execution finished: ../js/jquery-1.11.3.min.js
script execution finished: ../js/jquery-migrate-1.2.1.min.js
script execution finished: ../js/jquery-ui.min.js
script execution finished: ../js/core.js
$LAB.wait() executing: function (){ jQuery(function() { init(); }); }
$LAB.wait() error caught: TypeError: $(...).button is not a function
...
script execution finished: ../js/jquery.multiselect.min.js
script execution finished: ../js/jquery.multiselect.filter.min.js
script execution finished: ../js/rte/jquery.rte.js
script execution finished: ../js/rte/jquery.rte.tb.js
script execution finished: ../js/rte/jquery.ocupload-1.1.4.js
$LAB.wait() executing: function () {
jQuery(function() {
...
});
}
$LAB.wait() error caught: TypeError: $(...).multiselect is not a function
...
This error is almost always accompanied with long load times for the jquery.ui
library.
At the same time, however, it's clear from the debugger's output that it has already finished executing before the .button()
call.
I've been fighting with this for a while now and any help/insight into what the issue might be and how to fix it would be greatly appreciated. I've been crawling the LABjs
documentation for a clue as to something I may be doing wrong, but nothing seems to be popping out at me.
Note:
There does exist a <script>
reference to jquery
in the header, however this reference cannot be removed (I do not have access to the master page) and I have already tried removing jquery
from the chain, to no avail.
Edit:
Someone has suggested that the issue may be due to the fact that the SharePoint server is behind a load balancer, which might be the cause for the exceptionally long load times on the jquery.ui
library. While that is a possibility, I don't see how or why that would effect LABjs
's load/execute functionality.
---
Update
After quite some digging, I found that, for some reason that is still unknown to me, the jquery.ui
library was binding to jquery
and not $
as my code was expecting. To try and fix this, in core.js I created a variable core.$
which was instantiated with jQuery.noConflict()
, wrapped my DOM dependent code with
(function ($) {
...
})(core.$);
and moved the .script(".../js/core.js")
call to the end of the chain (to make sure all plugins were rolled back properly.)
While this didn't fix the problem, the occurrences have dropped to somewhere around 1 in 50.
<script>
tags does not cause the error. – AstoundjQuery
calls should make sure that the script content is bound to the DOM-ready event. – Astound