/*
 * jquery.subscribe.1.1
 * 
 * Implementation of publish/subcription framework for jQuery
 * Requires use of jQuery. Tested with jQuery 1.3 and above
 *
 *
 * Copyright (c) 2008 Eric Chijioke (obinna a-t g mail dot c o m)
 *
 * 
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 *  Release Notes:
 *  
 *  1.1:
 *  
 *  Fixed unexpected behavior which can occur when a script in a embedded page (page loaded in div,tab etc.) subscribes a handler for a topic using
 *  the jQuery subscribe ($.subscribe) or a no-id element but this subscribe plugin is not reloaded within that embedded page (for example, when
 *  script is included in containing page) . In this case, if the embedded page is reloaded without reloading the entire page (and plugin), the
 *  subscription could be made multiple times for the topic, which will call the handler multiple times each time the topic is published. 
 *  Code has been added to prevent this when the subscription is made using the non-element subscribe ($.subscribe()), which assures that only one
 *  subscription is made for a topic for a given window/frame. To prevent this from happening for an element subscription ($elem.subscribe()), make
 *  sure that the element has an id attribute.
 */

if(!Array.indexOf){Array.prototype.indexOf=function(obj){for(var i=0;i<this.length;i++){if(this[i]==obj){return i;}}
return-1;}}
(function($){_subscribe_topics={};_subscribe_handlers={};$.fn.extend({createTopic:function(topic){if(topic&&!_subscribe_topics[topic]){_subscribe_topics[topic]={};_subscribe_topics[topic].objects={};_subscribe_topics[topic].objects['__noId__']=[];}
return this;},destroyTopic:function(topic){if(topic&&_subscribe_topics[topic]){for(i in _subscribe_topics[topic].objects){var object=_subscribe_topics[topic].objects[i];if($.isArray(object)){if(object.length>0){for(j in object){object[j].unbind(topic);}}}else{object.unbind(topic,data);}}}
delete _subscribe_topics[topic];return this;},subscribe:function(topic,handler,data){if(this[0]&&topic&&handler){this.createTopic(topic);if(this.attr('id')){_subscribe_topics[topic].objects[this.attr('id')]=this;}else{var noIdObjects=_subscribe_topics[topic].objects['__noId__'];if(this[0].nodeType==9){for(var index in noIdObjects){var noIdObject=noIdObjects[index];if(noIdObject[0].nodeType==9&&this[0].defaultView.frameElement==noIdObject[0].defaultView.frameElement){return this;}}}
if(_subscribe_topics[topic].objects['__noId__'].indexOf(this)<0){_subscribe_topics[topic].objects['__noId__'].push(this);}}
if(typeof(handler)=='function'){this.bind(topic,data,handler);}else if(typeof(handler)=='string'&&typeof(_subscribe_handlers[handler])=='function'){this.bind(topic,data,_subscribe_handlers[handler]);}}
return this;},unsubscribe:function(topic){if(topic){if(this.attr('id')){if(_subscribe_topics[topic]){var object=_subscribe_topics[topic].objects[this.attr('id')];if(object){delete _subscribe_topics[topic].objects[this.attr('id')];}}}else{var index=_subscribe_topics[topic].objects['__noId__'].indexOf(this);if(index>=0){subscribe_topics[topic].objects['__noId__'].splice(index,1);}}
this.unbind(topic);}
return this;},publish:function(topic,data,originalEvent){if(topic){this.createTopic(topic);var subscriberStopPropagation=function(){this.isImmediatePropagationStopped=function(){return true;};(new $.Event).stopPropagation();if(this.originalEvent){this.originalEvent.isImmediatePropagationStopped=function(){return true;};this.originalEvent.stopPropagation=subscriberStopPropagation;}}
var event=jQuery.Event(topic);$.extend(event,{originalEvent:originalEvent,stopPropagation:subscriberStopPropagation});for(i in _subscribe_topics[topic].objects){var object=_subscribe_topics[topic].objects[i];if($.isArray(object)){if(object.length>0){for(j in object){object[j].trigger(event,data);}}}else{object.trigger(event,data);}}}
return this;},publishOnEvent:function(event,topic,data){if(event&&topic){this.createTopic(topic);this.bind(event,data,function(e){$(this).publish(topic,e.data,e);});}
return this;}});$.extend({subscribe:function(topic,handler,data){return $().subscribe(topic,handler,data);},subscribeHandler:function(name,handler){if(name&&handler&&typeof(handler)=="function"){_subscribe_handlers[name]=handler;}
return $();},publish:function(topic,data){return $().publish(topic,data);},createTopic:function(topic){return $().createTopic(topic);},destroyTopic:function(topic){return $().destroyTopic(topic);}});})(jQuery);