123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- /********************************************************************************************************************************
- * Licensed Materials - Property of IBM *
- * *
- * IBM Cognos Products: AGS *
- * *
- * (C) Copyright IBM Corp. 2005, 2008 *
- * *
- * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp. *
- *********************************************************************************************************************************/
- /*
- Wraps a CObserver to provide a general notification framework that includes support
- for frames. A primary goal of the framework is to enable components to 'listen' for
- events that are trapped and thus not propagated to the interested component, or events
- that would never reach the component because it is outside the context of the component
- and bubbles up (or bubbles down) another part of the component tree.
- The following comments outline the framework use.
- 1. The framework expects each window (main or frames) to have a CWndObserver, and
- support the getWndObserver() function, i.e. each window has the following script:
- oWndObserver = new CWndObserver(window.id);//global observer
- function getWndObserver() {
- return oWndObserver;
- }
-
- 2. A wndObserver can be hooked up to listen to events from Frames by adding the following
- script to the onload handler as follows (parent knows what it is interested in):
- getWndObserver().attachFrames("mouseup");
- 3. Part of the framework deal is that components that trap events should notify their
- wndObserver that such an event occurred. Example assumes a menu that has a CObserver:
- if (getWndObserver()) {
- //in this example, attach the wndObserver as a listener to the menu's CObserver
- menu.getObservers().attach(getWndObserver(), getWndObserver().mouseup, menu.onmouseup);
- }
- 4. Should a component wish to receive notification of events that are outside its scope (events
- it would never recieve in normal operation) then the component can listen as follows:
- getWndObserver().addListener(reportFrame.m_contextMenu, reportFrame.m_contextMenu.remove, "mouseup");
-
- 5. Generally, component handlers can be attached to the wndObserver as follows (if a handler is
- already connected to the component, it will still get called):
- getWndObserver().attachEvent(document.body, "mouseup");
-
- 6. To notify, use the following (its important to spicify the src obj if you don't want to be
- notified about events you have generated - meltdown):
- getWndObserver().notify(this, "mouseup");
-
- */
- //some constants
- sNotifyMouseUp = "mouseup";
- sNotifyMouseDown = "mousedown";
- //document.body.oWndObserver = new CWndObserver(window.id);//global observer
- //function getWndObserver() {
- // return oWndObserver;
- //}
- function CWndObserver(id) {
- this.m_cObserver = new CObserver(this);
- this.id = id;
- this.toRemoveLisenters = new Array();
- this.nesting=0;
- }
- //add an event listener. Listeners must 'implement' the Update function as per
- //CObserver requirements. A listener is an observer in CObserver parlance.
- function CWndObserver_addListener(listener, callback, evt) {
- this.m_cObserver.attach(listener, callback, evt);
- }
- //Remove an event listener.
- function CWndObserver_removeWhenDone(listener) {
- this.toRemoveLisenters.push(listener);
- }
- //Remove an event listener.
- function CWndObserver_removeListener(listener) {
- var observers = this.m_cObserver.m_observers;
- var length = observers.length;
- var tmpArray = new Array();
- for (var i=0;i < length;i++) {
- if (observers[i].getObserver() != listener) {
- tmpArray.push(observers[i]);
- }
- }
- this.m_cObserver.m_observers = tmpArray;
- }
- //Remove an event listener.
- function CWndObserver_removeListenerById(id) {
- var observers = this.m_cObserver.m_observers;
- var length = observers.length;
- var tmpArray = new Array();
- for (var i=0;i < length;i++) {
- if (observers[i].getObserver().id == id) {
- this.removeListener(observers[i].getObserver());
- }
- }
- }
- //a required method of CObserver listeners, and used from EventHandlerChain
- function CWndObserver_update(event) {
- this.notify(event, event.type);
- }
- //Note, when attaching events, the handlerStr should not be prefixed with 'on'.
- // ie. use 'mouseup' rather than 'onmouseup', as the 'on' prefix is 'handled'
- //in the eventHandlerChainUtil.
- function CWndObserver_attachEvent(obj, handlerStr) {
- //THIS DOESN'T WORK IN FIREFOX NETSCAPE BROWSERS!
- //TODO: try CWndObserver_privateCheckObjectForHandler
- var handler = obj["on" + handlerStr];
- if (handler) {
- //this should swap out the existing handler, but arrange that it is still called
- //pass in this, so ehc knows who to call - will callback to this.update(evt).
- eventHandlerChainUtil.doEventHandlerChain(obj, handlerStr, this);
- } else {
- obj["on" + handlerStr] = function() {
- document.body.getWndObserver().notify(this,handlerStr);
- }
- }
- }
- // ** POSSIBLE FUTURE SUPPORT FOR NETSCAPE/FIREFOX (EXPERIMENTAL) **
- function CWndObserver_privateCheckObjectForHandler(obj, handlerStr) {
- //THIS DOESN'T WORK IN FIREFOX NETSCAPE BROWSERS!
- handlerStr = "on" + handlerStr;
- //possible firefox/netscape way
- var attributes = obj.attributes;
- if (attributes) {
- var i = 0;
- for (i = 0; i < attributes.length && !handler; i++) {
- if (attributes[i].name == handlerStr) {
- return true;
- }
- }
- }
- }
- //Parameter is the event to listen for (a string e.g. "mouseup"). Chunder through the
- //frames adding ourself as a listener for the evt
- function CWndObserver_attachFrames(evt,frame) {
- var frame = frame?frame:window;
- var framesCount = frame.frames.length;
- for(var i = 0; i < framesCount; ++i) {
- //For some reason the body sometimes is not loaded correctly. So make
- //sure it is their before doing any work.
- //if (!frame.frames[i].getWndObserver && frame.frames[i].document.body) {
- if (frame.frames[i].document.body && !frame.frames[i].document.body.getWndObserver) {
- frame.frames[i].document.body.oWndObserver = new CWndObserver(frame.frames[i].name);
- frame.frames[i].document.body.getWndObserver = function() {
- return this.oWndObserver;
- }
-
- frame.frames[i].document.body.oWndObserver.attachEvent(frame.frames[i].document.body,evt);
- //frame.frames[i].document.body["on"+evt] = function() {
- // this.getWndObserver().notify(this, evt);
- //}
- }
- //For some reason sometimes we get here when body is not there yet.
- if (frame.frames[i].document.body && frame.frames[i].document.body.getWndObserver) {
- //Remove before adding just incase it was added before.
- frame.frames[i].document.body.getWndObserver().removeListener(this);
- //attach ourselves as a listener for stuff
- frame.frames[i].document.body.getWndObserver().addListener(this, this.notify, evt);
- }
- }
- }
- //Propagate an event. evt may be undefined.
- //object may be a string (mouseup - evt undefined)
- //or a CState, or a WndObserver (or what?)
- function CWndObserver_notify(obj, evt) {
- evt = (evt == null || evt == 'undefined')? obj.type : evt; //is an event?
- evt = (evt == null || evt == 'undefined')? obj.m_evt : evt;//is a CState?
- this.privateNotify(obj, evt);
- }
- //specific callback for an onmouseup - useful when attaching to an existing CObserver
- //and the Cobserver's evt is already set to a function (rather than the string "mouseup")
- //param should be a CState (from CObserver), or possibly an event.
- function CWndObserver_notifyMouseUp(obj) {
- this.privateNotify(obj, sNotifyMouseUp);
- }
- //mousedown specific callback - can add more functions if we need them (i.e. mousemove etc)
- function CWndObserver_notifyMouseDown(obj) {
- this.privateNotify(obj, "mousedown");
- }
- //Expect the obj to be a callback from an CObserver (in this case, obj will be a CState),
- //or obj will be an event (string). obj should not be null
- //obj is generally the src - a CState, or a WndObserver
- function CWndObserver_privateNotify(obj, evt) {
- // Prevent reentry into this method to avoid a stack exception.
- if (this.nesting!=0) return;
-
- var src = (obj.m_observer && obj.m_subject)? obj.m_subject : obj;
- evt = (evt == null || evt == 'undefined')? src.m_evt : evt;
- //we don't want to notify back to the observer that notified us!
- //naughty, but need to access the observers listeners directly (hidden here)
- //to omit callbacks to the source
- var cachedObservers = this.m_cObserver.m_observers;
- var tmpObservers = new Array();
- for (var i = 0; i < cachedObservers.length; i++) {
- if (src != cachedObservers[i].m_observer)
- tmpObservers.push(this.m_cObserver.m_observers[i]);
- }
-
- //notify
- this.m_cObserver.m_observers = tmpObservers;
- this.nesting++;
- this.m_cObserver.notify(evt);
- this.nesting--;
- this.m_cObserver.m_observers = cachedObservers;
-
- //Remove any tagged listeners. This is when some might have been tagged
- //during the notify call.
- for(var i=0; i<this.toRemoveLisenters.length;i++) {
- this.removeListener(this.toRemoveLisenters[i]);
- }
- //reset
- this.toRemoveLisenters = new Array();
- }
- //private - only used here to propagate notifications
- CWndObserver.prototype.privateNotify = CWndObserver_privateNotify;
- //public use
- CWndObserver.prototype.addListener = CWndObserver_addListener;
- CWndObserver.prototype.removeListener = CWndObserver_removeListener;
- CWndObserver.prototype.removeListenerById = CWndObserver_removeListenerById;
- CWndObserver.prototype.removeWhenDone = CWndObserver_removeWhenDone;
- CWndObserver.prototype.attachEvent = CWndObserver_attachEvent;
- CWndObserver.prototype.notify = CWndObserver_notify;
- CWndObserver.prototype.attachFrames = CWndObserver_attachFrames;
- CWndObserver.prototype.update = CWndObserver_update;
- CWndObserver.prototype.mouseup = CWndObserver_notifyMouseUp;
- CWndObserver.prototype.mousedown = CWndObserver_notifyMouseDown;
|