**Important**: Historically we have been using [PrototypeJS](http://prototypejs.com), which is now discouraged. SilverStripe as a framework doesn't impose a choice of library. It
tries to generate meaningful markup which you can alter with other JavaScript libraries as well. Only the CMS itself and
certain form widgets require jQuery to function correctly. You can also use jQuery in parallel with other libraries, see
jQuery allows you to write complex behaviour in a couple of lines of JavaScript. Smaller features which aren't likely to
be reused can be custom code without further encapsulation. For example, a button rollover effect doesn't require a full
plugin. See "[How jQuery Works](http://docs.jquery.com/How_jQuery_Works)" for a good introduction.
You should write all your custom jQuery code in a closure. This will prevent jQuery from conflicting from any prototype
code or any other framework code.
:::javascript
(function($) {
$(document).ready(function(){
// your code here.
})
})(jQuery);
### jQuery Plugins
A jQuery Plugin is essentially a method call which can act on a collection of DOM elements. It is contained within the `jQuery.fn` namespace, and attaches itself automatically to all jQuery collections. The basics for are outlined in the
official [jQuery Plugin Authoring](http://docs.jquery.com/Plugins/Authoring) documentation.
There a certain [documented patterns](http://www.learningjquery.com/2007/10/a-plugin-development-pattern) for plugin
development, most importantly:
* Claim only a single name in the jQuery namespace
* Accept an options argument to control plugin behavior
* Provide public access to default plugin settings
* Provide public access to secondary functions (as applicable)
* Keep private functions private
* Support the [Metadata Plugin](http://docs.jquery.com/Plugins/Metadata/metadata)
Example: A plugin to highlight a collection of elements with a configurable foreground and background colour
(abbreviated example from [learningjquery.com](http://www.learningjquery.com/2007/10/a-plugin-development-pattern)).
:::js
// create closure
(function($) {
// plugin definition
$.fn.hilight = function(options) {
// build main options before element iteration
var opts = $.extend({}, $.fn.hilight.defaults, options);
// iterate and reformat each matched element
return this.each(function() {
$this = $(this);
// build element specific options
var o = $.meta ? $.extend({}, opts, $this.data()) : opts;
// For demonstration purposes, this is also possible with jQuery.css()
$.ui.myHighlight.getter = "getBlink";
$.ui.myHighlight.defaults = {
foreground: "red",
background: "yellow",
blink: false
};
})(jQuery);
Usage:
:::js
(function($) {
// call with default options
$(':button').myHighlight();
// call with custom options
$(':button').myHighlight({background: "green"});
// set defaults for all future instances
$.ui.myHighlight.defaults.background = "green";
// Adjust property after initialization
$(':button').myHighlight('setBlink', true);
// Get property
$(':button').myHighlight('getBlink');
})(jQuery);
### entwine: Defining Behaviour and Public APIs
jQuery.entwine is a third-party plugin, from its documentation:
"A basic desire for jQuery programming is some sort of OO or other organisational method for code. For your
consideration, we provide a library for entwineUI style programming. In entwineUI you attach behavioral code to DOM
objects. entwine extends this concept beyond what is provided by other libraries to provide a very easy to use system
with class like, ploymorphic, namespaced properties."
Use jQuery.entwine when your code is likely to be customized by others, for example for most work in the CMS interface.
It is also suited for more complex applications beyond a single-purpose plugin.
Example: Highlighter
:::js
(function($) {
$(':button').entwine({
Foreground: 'red',
Background: 'yellow',
highlight: function() {
this.css('background', this.getBackground());
this.css('color', this.getForeground());
}
});
})(jQuery);
Usage:
:::js
(function($) {
// call with default options
$(':button').entwine().highlight();
// set options for existing and new instances
$(':button').entwine().setBackground('green');
// get property
$(':button').entwine().getBackground();
})(jQuery);
This is a deliberately simple example, the strength of jQuery.entwine over simple jQuery plugins lies in its public
properties, namespacing, as well as its inheritance based on CSS selectors. Please see the [project
documentation](http://github.com/hafriedlander/jquery.entwine/tree/master) for more complete examples.
## Architecture and Best Practices
### Keep things simple
Resist the temptation to build "cathedrals" of complex interrelated components. In general, you can get a lot done in
jQuery with a few lines of code. Your jQuery code will normally end up as a series of event handlers applied with `jQuery.live()` or jQuery.entwine, rather than a complex object graph.
Global properties are evil. They are accessible by other scripts, might be overwritten or misused. A popular case is the `$` shortcut in different libraries: in PrototypeJS it stands for `document.getElementByID()`, in jQuery for `jQuery()`.
// get form action, using the jQuery.metadata plugin
$(this).parent().metadata().url,
// submit all form values
$(this.form).serialize(),
// callback after data is loaded
function(data, status) {
resultsEl.show();
// get all record IDs from the new HTML
var ids = jQuery('.results').find('li').map(function() {
return $(this).attr('id').replace(/Record\-/,'');
});
}
);
});
Although they are the minority of cases, there are times when a simple HTML fragment isn't enough. For example, if you
have server side code that needs to trigger the update of a couple of elements in the CMS left-hand tree, it would be
inefficient to send back the HTML of entire tree. SilverStripe can serialize to and from JSON (see the `[api:Convert]` class), and jQuery deals very well with it through
[jQuery.getJSON()](http://docs.jquery.com/Ajax/jQuery.getJSON#urldatacallback), as long as the HTTP content-type is
properly set.
### Use events and observation to link components together
The philosophy behind this javascript guide is **component driven development**: your javascript should be structured as
a set of components that communicate. Event handlers are a great way of getting components to community, as long as
two-way communication isn't required. Set up a number of custom event names that your component will trigger. List
them in the component documentation comment.
jQuery can bind to DOM events and trigger them through custom code. It can also
[trigger custom events](http://docs.jquery.com/Events/trigger), and supports [namespaced