OpenText Content Server & jQuery

OpenText Content Server ships with an outdated version of jQuery (v1.3.2; released February 2009). The library is loaded in the "commonheader.html" file, which means it appears in almost every page in Content Server. Any WebReport or module that uses the standard header will have this version of jQuery forced onto the page. While this might suffice for simple operations in a WebReport or module, it can be limiting when a newer version of jQuery is required.

Unfortunately, you can't just reference a newer version of jQuery in your page. This will cause all menus to break since they rely on the version supplied with Content Server. Fortunately, jQuery provides a way to have multiple instances of jQuery in a page. It can be confusing if you're not familiar with variable scoping in Javascript, so here's a recipe and an explanation of how it works.

<script src="/img/yourmodule/jquery-1.10.2.min.js"></script>

<!-- Load your jQuery plugins here -->

<script>
  // This could also go in an externally referenced .js file
  $(document).ready(function ($) {
    // your code here
    // all variables should be locally defined
    // jQuery accessed via the $ alias
  });
</script>

<script>
  $.noConflict(true);
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

Let's break it down.

The first line adds the newer version of jQuery to the page and sets the jQuery and $ global variables (i.e., window.jQuery and window.$) to the v1.10.2 instance.

The second line is where jQuery plugins can be loaded (e.g., jQuery-ui). Plugins must not reference the global jQuery or $ variables since these variables will be later set back to the original version (i.e., v1.3.2). Fortunately, most third party jQuery plugins are written to access the global instance of jQuery that was valid when the plugin was imported (as opposed to the global instance that is valid when the plugin is executed). See the section "Protecting the $ Alias and Adding Scope" on How to Create a Basic Plugin (opens new window) for details.

Lines 7-9 is where you add your custom code and do any jQuery bindings to your DOM elements. This code is wrapped in an anonymous function that gets executed by $(document).ready() once the DOM has finished loading. It's important that variable scope be restricted to the anonymous function. This will ensure your variables and functions don't clobber any of the many globals that Content Server defines. It also ensures that no other variable or function can clobber your code. It's just good practice. For example:

$(document).ready(function($) {
	// bad - this would break function menus by clobbering window.renderMenu(), which
	// Content Server uses to render function menus
	renderMenu = "abc";

	// good - limit the scope to this anonymous function using
	// the "var" keyword
	var renderMenu = "abc";
);
1
2
3
4
5
6
7
8
9

The last line $.noConflict(true); sets the global jQuery and $ variables back to the original version (v1.3.2). This is required since other Javascript libraries in Content Server reference $ and expect it to be v1.3.2 with its associated plugins. You'll get Javascript errors and broken menus otherwise.

It's important your anonymous function accept a $ parameter, which becomes the alias you use to access your jQuery instance. Omitting this parameter would mean any reference to $ would reference the global instance, which has meanwhile been set back to v1.3.2. This might be easier to explain with examples:

Wrong:

$(document).ready(function () {
  // Without the $ parameter any reference to $ will access the global instance,
  // which has been set back to v1.3.2 via the $.noConflict() call.  e.g.,
  alert($.fn.jquery); // displays the version "1.3.2"
  alert(jQuery.fn.jquery); // displays "1.3.2"
});
1
2
3
4
5
6

Right:

$(document).ready(function ($) {
  // With the $ parameter we are referencing the newer instance.  e.g.,
  alert($.fn.jquery); // displays the version "1.10.2"
  alert(jQuery.fn.jquery); // displays "1.3.2"
});
1
2
3
4
5

This pattern isolates the Javascript from anything else going on in the page. It reduces the risk of conflicts and makes it much more likely to work after a Content Server version upgrade. I've been using it for years and it's by far the best way I know of doing this.