/*
 * MagicTags jQuery tagging plugin
 * Copyright (c) 2009 Dave Geddes, http://www.geddesign.com
 * Licensed under the MIT (MIT-LICENSE.txt) license.
 */

(function($){
	
var MagicTags = function(options){
	//override the defaults by any options passed in
	this.settings = $.extend({
	   fadeSpeed: "medium" //medium speed by default
	   }, options);
	   
	//Public Instance Variables
	this.fadeSpeed = this.settings['fadeSpeed'];
	
	//set things up   
	this.registerListeners(this);
	return this;
};

/*
 * hide participating (class="mtagged") elements in the DOM that do not have the passed in tag.
 * If an itemsetId is passed in, then only items of that itemset will be affected.
 * The itemsetId is the html id of the div containing the tags. Items that want to belong to
 * a specific itemset simply all have a CSS class that matches the html id of the tagset.
 */
MagicTags.prototype = {
	
  filterByTag: function(tagname, tagsetId) {
     //validate params
	 if (tagname != '' && typeof tagname == 'string'){
		if(tagsetId != '' & typeof tagsetId == 'string'){
			//deselect other tags in the set
			$("#"+tagsetId+" a.mtagcontrol.selected").each(function(){
				var a = $(this);
				var span = $(this).parent();
				var li = $(this).parent().parent();
				$(a).removeClass("selected");
				$(span).removeClass("selected");
				$(li).removeClass("selected");
			});
			
			//show visually the new tag selected
			$("#"+tagsetId+" a."+tagname).each(function(){
				var a = $(this);
				var span = $(this).parent();
				var li = $(this).parent().parent();
				$(a).addClass("selected");
				$(span).addClass("selected");
				$(li).addClass("selected");
			});
			
			//first unhide any elements who were hidden from previous tag filtering
			$(".mtagged."+tagsetId+":hidden").show(this.fadeSpeed);
			//hide participating elements who don't have the tag passed applied
			$(".mtagged."+tagsetId+":not(."+tagname+")").hide(this.fadeSpeed);
		}
	 }
  },
  
  filterByAdditionalTag: function(tagname, tagsetId){
  	 //validate params
	 if (tagname != '' && typeof tagname == 'string'){
		if(tagsetId != '' & typeof tagsetId == 'string'){
			//show visually the new tag selected
			$("#"+tagsetId+" a."+tagname).each(function(){
				var a = $(this);
				var span = $(this).parent();
				var li = $(this).parent().parent();
				$(a).addClass("selected");
				$(span).addClass("selected");
				$(li).addClass("selected");
			});
			
			//of the remaining items, hide those who don't have this new tag applied
			$(".mtagged."+tagsetId+":not(."+tagname+")").hide(this.fadeSpeed);
		}
	 }
  },
  
  /*
   * unhide any elements hidden by this tag selection
   * remove class of selected from the tag
   */
  deselectTag: function(tagname, tagsetId){
  	//validate params
	 if (tagname != '' && typeof tagname == 'string'){
		if(tagsetId != '' & typeof tagsetId == 'string'){
			//remove 'selected' css class
			//$("#"+tagsetId+" a."+tagname).removeClass("selected");
			$("#"+tagsetId+" a."+tagname).each(function(){
				var a = $(this);
				var span = $(this).parent();
				var li = $(this).parent().parent();
				$(a).removeClass("selected");
				$(span).removeClass("selected");
				$(li).removeClass("selected");
			});
			
			//show participating elements who were hidden by this tag, for the specific itemset,
			//that aren't currently hidden by another selected tag
			$(".mtagged."+tagsetId+":not(."+tagname+")").show(this.fadeSpeed);
			var instance = this;
			$("#"+tagsetId+" a.mtagcontrol.selected").each(function(){
			//$("a.mtagcontrol.selected").each(function(){
				var previousTag = $(this).attr("class").split(" ")[1];
				//console.log(previousTag);
				instance.filterByAdditionalTag(previousTag, tagsetId);
			});
		}
	 }
  },
  
  
  clearTagSelection: function(tagsetId){
      //show any hidden items that are linked to the tagset
	  $("."+tagsetId).show(this.fadeSpeed);
	  //clear the 'selected' css classes in the set
	  //$("#"+tagsetId+" a.mtagcontrol").removeClass("selected");
	   $("#"+tagsetId+" a.mtagcontrol").each(function(){
			var a = $(this);
			var span = $(this).parent();
			var li = $(this).parent().parent();
			$(a).removeClass("selected");
			$(span).removeClass("selected");
			$(li).removeClass("selected");
		});
  },
  
  
  /* 
   * if tag set has a class of 'mtagcontrol-global' filter all items on the page, 
   * otherwise filter for the specific itemset, based on the id.
   * 
   */
  handleTagClick: function(event){
  	 event.preventDefault();
	 var target = event.target;
	 //determine if selecting or deselecting
	 var selected = $(target).hasClass("selected");
	 var tag = $(target).attr("class").split(" ")[1]; 
  	 var tagSet = $(target).parent().parent().parent().attr("id"); //the ul
	 
	 if($(target).hasClass("mtagcontrol-clear")){
	 	this.clearTagSelection(tagSet);
		//stop here
		return false;
	 }
	 
	if(selected){
		this.deselectTag(tag, tagSet);
 	}
 	else{
		if(event.shiftKey) {
			this.filterByAdditionalTag(tag, tagSet);
	 	}
		else{
			this.filterByTag(tag, tagSet);
		}
 	}
  },
  
  /*
   * private instance method
   */
  registerListeners: function(instance){
	 //when user clicks on a tag link, call the click handler
	 var instance = this;
	 $(".mtagcontrol").live("click", function(event){
	 		instance.handleTagClick(event);
	 });
  }
};

//register as jQuery plugin (return an instance)
$.MagicTags = function(options){
	var instance = new MagicTags(options);
	return instance;	
}

})(jQuery);
