4 * Copyright(c) 2006-2007, Ext JS, LLC.
6 * Originally Released Under LGPL - original licence link has changed is not relivant.
9 * <script type="text/javascript">
11 XObject = imports.XObject.XObject;
14 * Base class that provides a common interface for publishing events. Subclasses are expected to
15 * to have a property "events" with all the events defined.<br>
18 Employee = XObject.define(
29 * @param {Object} config properties to use (incuding events / listeners)
33 Observable = XObject.define(
37 this.addEvents(cfg.events || {});
39 delete cfg.events; // make sure
42 XObject.extend(this, cfg);
45 this.on(this.listeners);
46 delete this.listeners;
52 * @cfg {Object} listeners list of events and functions to call for this object,
56 'click' : function(e) {
66 * Fires the specified event with the passed parameters (minus the event name).
67 * @param {String} eventName
68 * @param {Object...} args Variable number of parameters are passed to handlers
69 * @return {Boolean} returns false if any of the handlers return false otherwise it returns true
71 fireEvent : function(){
72 var ce = this.events[arguments[0].toLowerCase()];
73 if(typeof ce == "object"){
74 return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
80 // private - blcoks these types of signals?
81 filterOptRe : /^(?:scope|delay|buffer|single)$/,
84 * Appends an event handler to this component
85 * @param {String} eventName The type of event to listen for
86 * @param {Function} handler The method the event invokes
87 * @param {Object} scope (optional) The scope in which to execute the handler
88 * function. The handler function's "this" context.
89 * @param {Object} options (optional) An object containing handler configuration
90 * properties. This may contain any of the following properties:<ul>
91 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
92 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.NOT AVAIALBLE</li>
93 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
94 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link DelayedEvent} delayed NOT AVAIALBLE
95 * by the specified number of milliseconds. If the event fires again within that time, the original
96 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
99 * <b>Combining Options</b><br>
100 * Using the options argument, it is possible to combine different types of listeners:<br>
102 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)
104 el.on('click', this.onClick, this, {
111 * <b>Attaching multiple handlers in 1 call</b><br>
112 * The method also allows for a single argument to be passed which is a config object containing properties
113 * which specify multiple handlers.
122 fn: this.onMouseOver,
132 * Or a shorthand syntax which passes the same scope object to all handlers:
135 'click': this.onClick,
136 'mouseover': this.onMouseOver,
137 'mouseout': this.onMouseOut,
142 on : function(eventName, fn, scope, o){
143 if(typeof eventName == "object"){
146 if(this.filterOptRe.test(e)){
149 if(typeof o[e] == "function"){
151 this.on(e, o[e], o.scope, o);
153 // individual options
154 this.on(e, o[e].fn, o[e].scope, o[e]);
159 o = (!o || typeof o == "boolean") ? {} : o;
160 eventName = eventName.toLowerCase();
161 var ce = this.events[eventName] || true;
162 if(typeof ce == "boolean"){
163 ce = new Event(this, eventName);
164 this.events[eventName] = ce;
166 ce.addListener(fn, scope, o);
171 * @param {String} eventName The type of event to listen for
172 * @param {Function} handler The handler to remove
173 * @param {Object} scope (optional) The scope (this object) for the handler
175 un : function(eventName, fn, scope){
176 var ce = this.events[eventName.toLowerCase()];
177 if(typeof ce == "object"){
178 ce.removeListener(fn, scope);
183 * Removes all listeners for this object
185 purgeListeners : function(){
186 for(var evt in this.events){
187 if(typeof this.events[evt] == "object"){
188 this.events[evt].clearListeners();
192 _combine : function(){
193 var as = arguments, l = as.length, r = [];
194 for(var i = 0; i < l; i++){
196 if(a instanceof Array){
198 }else if(a.length !== undefined && !a.substr){
199 r = r.concat(Array.prototype.slice.call(a, 0));
207 relayEvents : function(o, events){
208 var createHandler = function(ename){
210 return this.fireEvent.apply(this, Event.prototype.combine(ename,
211 Array.prototype.slice.call(arguments, 0)));
214 for(var i = 0, len = events.length; i < len; i++){
215 var ename = events[i];
216 if(!this.events[ename]){ this.events[ename] = true; };
217 o.on(ename, createHandler(ename), this);
222 * Used to define events on this Observable
223 * @param {Object} object The object with the events defined
225 addEvents : function(o){
229 XObject.extendIf(this.events, o);
233 * Checks to see if this object has any listeners for a specified event
234 * @param {String} eventName The name of the event to check for
235 * @return {Boolean} True if the event is being listened for, else false
237 hasListener : function(eventName){
238 var e = this.events[eventName];
239 return typeof e == "object" && e.listeners.length > 0;
244 * Starts capture on the specified Observable. All events will be passed
245 * to the supplied function with the event name + standard signature of the event
246 * <b>before</b> the event is fired. If the supplied function returns false,
247 * the event will not fire.
248 * @param {Observable} o The Observable to capture
249 * @param {Function} fn The function to call
250 * @param {Object} scope (optional) The scope (this object) for the fn
253 Observable.capture = function(o, fn, scope){
254 o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
258 * Removes <b>all</b> added captures from the Observable.
259 * @param {Observable} o The Observable to release
262 Observable.releaseCapture = function(o){
263 o.fireEvent = Observable.prototype.fireEvent;
268 var createSingle = function(h, e, fn, scope){
270 e.removeListener(fn, scope);
271 return h.apply(scope, arguments);
275 // NOT SUPPORTED YET>
276 //var createBuffered = function(h, o, scope){
277 // var task = new DelayedTask();
278 // return function(){
279 // task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
284 //var createDelayed = function(h, o, scope){
285 // return function(){
286 // var args = Array.prototype.slice.call(arguments, 0);
287 // setTimeout(function(){
288 // h.apply(scope, args);
289 // }, o.delay || 10);
295 * Event Object - manages a specific event.
303 Event = XObject.define(
311 addListener : function(fn, scope, options){
312 var o = options || {};
313 scope = scope || this.obj;
314 if(!this.isListening(fn, scope)){
315 var l = {fn: fn, scope: scope, options: o};
318 // h = createDelayed(h, o, scope);
321 h = createSingle(h, this, fn, scope);
324 // h = createBuffered(h, o, scope);
327 if(!this.firing){ // if we are currently firing this event, don't disturb the listener loop
328 this.listeners.push(l);
330 this.listeners = this.listeners.slice(0);
331 this.listeners.push(l);
336 findListener : function(fn, scope){
337 scope = scope || this.obj;
338 var ls = this.listeners;
339 for(var i = 0, len = ls.length; i < len; i++){
341 if(l.fn == fn && l.scope == scope){
348 isListening : function(fn, scope){
349 return this.findListener(fn, scope) != -1;
352 removeListener : function(fn, scope){
354 if((index = this.findListener(fn, scope)) != -1){
356 this.listeners.splice(index, 1);
358 this.listeners = this.listeners.slice(0);
359 this.listeners.splice(index, 1);
366 clearListeners : function(){
371 var ls = this.listeners, scope, len = ls.length;
374 var args = Array.prototype.slice.call(arguments, 0);
375 for(var i = 0; i < len; i++){
377 if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){