
var Tags=function(model,name,callback,no_hash)
{var self=this;var i;this.persists=true;this.hash_key=undefined;this.conditions={};this.url=undefined;this.level=undefined;this.baseClass='tags';this.activeClass="active";this.passiveClass="passive";this.labelClass='label';this.countClass='count';this.hoverClass='hover';this.moreClass='more';this.labelAppend=function($label,$count,$more){$label.append($count).append($more);}
this.formatCounter=function(count){return' ('+count+')';}
this.moreTags="";this.user_id=undefined;this.speed=navigator.appName.match(/Microsoft/i)?0:'medium';if(model)
{this.init(model,name,callback);}
if(!no_hash)
{jQuery(document).ready(function(){jQuery(window).bind('hashchange',function(){self.hash();});})}}
Tags.prototype.init=function(model,name,callback)
{var self=this;if(model)
{this.reset();if(typeof model=='object'&&model)
{for(i in model)
{this[i]=model[i];}}
else
{this.model=model;this.name=name;}
this.id=String('tags_'+this.name).replace(/\W+/,'_')+'_';this.__ready=callback?callback:this.callback;if(this.hash_key?!this.hash():true)
{this.load(model);}}}
Tags.prototype.hash=function()
{if(!this.hash_key){return;}
var hash=jQuery.deparam(window.location.hash.replace(/#/g,''));if(hash[this.hash_key]!=this.tag_id)
{this.tag_id=hash[this.hash_key];this.activate(this.tag_id);return true;}
else if(this.data[0]?this.data[0].id:false)
{this.activate(this.data[0].id);return true;}
return false;}
Tags.prototype.setHash=function(id)
{var hash=jQuery.deparam(window.location.hash.replace(/#/g,''));hash[this.hash_key]=id?id:'';return'#'+jQuery.param(hash);}
Tags.prototype.alert=function(msg)
{window.alert(msg);}
Tags.prototype.reset=function()
{this.data={};this.link={};this.stack=[];this.tag_id=undefined;if(this.$element)
{this.$element.empty();}}
Tags.prototype.tagsClass=function()
{return':not(.'+this.labelClass+')';}
Tags.prototype.activate=function(obj,speed)
{if(typeof obj=='number'||typeof obj=='string')
{if(isNaN(Number(obj)))
{this.load(obj,typeof speed=='function'?speed:undefined,false);return;}
if(!this.link[obj])
{this.tag_id=obj;this.loadAll(this.tag_id);return;}
obj=this.link[obj];}
var i;if(obj?!obj.element:true)
{return;}
var element=obj.element;var self=this;var id=self.getId(element);var elements;var parents=[];var parent;var hash={};var url=undefined;if(speed!==false&&typeof self.url=='function')
{url=self.url(obj,self);if(typeof url!='undefined'&&!url)
{return;}}
if(!obj.loaded)
{self.load(id);}
speed=typeof speed=='undefined'?self.speed:speed;element=jQuery(element);parent=obj;hash[obj['id']]=1;obj.element.addClass(self.activeClass).removeClass(self.passiveClass);while(parent=parent.parent)
{hash[parent['id']]=1;parent.element.addClass(self.activeClass).removeClass(self.passiveClass);}
if(obj.tags)
{for(i=0;i<obj.tags.length;i++)
{hash[obj.tags[i].id]=1;if(typeof obj.tags[i].element=='object')
{obj.tags[i].element.addClass(self.passiveClass).removeClass(self.activeClass);}}}
self.showHide(hash,speed);return;for(i in self.link)
{self.link[i].element.removeClass(self.hoverClass);self.link[i].element[hash[i]?'show':'hide'](speed);}
return;}
Tags.prototype.showHide=function(keys,data,speed)
{var i;if(typeof data!='object')
{speed=data;data=this.data[0];}
if(!data)
{return;}
if(keys[data.id])
{if(data.tags instanceof Array)
{for(i=0;i<data.tags.length;i++)
{this.showHide(keys,data.tags[i],speed);}}
if(data.element)
{data.element.show(speed);}}
else if(data.element)
{data.element.hide(speed,(function($){return function(){$.css('display','none');}})(data.element));}}
Tags.prototype.loadAll=function(tag_id,first)
{var self=this;var id;if(!this.model){return;}
if(tag_id instanceof Array)
{if(tag_id.length>0)
{var tid=tag_id.shift();if(tag_id.length>0)
{self.load(first?self.model:tid,function(data){self.loadAll(data);},tag_id);}
else
{self.load(first?self.model:tid,function(tid){if(typeof self.__ready=='function')
{self.__ready();}
self.activate(tid);},tid);}}}
else
{id=tag_id;if(this.link[id])
{this.load(id);}
else
{jQuery.getJSON('/tags/json_path/'+tag_id+'?model='+escape(this.model),function(data){self.loadAll(data,true);});}}}
Tags.prototype.load=function(tag_id,ready_fun,params)
{var i;var isModel=!parseInt(tag_id);var self=this;var query;if(typeof tag_id=='string'||typeof tag_id=='number')
{query=(parseInt(tag_id)?'model='+escape(this.model):'')+(typeof this.level!='undefined'?'level='+parseInt(this.level):'')+(self.query?'&q='+escape(self.query):'')+(self.conditions?'&'+jQuery.param(self.conditions):'');if(this.user_id)
{query+='&user_id='+this.user_id;}
jQuery.getJSON("/tags/json/"+tag_id+'?'+query,function(data)
{var els,i,el,id;if(data['error'])
{self.alert(data['error']);}
else
{if(!data['data'].length)
{self.__ready();return;}
if(isModel)
{data=data['data'];self.process(data,tag_id);data=data[0];}
else
{data=data['data'][0];if(self.link[tag_id])
{self.element(data,self.link[tag_id].parent,true);}
else if(data.id!=tag_id)
{alert(data.id);return self.load(data.id,ready_fun,params);}}
if(data?typeof data.element=='object':false)
{data.loaded=true;self.activate(data,typeof ready_fun!='function');}
if(typeof ready_fun=='function')
{ready_fun(params);}
else
{if(typeof self.__ready=='function')
{self.__ready();}}}});}}
Tags.prototype.getId=function(id)
{var $id;if(typeof id=='object')
{$id=id.attr?id.attr('id'):id.id;}
else
{$id=String(id);}
return parseInt($id.match(/\d+$/)[0]);}
Tags.prototype.element=function(data,parent,setsLoad)
{var self=this;var $label,$count,$more;var i,id=parseInt(data['id']);if(!(data instanceof Object))
{return;}
obj=this.link[id];if(!obj)
{return;}
if(setsLoad)
{obj.loaded=true;}
if(!obj.element)
{obj.element=jQuery('<div></div>');$label=jQuery('<div></div>');$label.addClass(this.labelClass);$label.html(data.name);$count=jQuery('<span></span>');$count.addClass(this.countClass);$count.html(self.formatCounter(data.count));$more=jQuery('<span></span>');$more.addClass(this.moreClass);$more.html((data.tags instanceof Array)&&data.tags.length>0?self.moreTags:'');obj.element.addClass(this.passiveClass);obj.element.hide();obj.element.attr('id',this.id+data.id);obj.element.object=obj;this.labelAppend($label,$count,$more);obj.element.append($label);this.addEvents($label,obj);if(typeof parent=='object'?parent.element:false)
{parent.element.append(obj.element);}
if(obj.name==='')
{$label.hide();}}
else if((data.tags instanceof Array)&&data.tags.length>0)
{if($more=obj.element.children('.'+this.labelClass).find('.'+this.moreClass))
{$more.html(self.moreTags);}}
for(i in data)
{if(typeof data[i]!='object'&&i!='depth')
{obj[i]=data[i];}
else if(i=='tags'&&(data.tags instanceof Array?data.tags.length>0:false))
{this.process(data[i],data['id']);}}
return;}
Tags.prototype.addEvents=function($label,obj)
{var self=this;$label.unbind('click').unbind('mouseover').unbind('mouseout');$label.click((function(obj)
{return function()
{if(self.hash_key)
{location.href=self.setHash(obj.id);}
else
{self.activate(obj);}}})(obj));$label.mouseover((function($label){return function(){$label.addClass(self.hoverClass);}})($label));$label.mouseout((function($label){return function(){$label.removeClass(self.hoverClass);}})($label));}
Tags.prototype.attach=function(element)
{if(this.data[0]?typeof this.data[0].element=='object'&&this.data[0].element:false)
{element=jQuery(element);this.$element=element;element.append(this.data[0].element);return this.data[0].element;}
return null;}
Tags.prototype.clone=function(obj)
{var i;var clone;if(obj instanceof Array)
{clone=[];for(i=0;i<obj.length;i++)
{clone.push(arguments.callee(obj[i]));}}
else if(typeof obj=='object'&&obj)
{clone={};for(i in obj)
{clone[i]=arguments.callee(obj[i]);}}
else
{clone=(obj);}
return clone;}
Tags.prototype.process=function(data,tag_id)
{var i,obj,id;$tag_id=parseInt(tag_id);if(!(data instanceof Object))
{return null;}
obj=this.link[$tag_id]?this.link[$tag_id]:null;if(data instanceof Array)
{if(!data.length){return null;}
if(!obj&&!$tag_id)
{this.data=data;obj=data[0];if(typeof this.name=='string')
{obj.name=this.name;}
id=parseInt(obj.id);this.link[id]=obj;this.element(obj);return null;}
else if(typeof obj=='object'&&!obj.tags)
{obj.tags=data;}
for(i=0;i<data.length;i++)
{id=parseInt(data[i].id);if(!this.link[id])
{this.link[id]=data[i];}
if(obj)
{data[i].parent=obj;data[i].depth=+obj.depth+1;}
this.element(data[i],obj);}}
else if(typeof data=='object'&&data)
{this.element(data);}
return null;}