1 /** 2 * Stores, applies, and removes a named set of behaviors. A behavior 3 * is a set of event handlers that need to be connected and then 4 * disconnected repeatedly as a group. 5 * @constructor 6 * @class 7 * @param {Object} args.behaviors object containing the behaviors to be managed, as: 8 * <pre> 9 * { 10 * behavior_name: { 11 * apply_on_init: true if this behavior should be applied when the manager is initialized, 12 * apply: function( manager_object, handles_array ) { 13 * // required function that returns an array of dojo event handles. for example: 14 * return [ 15 * dojo.connect(document.body, "mouseup", this, 'rubberExecute' ), 16 * dojo.connect(document.body, "mousemove", this, 'rubberMove' ) 17 * ]; 18 * }, 19 * remove: function( manager_object, handles_array ) { 20 * // optional function that removes the behavior. by 21 * // default dojo.disconnect() is just called on each 22 * // of the event handles that were returned by the 23 * // apply function 24 * } 25 * }, 26 * ... 27 * } 28 * </pre> 29 * @param {Object} [args.context=BehaviorManager itself] context 30 * (i.e. <code>this</code>) in which each of the behavior 31 * <code>apply()</code> and <code>remove()</code> functions will be 32 * called. 33 */ 34 function BehaviorManager( args ) { 35 this.context = args.context; 36 this.behaviors = args.behaviors; 37 }; 38 39 /** 40 * Apply the behaviors that have <code>apply_on_init</code> true. 41 */ 42 BehaviorManager.prototype.initialize = function() { 43 this.removeAll(); 44 for( var bname in this.behaviors ) { 45 var b = this.behaviors[bname]; 46 if( b.apply_on_init ) { 47 this.applyBehaviors( bname ); 48 } 49 } 50 }; 51 52 /** 53 * Apply each of the behaviors named as arguments to this function. 54 * @param {String} [...] Zero or more string behavior names to apply. 55 */ 56 BehaviorManager.prototype.applyBehaviors = function() { 57 dojo.forEach( arguments, function(name) { 58 var b = this._get(name); 59 if( !b.applied ) { 60 b.handles = b.handles || []; 61 b.handles = b.apply.call( this.context || this, this, b.handles ); 62 b.applied = true; 63 } 64 }, this); 65 }; 66 67 /** 68 * Look up a behavior by name, throw an exception if it's not there. 69 * @private 70 */ 71 BehaviorManager.prototype._get = function( name ) { 72 var b = this.behaviors[name]; 73 if( !b ) throw "no behavior registed with name '"+"'name"; 74 return b; 75 }; 76 77 /** 78 * Given two behavior names, remove the first one and apply the second 79 * one. For convenience. 80 */ 81 BehaviorManager.prototype.swapBehaviors = function( off, on ) { 82 this.removeBehaviors(off); 83 this.applyBehaviors(on); 84 }; 85 86 /** 87 * Remove each of the behaviors named as arguments to this function. 88 * @param {String} [...] Zero or more string behavior names to remove. 89 */ 90 BehaviorManager.prototype.removeBehaviors = function( ) { 91 dojo.forEach( arguments, function(name) { 92 var b = this._get(name); 93 if( b.applied ) { 94 var remove = b.remove || function( m, h ) { 95 dojo.forEach( h, dojo.disconnect, dojo ); 96 }; 97 remove.call( this.context || this, this, b.handles ); 98 b.applied = false; 99 } 100 }, this); 101 }; 102 103 /** 104 * Remove all behaviors that are currently applied. 105 */ 106 BehaviorManager.prototype.removeAll = function( ) { 107 for( var bname in this.behaviors ) { 108 this.removeBehaviors( bname ); 109 } 110 };