/** * If there is going to be more than 1 type of popup related to the badges * we need something to manage them all. * * First call register passing the @selector which will be assigned a listener of @type. * When this @type event triggers, @func will be called. @func should close the popup. * NOTE: @func is forwarded the event parameter, however this paramter may be null. Be sure to check for this. * * After register, call assign to set up listeners which will trigger a popup to open. * assign is a wrapper around listeners that closes other open popups. * * If you want to force your popup to be the only one open call set_master. * * Use set_active to turn off/on the handlers. * * EXAMPLE USAGE: * var popup = new PopUp(); * bf_badge_popup.register(popup, $$('body')[0], 'click', function(evt) { * popup.close(); * }); * bf_badge_popup.assign(popup, $$('.button'), 'mouseover', function(evt) { * popup.open(); * }); * */ var bf_badge_popup = { _objs_seed: 0, _objs: { }, _active: true, _master_obj: null, //////// register: function(obj, selector, type, func) { var objid = this._objs_seed++; this._objs[objid] = { obj: obj, is_open: false, on_close: func }; this._wrap('close', objid, selector, type, func); }, //////// assign: function(obj, selector, type, func) { var objid = this._find_objid(obj); if(objid === false) return; this._wrap('open', objid, selector, type, func); }, //////// unregister: function(obj) { var objid = this._find_objid(obj); if(objid === false) return; delete this._objs[objid]; }, //////// set_master: function(obj) { this._master_obj = obj; }, //////// force_close: function(obj) { this._close_all(); if(this._master_obj == obj) { this._master_obj = null; } }, //////// force_open: function(obj) { var objid = this._find_objid(obj); if(objid === false) return; obj = this._objs[objid]; this._close_all(obj.obj); obj.is_open = true; }, //////// set_active: function(val) { this._active = val; }, //////// _wrap: function(wrap_type, objid, selector, evt_type, func) { if(selector.each) { var self = this; selector.each(function(ele) { self['_wrap_' + wrap_type](objid, ele, evt_type, func); }); } else { this['_wrap_' + wrap_type](objid, selector, evt_type, func); } }, //////// _wrap_close: function(objid, ele, type, func) { var self = this; ele.observe(type, function(evt) { if(!self._active) return; var obj = self._objs[objid]; if(!obj) { ele.stopObserving(type, arguments.callee); } else if(obj.is_open && (!self._master_obj || obj.obj == self._master_obj)) { var ret = func(evt); if(ret !== false) { obj.is_open = false; self._master_obj = null; } } }); }, //////// _wrap_open: function(objid, ele, type, func) { var self = this; ele.observe(type, function(evt) { if(!self._active) return; var obj = self._objs[objid]; if(!obj) { ele.stopObserving(type, arguments.callee); } else if(!self._master_obj) { self._close_all(obj.obj); func(evt); obj.is_open = true; } }); }, //////// _close_all: function(skip_obj) { for(var p in this._objs) { var obj = this._objs[p]; if(obj.is_open && obj.obj != skip_obj) { obj.on_close(); obj.is_open = false; } } }, //////// _find_objid: function(obj) { for(var p in this._objs) { if(this._objs[p].obj == obj) return p; } return false; } };