(function($) {
	
	var rootPluginObj = {
		abovethetop: function(element) {
			var top = $(window).scrollTop();
			if($(element).offset().top < top) {
				return true;	
			}
			else {
				return false;
			}
		},
		belowthefold: function(element) {
			var fold = $(window).height() + $(window).scrollTop();
			if(($(element).offset().top + $(element).outerHeight()) > fold) {
				return true;
			}
			else {
				return false;
			}
		}
	}
	
	var pluginObj = {
		afalc: function() {
			var className = this.getSelector();
			this.each(function() {	
				$(this).children().first().addClass("first-child");
				$(this).children().last().addClass("last-child");
				$(this).removeClassAndAttr(className);
			});
			return this;
		},
		columns: function(selector) {
			var columnsExist = false;
			var cssString = new String();
			cssString += ".column{float:left;}";
			
			this.each(function(p) {
				columnsExist = true;
				var selectorString = "setOfColumns" + p;
				var fullWidth = $(this).width();
				var columns = $(this).find(selector);
				var numberOfColsMinusOne = columns.length - 1;
				var fullMargin = getFullMargin(Number($(columns[0]).css("marginLeft").replace("px", "")), Number($(columns[0]).css("marginRight").replace("px", "")));
				var mainCalculation = fullWidth - fullMargin*numberOfColsMinusOne;
				var result = Math.floor(mainCalculation / columns.length);
				cssString += "." + selectorString + " .column{width:" + result + "px;}";
				$(columns[0]).parent().addClass(selectorString);
				$(columns[columns.length-1]).addClass("last-child");
			});
			
			if(columnsExist==true) {
				var styleElement = $("<style type=\"text/css\">" + cssString + "</style>");
				$("head").append(styleElement);
			}
	
			function getFullMargin(a, b) {
				var number = new Number();
				if(a>0) {
					number += a;
				}
				if(b>0) {
					number += b;
				}
				return number;
			}
			return this;
		},
		labeler: function(options) {
			var settings = $.extend({
				className: "labeler",
				passwordValue: "Password",
				hiddenClass: "hidden"
			}, options);
			var selector = this.getSelector();
			this.each(function() {
				var labelTextValue = $(this).text();
				var relatedInputElement = $("#" + $(this).attr("for"));
				if(relatedInputElement.attr("type")=="password") {
					var duplecatedInput = $("<input type=\"text\">");
					duplecatedInput.addClass(settings.className);
					if(relatedInputElement.attr("class")) {
						duplecatedInput.addClass(relatedInputElement.attr("class"));
					}
					duplecatedInput.val(settings.passwordValue);
					relatedInputElement.after(duplecatedInput);
					relatedInputElement.addClass(settings.hiddenClass);
					duplecatedInput.focus(function() {
						$(this).toggleClass(settings.hiddenClass);
						relatedInputElement.toggleClass(settings.hiddenClass);
						relatedInputElement.focus();
					});
					relatedInputElement.blur(function() {
						if(!$(this).val()) {
							$(this).toggleClass(settings.hiddenClass);
							duplecatedInput.toggleClass(settings.hiddenClass);
						}
					});
				}
				else {
					relatedInputElement.addClass(settings.className);
					if(!relatedInputElement.val()) {
						relatedInputElement.val(labelTextValue);
					}
					else {
						labelTextValue = relatedInputElement.val();
					}
					relatedInputElement.focus(function() {
						if($(this).val()==labelTextValue) {
							$(this).toggleClass(settings.className);
							$(this).val("");
						}
					}).blur(function() {
							if(!$(this).val()) {
								$(this).toggleClass(settings.className);
								$(this).val(labelTextValue);
							}
						});
				}
				$(this).removeClassAndAttr(selector);
				
			});
			return this;
		},
		moveClass: function(target) {
			$(target).addClass($(this).attr("class"));
			$(this).removeAttr("class");
			return this;
		},
		oinw: function() {
			this.each(function() {
				$(this).click(function(){
					window.open(this.href);
					return false;
				});		
			});
			return this;
		},
		typeClass: function(prefix) {
			this.each(function() {	
				$(this).addClass(prefix + "_" + $(this).attr("type"))
			});
			return this;
		},
		slideAndFadeToggle: function(speed, func) {
			this.each(function() {
				$(this).animate({
					opacity: "toggle",
					height: "toggle"
				}, speed, func);			   
			});
			return this;
		},
		slidingPane: function(options) {
			var settings = $.extend({
				slideSpeed: 300,
				displayOnLoad: false,
				openClassName: "open"
			}, options);
			this.each(function() {
				var anchorElement = $(this);
				var slidingElement = $(anchorElement.attr("href"));
				if(settings.displayOnLoad==false) {	
					slidingElement.hide();
				}
				else {
					anchorElement.addClass(settings.openClassName);
				}
				anchorElement.click(function() {
					slidingElement.slideAndFadeToggle(settings.slideSpeed, function() {
						anchorElement.toggleClass(settings.openClassName);
					});	
					return false;
				});
			});
			return this;
		},
		tooltiper: function(settings) {
			var settings = $.extend({
				triggerContentHolder: "div",
				showDelay: 50,
				hideDelay: 50,
				animateDuration: 250,
				animateEffect: "toggle",
				animationEasing: "swing",
				slideEffectDistance: 10,
				tooltipClassName: "tooltip",
				layout: "<div/>",
				appendTo: "body",
				position: ["top", "center"],
				offset: [0, 0],
				relative: true,
				coords: [0, 0],
				triggerEvent: "hover",
				clickHideDelay: 5,
				getFromTitleAttr: false
			}, settings);
			this.each(function() {
		
				if(typeof settings.position=="string") {
					settings.position = settings.position.split(/,?\s/);	
				}
							   
				var tooltipObject = null;
				var beingShown = false;
				var mouseOverTrigger = false;
				var mouseOverTooltip = false;
				var hideDelayTimer = null;
				var tooltipHideDelayTimer = null;
				var tooltipShowDelayTimer = null;
				var tooltipClickHideTimer = null;
				var elementOffset = null;
				var triggerWidth = null;
				var triggerHeight = null;
				var tooltipWidth = null;
				var tooltipHeight = null;
				var makePosition = null;
				var xPos = null;
				var yPos = null;
				var refPoint = null;
				var top = null;
				var left = null;
				var tooltipContentStore = null;
				var tooltipContentHasBeenStored = false;
				var trigger = $(this);
				
				if(settings.triggerEvent=="hover") {
					trigger.mouseenter(triggerMouseEnter).mouseleave(triggerMouseLeave);
				}
				if(settings.triggerEvent=="click") {
					trigger.click(function() {
						triggerMouseEnter();
						clickHideDelaySeconds = settings.clickHideDelay * 1000;
						tooltipClickHideTimer = setTimeout(function() {
							triggerMouseLeave();
							clearTimeout(tooltipClickHideTimer);
						}, clickHideDelaySeconds);
						return false;
					})
				}
				if(settings.triggerEvent=="focus") {
					trigger.focus(triggerMouseEnter).blur(triggerMouseLeave);
				}
				
				// trigger mouseenter and mouseout functions 
				function triggerMouseEnter() {
					mouseOverTrigger = true;
					if(beingShown==false) {
						tooltipObject = $(settings.layout).addClass(settings.tooltipClassName);
						if(settings.getFromTitleAttr==true) {
							if(tooltipContentHasBeenStored==false) {
								tooltipContentStore = trigger.attr("title");
								trigger.removeAttr("title");
								tooltipContentHasBeenStored = true;
							}
							tooltipObject.html(tooltipContentStore);
						}
						else {
							if(tooltipContentHasBeenStored==false) {
								tooltipContentStore = trigger.siblings(settings.triggerContentHolder).html();
								trigger.siblings(settings.triggerContentHolder).remove();
								tooltipContentHasBeenStored = true;
							}
							tooltipObject.html(tooltipContentStore);	
						}
						$(settings.appendTo).append(tooltipObject);
						tooltipObject.css({"position": "absolute", "opacity": 0});
						tooltipObject.mouseenter(tooltipMouseEnter).mouseleave(tooltipMouseLeave);			
						makePosition = setTooltipPosition();
						tooltipObject.css({"top": makePosition.top,"left": makePosition.left});
						beingShown = true;
						tooltipShowDelayTimer = setTimeout(function() {	
							tooltipAnimateIn();
						}, settings.showDelay);
						clearTimeout(hideDelayTimer);
					}
				}
				
				function tooltipAnimateIn() {
					if(settings.animateEffect=="toggle") {
						tooltipObject.show();
						tooltipObject.css("opacity", 1);
					}
					else if(settings.animateEffect=="fade") {
						tooltipObject.show().animate({
							opacity: 1
						}, settings.animateDuration, settings.animationEasing);
					}
					else if(settings.animateEffect=="slide") {
						tooltipObject.show().animate({
							top: "-=" + settings.slideEffectDistance + "px",
							opacity: 1
						}, settings.animateDuration, settings.animationEasing);
					}
					else {
						tooltipObject.show();
						tooltipObject.css("opacity", 1);
						console.log("animateEffect name is invalid");
					}
				}
				
				function triggerMouseLeave() {
					mouseOverTrigger = false;
					hideDelayTimer = setTimeout(function() {
						if(mouseOverTooltip==false) {
							tooltipAnimateOut();
							clearTimeout(tooltipShowDelayTimer);
							clearTimeout(hideDelayTimer);
						}
					}, settings.hideDelay);
				}
				
				// tooltip mouseenter and mouseleave functions
				function tooltipMouseEnter() {
					clearTimeout(hideDelayTimer);
					mouseOverTooltip = true;
				}
				
				function tooltipMouseLeave() {
					mouseOverTooltip = false;
					tooltipHideDelayTimer = setTimeout(function() {
						if(mouseOverTrigger==false) {
							tooltipAnimateOut();
							clearTimeout(tooltipHideDelayTimer);
						}
					}, settings.hideDelay);
				}
				
				function tooltipAnimateOut() {
					if(settings.animateEffect=="toggle") {
						tooltipClearAndHide();
					}
					else if(settings.animateEffect=="fade") {
						tooltipObject.animate({
							opacity: 0
						}, settings.animateDuration, settings.animationEasing, tooltipClearAndHide);
					}
					else if(settings.animateEffect=="slide") {
						tooltipObject.animate({
							top: "-=" + settings.slideEffectDistance + "px",
							opacity: 0
						}, settings.animateDuration, settings.animationEasing, tooltipClearAndHide);
					}
					else {
						tooltipClearAndHide();
						console.log("animateEffect name is invalid");
					}
				}
				
				function tooltipClearAndHide() {
					tooltipObject.hide().css("opacity", 0);
					tooltipObject.remove();
					beingShown = false;
				}
				
				function setTooltipPosition() {
					if(settings.relative==true) {
						triggerWidth = trigger.outerWidth();
						triggerHeight = trigger.outerHeight();
						tooltipWidth = tooltipObject.outerWidth();
						tooltipHeight = tooltipObject.outerHeight();
						elementOffset = trigger.offset();
						xPos = settings.position[0];
						yPos = settings.position[1];
						refPoint = settings.position[2];
						left = elementOffset.left += settings.offset[0];
						top = elementOffset.top += settings.offset[1];
						
						// adjust refference point
						if(refPoint=="tl"||refPoint=="bl") {
							if(xPos=="left") {
								left += tooltipWidth;
							}
							if(xPos=="center") {
								left += tooltipWidth / 2;
							}
						}
						if(refPoint=="tr"||refPoint=="br") {
							if(xPos=="center") {
								left -= tooltipWidth / 2;
							}
							if(xPos=="right") {
								left -= tooltipWidth;
							}
						}
						if(refPoint=="tl"||refPoint=="tr") {
							if(yPos=="top") {
								top += tooltipHeight;
							}
							if(yPos=="center") {
								top += tooltipHeight - tooltipHeight / 2;
							}
						}
						if(refPoint=="bl"||refPoint=="br") {
							if(yPos=="center") {
								top -= tooltipHeight / 2;
							}
							if(yPos=="bottom") {
								top -= tooltipHeight;
							}
						}
						if(xPos=="left") {
							left -= tooltipWidth;
						}
						else if(xPos=="center") {
							left +=  triggerWidth / 2 - tooltipWidth / 2;
						}
						else if(xPos=="right") {
							left += triggerWidth;
						}
						if(yPos=="top") {
							top -= tooltipHeight;
						}
						else if(yPos=="center") {
							top += triggerHeight / 2 - tooltipHeight / 2;
						}
						else if(yPos=="bottom") {
							top += triggerHeight;
						}
					}
					else if(settings.relative==false) {
						top = settings.coords[0];
						left = settings.coords[1];
					}
					
					if(settings.animateEffect=="slide") {
						top += settings.slideEffectDistance;
					}
					
					return {top: top, left: left};
				}
			});
			return this;
		},
		oddEven: function(options) {
			var selector = this.getSelector();
			var settings = $.extend({
				type: "odd",
				target: "*"
			}, options);
			this.each(function() {
				$(this).children(settings.target + ":" + settings.type).addClass(settings.type);
				$(this).removeClassAndAttr(selector);
			});
			return this;
		},
		clickAndWait: function(options) {
			var settings = $.extend({
				loadingValue: "Loading",
				loadingClass: "btn_loading",
				hiddenClass: "hidden",
				disabledClass: "disabled",
				animate: false
			}, options);
			this.each(function() {
				$(this).click(function() {
					if($(this).is("input")) {
						if($(this).is(":disabled")==false) {
							var newBtn = $("<input type=\"submit\"/>");
							newBtn.addClass(settings.loadingClass + " " + settings.disabledClass);
							if($(this).attr("class").length>=1) {
								newBtn.addClass($(this).attr("class"));
							}
							newBtn.attr("disabled", "disabled");
							$(this).addClass(settings.hiddenClass);
							newBtn.val(settings.loadingValue);
							$(this).before(newBtn);
							if(settings.animate==true) {
								animateElipsis(newBtn);
							}
						}
					}
					if($(this).is("a")) {
						takeActions($(this));
						if($(this).attr("href").length==1) {
							return false;
						}
					}
				});
			});
			
			function takeActions(target) {
				if(target.hasClass("disabled")==false) {
					var newBtn = $("<a href=\"#\"/>");
					newBtn.addClass(settings.loadingClass + " " + settings.disabledClass);
					if(target.attr("class").length>=1) {
						newBtn.addClass(target.attr("class"));
					}
					target.addClass(settings.hiddenClass);
					newBtn.text(settings.loadingValue);
					target.before(newBtn);
					newBtn.click(function() {
						return false;					  
					});
				}
			}
			
			function animateElipsis(target) {
				var loopedAmount = 0;
				var loadingValueClone = settings.loadingValue;
				var loopLoadingValue = loadingValueClone;
				var currentVal = target.val();
				target.val(currentVal + "...");
				target.css("width", target.outerWidth());
				var timer = setInterval(function() {
					target.val(loadingValueClone);
					loadingValueClone = loadingValueClone + ".";
					loopedAmount ++;
					if(loopedAmount==4) {
						loadingValueClone = loopLoadingValue;
						loopedAmount = 0;
					}
				}, 180);
			}
			
			return this;
		},
		hoverClass: function(options) {
			var settings = $.extend({
				className: "hovered"
			}, options);
			this.each(function() {
				$(this).mouseenter(function() {
					hoverclassover	($(this));					
				}).mouseleave(function() {
					hoverclassleave($(this));
				});
				function hoverclassover(trigger) {
					trigger.toggleClass(settings.className);
				}
				function hoverclassleave(trigger) {
					trigger.toggleClass(settings.className);
				}
			});
			return this;
		},
		windower: function(options) {
			var settings = $.extend({
				width: 500,
				height: 550,
				target: "body",
				title: "New window",
				wrapClass: "iframeWrap"
			}, options);
			var iframeWrap = $("<div class=\"" + settings.wrapClass + "\"/>");
			var iframe = $("<iframe>");
			iframe.attr({"src": $(this).attr("href"), "width": settings.width, "height": settings.height, "frameborder": 0});
			iframe.css({"vertical-align":"middle", "border": 0});
			$(settings.target).append(iframeWrap);
			$(iframeWrap).append(iframe);
			iframeWrap.dialog({
				title: settings.title,
				width: settings.width,
				autoOpen: true,
				modal: true,
				close: function() {
					$(this).remove();
				}
			});
			return this;
		},
		removeClassAndAttr: function(className) {
			this.each(function() {
				$(this).removeClass(className);
				if(!$(this).attr("class")) {
					$(this).removeAttr("class");
				}
			});
			return this;
		},
		clearThis: function(options) {
			var settings = $.extend({
				className: "clear",
				removeClass: true
			}, options);
			var selector = this.getSelector()
			this.each(function() {
				var clearDiv = $("<div class=\"" + settings.className + "\"/>");
				$(this).append(clearDiv);
				if(settings.removeClass==true) {
					$(this).removeClassAndAttr(selector);
				}
			});
			return this;
		},
		getSelector: function() {
			var selector = this.selector.split(" ");
			var valueToReturn = selector[selector.length-1];
			if(valueToReturn.indexOf(".")>=0) {
				var valueToSubstring = valueToReturn.lastIndexOf(".");
				valueToReturn = valueToReturn.substring(valueToSubstring+1);
			}
			else {
				valueToReturn = null;
			}
			return valueToReturn;
		},
		clickable: function(target) {
			this.each(function() {
				var toTarget = $(this).parents().find(target);
				var linkLocation = $(this).attr("href");
				toTarget.click(function() {
					window.location = linkLocation;					
				});
			});
			return this;
		},
		columnise: function(dataset, options) {
			var settings = $.extend({
				numberOfColumns: 2,
				wrapType: "column",
				className: "column",
				lastChildClass: "last-child"
			}, options);
			
			var div = "<div/>";
			
			this.each(function() {
				var divCatcher = [];
				var parent = $(this);
				var dataSetObj = parent.find(dataset);
				var numberToAppendTo = 0;
				if(settings.wrapType=="column") {
					// loop number of columns and output and run function to create, push and append div
					for(var i=0;i<settings.numberOfColumns;i++) {
						createAndAppendDiv(parent, settings.className, divCatcher);
					}
					// loop each dataset item
					$(dataSetObj).each(function() {
						// move to pre-created div
						$(this).appendTo(divCatcher[numberToAppendTo]);
						// increment numberToAppendTo
						numberToAppendTo++;
						// if numberToAppendTo is equal to number of colmns, reset to 0
						if(numberToAppendTo==settings.numberOfColumns) {
							numberToAppendTo = 0;
						}					
					});
				}
				else if(settings.wrapType=="row") {
					// get number of items per row from numberOfColumns
					var numberOfItemsPerRow = settings.numberOfColumns;
					// create inital div to append to
					createAndAppendDiv(parent, settings.className, divCatcher);
					// loop each dataset item
					$(dataSetObj).each(function(x) {
						// add 1 to index value of loop
						x+=1;
						// move to pre-created div
						$(this).appendTo(divCatcher[numberToAppendTo]);
						// if index is equal to numberOfItemsPerRow
						if(x==numberOfItemsPerRow) {
							// increment numberToAppendTo by 1 so to move to next div
							numberToAppendTo += 1;
							// add numberOfColumns value to numberOfItemsPerRow so to look for when next row max has been reached
							numberOfItemsPerRow += settings.numberOfColumns;
							// if index is not equal to number of child items; create, push and append div
							if(x!=dataSetObj.length) {
								createAndAppendDiv(parent, settings.className, divCatcher);
							}
						}
					});
				}
				//$(divCatcher[divCatcher.length-1]).addClass(settings.lastChildClass);
			});
			
			function createAndAppendDiv(appendTo, className, toPushTo) {
				var divObj = $(div);
				divObj.addClass(settings.className);
				toPushTo.push(divObj[0]);
				appendTo.append(divObj);
			}
			
			return this;
		},
		removeIfEmpty: function() {
			this.each(function() {
				if(hasWhiteSpace($(this).html())) {
					$(this).remove();
				}
				if($(this).is(":empty")) {
					$(this).remove();
				}
			});
			function hasWhiteSpace(a) {
				reWhiteSpace = RegExp(/^\s*$/);
				return reWhiteSpace.test(a);
			}
			return this;
		},
		customForm: function(externalVar, options) {
			var settings = $.extend({
				hiddenClass: "hidden",
				customSelect: {
					className: "customSelect",
					titleClass: "customSelectTitle",
					listClass: "customSelectList",
					listItemClass: "customSelectListItem",
					menuClass: "customSelectMenu",
					scrollWrapClass: "customSelectScrollWrap",
					listingHover: "customSelectListing_Hover",
					listingActive: "customSelectListing_Active",
					selectHover: "customSelect_Hover",
					selectOpen: "customSelect_Open",
					maxNumberOfListItems: 15,
					autoPostBack: false,
					toggleFunction: function() {
						
					}
				},
				customCheckBox: {
					className: "customCheckBox",
					innerClass: "customCheckBox_Inner",
					activeClass: "customCheckBox_Active",
					inactiveClass: "customCheckBox_Inactive",
					hoverClass: "customCheckBox_Hover"
				},
				customRadioBtn: {
					className: "customRadioBtn",
					innerClass: "customRadioBtn_Inner",
					activeClass: "customRadioBtn_Active",
					inactiveClass: "customRadioBtn_Inactive",
					hoverClass: "customRadioBtn_Hover"
				}
			}, options);
			
			var div = "<div/>";
			var span = "<span/>";
			var ul = "<ul/>";
			var li = "<li/>";
			var radioCatcher = [];
			var customSelectWholeObjects = [];
			
			var chars = [{charic:"A", code:65}, {charic:"B", code:66}, {charic:"C", code:67}, {charic:"D", code:68}, {charic:"E", code:69}, {charic:"F", code:70}, {charic:"G", code:71}, {charic:"H", code:72}, {charic:"I", code:73}, {charic:"J", code:74}, {charic:"K", code:75}, {charic:"L", code:76}, {charic:"M", code:77}, {charic:"N", code:78}, {charic:"O", code:79}, {charic:"P", code:80}, {charic:"Q", code:81}, {charic:"R", code:82}, {charic:"S", code:83}, {charic:"T", code:84}, {charic:"U", code:85}, {charic:"V", code:86}, {charic:"W", code:87}, {charic:"X", code:88}, {charic:"Y", code:89}, {charic:"Z", code:90}, {charic:"0", code:48}, {charic:"1", code:49}, {charic:"2", code:50}, {charic:"3", code:51}, {charic:"4", code:52}, {charic:"5", code:53}, {charic:"6", code:54}, {charic:"7", code:55}, {charic:"8", code:56}, {charic:"9", code:57}];
			
			this.each(function(index) {
				if($(this).is("select")) {
					customSelectWholeObjects.push(createWholeSelectObject(this, index));
					if(externalVar) {
						externalVar.push(this);
					}
				}
				else if($(this).attr("type")=="checkbox") {
					var checkBoxElement = createCustomElement($(this), settings.hiddenClass);
					var customCheckBox = createCustomElement(span, settings.customCheckBox.className);
					var customCheckBoxInner = createCustomElement(span, settings.customCheckBox.innerClass);
					customCheckBox.append(customCheckBoxInner);
					checkBoxElement.before(customCheckBox);
					
					customCheckBox.mouseenter(function() {
						$(this).addClass(settings.customCheckBox.hoverClass);
					}).mouseleave(function() {
						$(this).removeClass(settings.customCheckBox.hoverClass);					   
					}).click(function() {
						if($(this).hasClass(settings.customCheckBox.activeClass)) {
							$(this).removeClass(settings.customCheckBox.activeClass);
							checkBoxElement.attr("checked", false);
						}
						else {
							$(this).addClass(settings.customCheckBox.activeClass);
							checkBoxElement.attr("checked", true);
						}
					});
				}
				else if($(this).attr("type")=="radio") {
					var radioBtnElement = createCustomElement($(this), settings.hiddenClass);
					var customRadioBtn = createCustomElement(span, settings.customRadioBtn.className);
					var customRadioBtnInner = createCustomElement(span, settings.customRadioBtn.innerClass);
					customRadioBtn.append(customRadioBtnInner);
					radioBtnElement.before(customRadioBtn);
					
					customRadioBtn.mouseenter(function() {
						$(this).addClass(settings.customRadioBtn.hoverClass);
					}).mouseleave(function() {
						$(this).removeClass(settings.customRadioBtn.hoverClass);					   
					}).click(function() {
						if($(this).hasClass(settings.customRadioBtn.activeClass)) {
							$(this).removeClass(settings.customRadioBtn.activeClass);
							radioBtnElement.attr("checked", false);
						}
						else {
							$(radioCatcher).each(function(i) {
								if($(radioCatcher[i].radioItem).attr("name")==radioBtnElement.attr("name")) {
									$(radioCatcher[i].customItem).removeClass(settings.customRadioBtn.activeClass);
								}						  
							});
							$(this).addClass(settings.customRadioBtn.activeClass);
							radioBtnElement.attr("checked", true);
						}
					});
					var radioAndRelatedCustomItem = {customItem:customRadioBtn, radioItem:radioBtnElement};
					radioCatcher.push(radioAndRelatedCustomItem);
				}
			});
			
			$(customSelectWholeObjects).each(function(a) {
				var customSelectWholeObj = this;
				var customSelectObj = customSelectWholeObj.customSelectElement;
				$(customSelectWholeObj.originalSelectElement).before(customSelectObj);
				customSelectWholeObj.activeOption.customOption.addClass(settings.customSelect.listingActive);
				// append title
				customSelectWholeObj.customTitle.text(customSelectWholeObj.activeOption.text);
				$(customSelectObj).append(customSelectWholeObj.customTitle);
				// append menu
				//$(customSelectObj).append(customSelectWholeObj.customMenu);
				$("body").append(customSelectWholeObj.customMenu);
				// append scroll wrap
				$(customSelectWholeObj.customMenu).append(customSelectWholeObj.customScrollWrap);
				customSelectWholeObj.customMenu.width(customSelectObj.css("width"));
				// append ul
				$(customSelectWholeObj.customScrollWrap).append(customSelectWholeObj.unorderedList);
				$(customSelectWholeObj.originalSelectElementOptions).each(function() {
					var customOptionWholeObj = this;
					var customOptionObj = customOptionWholeObj.customOption;
					customOptionObj.text(customOptionWholeObj.text);
					customSelectWholeObj.unorderedList.append(customOptionObj);
					customOptionObj.mouseenter(function() {
						$(customSelectWholeObj.originalSelectElementOptions).each(function() {
							$(this.customOption).removeClass(settings.customSelect.listingHover + " " + settings.customSelect.listingActive);										
						});
						$(this).addClass(settings.customSelect.listingHover);
						customSelectWholeObj.optionInFocus = customOptionWholeObj;
					}).click(function() {
						customSelectWholeObj.activeOption = selectValue(customSelectWholeObj);
						customSelectWholeObj.hasBeenSelected = true;
					});
				});
				
				customSelectWholeObj.maxHeightOfMenu = customSelectWholeObj.activeOption.customOption.outerHeight() * settings.customSelect.maxNumberOfListItems;
				if(customSelectWholeObj.customScrollWrap.height()>customSelectWholeObj.maxHeightOfMenu) {
					customSelectWholeObj.customScrollWrap.css({"height":customSelectWholeObj.maxHeightOfMenu, "overflow-y":"scroll"});
				}
				
				// standard positioning below 
				customSelectWholeObj.customMenu.css({"top":Math.round(customSelectWholeObj.customSelectElement.position().top)+customSelectWholeObj.customSelectElement.height()});
				customSelectWholeObj.customMenu.hide();
				
				customSelectObj.mouseenter(function() {
					$(this).addClass(settings.customSelect.selectHover);
					removeClickHandler(customSelectWholeObj);
				}).mouseleave(function() {
					$(this).removeClass(settings.customSelect.selectHover);
					if(customSelectWholeObj.isBeingShown==true) {			
						$(document).bind("click." + customSelectWholeObj.eventNameSpace, function() {
							$(customSelectWholeObj.customScrollWrap).scrollTop(0);
							customSelectWholeObj.customMenu.hide();
							customSelectWholeObj.isBeingShown = false;
							$(customSelectWholeObj.originalSelectElementOptions).each(function() {
								$(this.customOption).removeClass(settings.customSelect.listingHover);
							});
							$(customSelectWholeObj.activeOption.customOption).addClass(settings.customSelect.listingActive);
							if(customSelectWholeObj.optionInFocus!=customSelectWholeObj.activeOption) {
								customSelectWholeObj.optionInFocus=customSelectWholeObj.activeOption;
							}
							customSelectWholeObj.activeOption = selectValue(customSelectWholeObj);
							removeClickHandler(customSelectWholeObj);
						});
					}
				})
				
				customSelectWholeObj.customTitle.click(function() {
					customSelectWholeObj.customMenu.show();
					// reposition to top - check against browser window
					if(customSelectWholeObj.customMenu.is(":below-the-fold")) {
						customSelectWholeObj.customMenu.css({"top":Math.round(customSelectWholeObj.customSelectElement.position().top)-customSelectWholeObj.customMenu.outerHeight()});
					}
					if(customSelectWholeObj.customMenu.is(":above-the-top")) {
						customSelectWholeObj.customMenu.css({"top":Math.round(customSelectWholeObj.customSelectElement.position().top)+customSelectWholeObj.customSelectElement.outerHeight()});
					}
					$(customSelectWholeObj.customScrollWrap).jumpToElm(customSelectWholeObj.activeOption.customOption);
					customSelectWholeObj.isBeingShown = true;
					removeKeyHandler(customSelectWholeObj);
					addKeyHandler(customSelectWholeObj);
					$(customSelectWholeObj.customSelectElement).addClass(settings.customSelect.selectOpen);
				});
				
			});
			
			function addKeyHandler(a) {
				$(document).bind("keydown." + a.eventNameSpace, function(e) {
					var keycode = e.charCode ? e.charCode : e.keyCode ? e.keyCode : 0;
					$(chars).each(function(i) {
						if(this.code==keycode) {
							a.activeOption = jumpTo(this, a);
							a.optionInFocus = a.activeOption;
						}			   
					});
					if(keycode==38) {
						a.activeOption = moveToListItem(a, "up");
						a.optionInFocus = a.activeOption;
					}
					else if(keycode==40) {
						a.activeOption = moveToListItem(a, "down");
						a.optionInFocus = a.activeOption;
					}
					else if(keycode==13) {
						a.activeOption = selectValue(a);
						a.hasBeenSelected = true;
					}
					return false;
				});
			}
			
			function removeKeyHandler(a) {
				$(document).unbind("keydown." + a.eventNameSpace);
			}
			
			function removeClickHandler(a) {
				$(document).unbind("click." + a.eventNameSpace);
			}
	
			function jumpTo(a, b) {
				var c = b.optionInFocus;
				var found = false;
				$(b.originalSelectElementOptions).each(function() {
					var curr = this;
					if(found==false) {
						if(curr.firstLetter==a.charic) {
							$(b.originalSelectElementOptions).each(function() {
								$(this.customOption).removeClass(settings.customSelect.listingHover + " " + settings.customSelect.listingActive);											
							});
							$(curr.customOption).addClass(settings.customSelect.listingHover);
							found = true;
							c = curr;
							b.customTitle.text(c.text);
							$(b.customScrollWrap).jumpToElm(c.customOption);
						}
					}
				});
				return c;
			}
	
			function setValueOfElement(currentElm, val, elm) {
				$(elm).val(val);
				currentElm.addClass(settings.customSelect.listingActive);
			}
			
			function selectValue(a) {
				setValueOfElement(a.optionInFocus.customOption, a.optionInFocus.value, a.originalSelectElement);
				a.customMenu.hide();
				a.isBeingShown = false;
				a.customTitle.text(a.optionInFocus.text);
				$(a.customSelectElement).removeClass(settings.customSelect.selectOpen);
				removeKeyHandler(a);
				return a.optionInFocus;
			}
			
			function createCustomElement(elmType, elmClass) {
				var customElement = $(elmType);
				customElement.addClass(elmClass);
				return customElement;
			}
			
			function moveToListItem(a, b) {
				var toReturn = a.optionInFocus;
				var currentIndex = toReturn.index;
				if(b=="up") {
					if(currentIndex!=0) {
						toReturn = a.originalSelectElementOptions[currentIndex-1];
						scroller(a, toReturn, b);
					}
				}
				else if(b=="down") {
					if(currentIndex!=a.originalSelectElementOptions.length-1) {
						toReturn = a.originalSelectElementOptions[currentIndex+1];
						scroller(a, toReturn, b);
					}
				}
				$(a.originalSelectElementOptions).each(function() {
					$(this.customOption).removeClass(settings.customSelect.listingHover + " " + settings.customSelect.listingActive);													
				});
				$(toReturn.customOption).addClass(settings.customSelect.listingHover);
				$(a.customTitle).text(toReturn.text);
				return toReturn;
			}
			
			function scroller(a, b, direction) {
				var topPos = b.customOption.position().top + b.customOption.outerHeight();
				if(topPos>=a.maxHeightOfMenu) {
					startScroll();
					//console.log("yeah");
				}
				else if(topPos<=0) {
					startScroll();
				}
				function startScroll() {
					$(a.customScrollWrap).scrollToElm(b.customOption, direction);
				}
			}
			
			function setActiveOption(a, b) {
				var toReturn = null;			
				$(b).each(function() {
					if(this.value==$(a).val()) {
						toReturn = this;
					}
				});
				return toReturn;
			}
			
			function createKeyGroups(a) {
				var arrayOfFirstLetters = [];
				$(a).each(function(i) {
					/*for(var x=0;x<arrayOfFirstLetters.length;x++) {
						console.log("once");
					}*/
					arrayOfFirstLetters.push(this.firstLetter);
				});
				var unique = $.unique(arrayOfFirstLetters);
				//console.log(unique);
				
				return "james test";
			}
			
			function createWholeSelectObject(a, b) {
				$(a).addClass(settings.hiddenClass);
				if(settings.customSelect.autoPostBack==true) {
					$(a).onChange();
				}
				var optionStore = $(a).find("option");
				var oringalOptionObjects = [];
				
				$(optionStore).each(function(i) {	
					var customOptionObj = createCustomElement(li, settings.customSelect.listItemClass);
					var optionObj = {value:$(this).attr("value"), text:$(this).text(), index:i, firstLetter:$(this).text().charAt(0).toUpperCase(), customOption:customOptionObj};
					oringalOptionObjects.push(optionObj);
				});
				
				var customSelectObj = createCustomElement(div, settings.customSelect.className);
				var customTitleObj = createCustomElement(div, settings.customSelect.titleClass);
				var customMenuObj = createCustomElement(div, settings.customSelect.menuClass);
				var customScrollWrapObj = createCustomElement(div, settings.customSelect.scrollWrapClass);
				var unorderedListObj = createCustomElement(ul, settings.customSelect.listClass);
				
				var selectObj = {
					originalSelectElement:a, 
					customSelectElement:customSelectObj, 
					index:b, 
					originalSelectElementOptions:oringalOptionObjects, 
					unorderedList:unorderedListObj, 
					customScrollWrap:customScrollWrapObj, 
					customMenu:customMenuObj, 
					customTitle:customTitleObj, 
					activeOption:setActiveOption(a, oringalOptionObjects), 
					optionInFocus:setActiveOption(a, oringalOptionObjects), 
					hasBeenSelected:false, 
					isBeingShown:false,
					eventNameSpace: "customFormEventNamespace" + b,
					maxHeightOfMenu: null,
					keyGroups: createKeyGroups(oringalOptionObjects)
				};	
				
				//console.log(selectObj);
				
				return selectObj;
			}
			
			return this;
		},
		scrollToElm: function(elmToScrollTo, direction) {
			var amountScrolled = $(this).scrollTop();
			var posOfElm = Math.round($(elmToScrollTo).position().top);
			if(direction=="up") {
				$(this).scrollTop(amountScrolled-=elmToScrollTo.outerHeight());
			}
			else if(direction=="down") {
				$(this).scrollTop(amountScrolled+=elmToScrollTo.outerHeight());
			}
			return this;
		},
		jumpToElm: function(elmToScrollTo) {
			//console.log("jump to");
			var posOfElm = Math.round($(elmToScrollTo).position().top);
			if(posOfElm!=0) {
				$(this).scrollTop(posOfElm);
			}
			//console.log(posOfElm);
			return this;
		},
		tabber: function(options) {
			var settings = $.extend({
				navigationTag: "a",
				defaultIndex: 0,
				event: "click",
				duration: 5000,
				classNames: {
					hidden: "tabber_hidden",
					active: "tabber_active",
					inactive: "tabber_inactive",
					hover: "tabber_hover",
					navigation: "tabber_nav",
					panel: "tabber_panel"
				},
				errorMsg: "Sorry, there has been an error loading the tabbed content.",
				debug: false
			}, options);
			
			// test if document is hashed - if not; return false;
			var documentHash = document.location.hash.length > 0 ? document.location.hash.substring(1) : false;
			
			// if document is hashed; keep to top of page on reload
			if(documentHash) {
				$(window).scrollTop(0);
			}
			
			function setOfTabsObj(a) {
				this.tabGroups = a;
			}
			
			this.each(function() {
				$(this).addClass(settings.classNames.navigation);
				var setOfTabs = new setOfTabsObj(makeTabGroups($(this).find(settings.navigationTag)));
				var defaultIndex = documentHash ? getHashedTabGroup(setOfTabs, settings.defaultIndex) : settings.defaultIndex;
				$(setOfTabs.tabGroups).each(function(index) {
					var currentTabGroup = this;
	
					$(currentTabGroup.nav).mouseenter(function() {
						$(this).addClass(settings.classNames.hover);
					})
					
					if(settings.event=="click") {
						$(currentTabGroup.nav).click(function() {
							changeTabGroup(setOfTabs, currentTabGroup);
							return false;
						})
					}
					else if(settings.event=="mouseover") {
						$(currentTabGroup.nav).mouseenter(function() {
							changeTabGroup(setOfTabs, currentTabGroup);
						})
					}
					
					$(currentTabGroup.nav).mouseleave(function() {
						$(this).removeClass(settings.classNames.hover);
					});
					
					// add classes to navigation and panels
					if(index==defaultIndex) {
						$(currentTabGroup.nav).addClass(settings.classNames.active);
						$(currentTabGroup.panel).addClass(settings.classNames.active);
						if(currentTabGroup.url && !currentTabGroup.loaded) {
							loadAJAX(currentTabGroup, setOfTabs);
						}
					}
					else {
						$(currentTabGroup.nav).addClass(settings.classNames.inactive);
						$(currentTabGroup.panel).addClass(settings.classNames.hidden);
					}
				});
				if(settings.debug) {
					console.log(setOfTabs);
				}
			});
			
			function makeTabGroups(a) {
				var newArray = new Array();
				$(a).each(function() {
					var hrefAttrValue = $(this).attr("href");
					var tabPanelID = ifTypeOfHash(hrefAttrValue) ? hrefAttrValue : "#" + readQuery(hrefAttrValue.substring(hrefAttrValue.indexOf("?") + 1)).panel;
					var tabGroup = new tabGroupObj($(this)[0], $("div" + tabPanelID)[0], tabPanelID, ifTypeOfHash(hrefAttrValue) ? false : readQuery(hrefAttrValue).fragment, ifTypeOfHash(hrefAttrValue) ? false : hrefAttrValue.substring(0, hrefAttrValue.indexOf("?")));
					newArray.push(tabGroup);
				});
				return newArray;
			}
			
			function tabGroupObj(a, b, c, d, e) {
				this.nav = a;
				this.panel = b;
				this.tabID = c;
				this.fragment = d;
				this.url = e;
				this.loaded = false;
				replaceURL(this.nav, this.tabID);
				$(this.panel).addClass(settings.classNames.panel);
			}
			
			function readQuery(a) {
				var splits = a.split(",");
				var obj = new Object();
				obj.panel = splits[0];
				obj.fragment = splits[1] ? "#" + splits[1] : false;
				return obj;
			}
			
			function replaceURL(a, b) {
				$(a).attr("href", b);
			}
			
			function changeTabGroup(a, b) {
				// loop through all groups in currentSetOfTabs
				$(a.tabGroups).each(function() {
					$(this.nav).swapClass(settings.classNames.active, settings.classNames.inactive);
					$(this.panel).swapClass(settings.classNames.active, settings.classNames.hidden);
				});
				// add relevent classnames to currently selected group
				$(b.nav).swapClass(settings.classNames.inactive, settings.classNames.active);
				$(b.panel).swapClass(settings.classNames.hidden, settings.classNames.active);
				if(b.url && !b.loaded) {
					$(b.panel).css("height", a.defaultHeight);
					loadAJAX(b, a);
				}
			}
			
			function getHashedTabGroup(a, b) {	
				$(a.tabGroups).each(function(p) {
					if($(this.panel).attr("id")==documentHash) {
						b = p;
						return false;
					}
				});
				return b;
			}
			
			function ifTypeOfHash(a) {
				if(a.charAt(0)=="#") {
					return true;
				}
				else {
					return false;
				}
			}
			
			function loadAJAX(a, e) {
				var toLoad = a.fragment ? a.url + " " + a.fragment : a.url;
				$(a.panel).load(toLoad, function(b, c, d) {
					if(c=="error") {
						$(a.panel).html(settings.errorMsg);
					}
					a.loaded = true;
					$(a.panel).removeAttr("style");
					e.defaultHeight = $(a.panel).outerHeight();
				});
			}
	
			return this;
		},
		swapClass: function(classToSwap, swapToValue) {
			this.each(function() {
				var currentElm = this;
				var arrayOfClassNames = $(this).attr("class").split(" ");
				$(arrayOfClassNames).each(function(index) {
					if(this.toString()==classToSwap) {
						arrayOfClassNames[index] = swapToValue;
						$(currentElm).attr("class", arrayOfClassNames.toString().replace(/,+/g, " "));
					}
				});
			});
			return this;
		},
		smoothAnchor: function(options) {
			var settings = $.extend({
				duration: 500
			}, options);
			this.each(function() {
				$(this).click(function() {
					var elementToLinkTo = $("div" + $(this).attr("href"))[0];
					var scrollToAmount = $(elementToLinkTo).offset().top;
					$("html, body").animate({
						scrollTop: scrollToAmount
					}, settings.duration);
					return false;
				});
			});
			return this;
		},
		twitter: function(options) {
			
			var settings = $.extend({
				count: 5,
				username: "alicerockmusic",
				className: "blog_post",
				genericClassName: "post"
			}, options);
			
			var url = "http://twitter.com/statuses/user_timeline/" + settings.username + ".json?count=" + settings.count;

			this.each(function() {
				
				var divToAppendTo = $(this);
				
				$.ajax({
					url:url, 
					dataType:"jsonp",
					success:function(a) {
						applyCustomMethods(a).each(function(base) {
							var div = $("<div/>");
							div.html("<a href=\"http://www.twitter.com/" + settings.username + "\" target=\"_blank\"><span class=\"date\">" + returnDaysAgoString(base.created_at) + "</span> " + base.text + "</a>");
							div.addClass(settings.className + " " + settings.genericClassName);
							divToAppendTo.append(div);
						});
					}
				});
			});
			return this;
		},
		blogger: function(options) {
			var settings = $.extend({
				count: 5,
				username: "alicerockblog",
				className: "blog_post"
			}, options);
			
			var url = "http://" + settings.username + ".blogspot.com/feeds/posts/default?alt=json-in-script";
			
			this.each(function() {
				
				var divToAppendTo = $(this);
				$.ajax({
					url:url, 
					dataType:"jsonp",
					success:function(a) {
						applyCustomMethods(a.feed.entry).each(function(base) {
							var div = $("<div/>");
							var anchorElm = $("<a href=\"#\"/ class=\"blog_title\">");
							anchorElm.html("<span class=\"date\">" + returnDaysAgoString(base.published.$t) + "</span> " + base.title.$t);
							anchorElm.click(function() {
								$(this).next().animate({
									height: "toggle",
									opacity: "toggle"	
								}, 300);
								return false;
							});
							div.append(anchorElm);
							var newDiv = $("<div/>");
							newDiv.html(base.content.$t);
							div.append(newDiv);
							newDiv.hide();
							div.addClass(settings.className);
							divToAppendTo.append(div);
							div.find(".blogger-post-footer").remove();
						});
					}
				});
			});
			return this;
		},
		slideTo: function(leftPos, options) {
			var settings = $.extend({
				duration: "fast"
			}, options);
			
			this.each(function() {
				$(this).animate({
					left: leftPos
				}, settings.duration);
			});
		}
	}
	
	var applyCustomMethods = function(a) {
		a.each = function(a) {
			for(var i=0;i<this.length;i++) {
				a.call(this, this[i], i);
			}
		}
		return a;
	}
	
	function returnDaysAgoString(a) {
		
		var b = a.substring(8, 10) + " " + a.substring(4, 7) + " " + a.substring(26, 31) +  " " +  a.substring(11, 19) 
		
		var currentDate = new Date();
		var currentTime = currentDate.getTime();
		var dateOfPost = new Date(Date.parse(b.toString()));
		var timeOfPost = dateOfPost.getTime();
		
		var differenceBetweenDates = 0;
		differenceBetweenDates = dateOfPost - currentDate;
		var valueOfDifferenceInDays = Number(Math.round(differenceBetweenDates/(1000*60*60*24)).toString().substring(1));
		if(valueOfDifferenceInDays===0) {
			return "Today we said..."
		}
		else if(valueOfDifferenceInDays===1)
			return valueOfDifferenceInDays + " day ago we said..."
		else {
			return valueOfDifferenceInDays + " days ago we said..."
		}
	}
	
	$.fn.extend(pluginObj);
	$.extend($.expr[":"], rootPluginObj);

})(jQuery);
