/* This file is intended for you to add application-specific Javascript behaviours. Behaviour lets you apply javascript to elements of the DOM using CSS selectors. A simple example: var myrules = { "h2.rounded": function(element) { doRounding(element); } }; Behaviour.register(myrules); In general, you'll rarely if ever have to worry about calling Behaviour.apply() yourself -- Jifty will take care of it on DOM load and on any AJAX updates that it does. Some Notes About Writing Behaviours =================================== * Jifty's Behaviour.js uses the jQuery[1] library to do our DOM lookups by CSS selector. jQuery is very powerful, but can be slower as the DOM size grows. For best performance, follow these guidelines when writing behaviours, whenever possible: * Prefer selectors that begin with '#id'. jQuery will use document.getElementByID to get the ID in question, meaning we only have to search a small fragment of the DOM by hand * Barring that, prefer selectors of the form 'element.class' over simply '.class' selectors. This lets us filter for that element specifically using DOM calls, again hugely reducing the amount of DOM walking we have to do. [1] http://jquery.com * Behaviour has something of a reputation for leaking memory. The reason for this is a common idiom used in constructing behaviours. Code like: Behaviour.register({ 'a.help': function(e) { e.onclick = function() { openInHelpWindow(this); return false; } } }); will leak memory in Internet Explorer, thanks to how IE handles garbage collection (See the footnote for details). To avoid this, you can use one of the following two idioms: (a) Use jQuery to bind events like onclick: Behaviour.register({ 'a.help': function(e) { jQuery(e).click(function() { openInHelpWindow(this); return false; }); } }); (b) Declare the onclick function elsewhere: function openHelpLink() { openInHelpWindow(this); return false; } Behaviour.register({ 'a.help': function(e) { e.onclick = openHelpLink; } }); (c) Set the element to 'null' at the end of the Behaviour function: Behaviour.register({ 'a.help': function(e) { e.onclick = function() { openInHelpWindow(this); return false; } e = null; } }); * Jifty has recently gained built-in support for limited profiling of Behaviours via the ProfileBehaviour plugin (in the Jifty svn tree). After installing the module, add it to your config.yml, using, e.g: Plugins: - ProfileBehaviour: {} Once you do this, all pages in your application should have a ``Behaviour profile'' link at the bottom left hand corner of the screen. Click it to get a breakdown of how much time your javascript is spending in which behaviours, and whether the time is spent in looking up the CSS Selector you passed (jQuery time), or in applying the Behaviour function (function time). ** Footnote ** The reason that code leaks in IE is that Internet Explorer uses reference counting to manage memory in its Javascript engine, which means that circular references are never freed. When you write this code: Behaviour.register({ 'a.help': function(e) { // <-- FUNCTION A e.onclick = function() { // <-- FUNCTION B openInHelpWindow(this); return false; } } }); You are in fact creating a circular data structure because function `B', when it is created, stores a reference to the environment in which it was created, which includes the variable `e'. `e', however, also references function `B' through its `onclick' property, and this a circular chain of references is created, which IE will never garbage collect. Solution (b) addresses this by moving function `b' outside of the scope where `e' is defined. Solution (c) addresses it by setting `e' to null in the environment around `b', which means that that environment no longer contains a reference to that DOM node, and the loop no longer exists. */