/*!
 * @author stefan.schult
 * @id $Id: functions.js 208 2010-02-22 16:37:39Z stefan.schult $
 */

/**
 * @param {Object} context the 'this' value to be used.
 * @param {arguments} [1..n] optional arguments that are
 * prepended to returned function's call.
 * @return {Function} a function that applies the original
 * function with 'context' as the thisArg.
 */
Function.prototype.delegate = function(context){
  var fn = this,
      ap, concat, args,
      isPartial = arguments.length > 1;
  // Strategy 1: just bind, not a partialApply
  if(!isPartial) {
    return function() {
        if(arguments.length !== 0) {
          return fn.apply(context, arguments);
        } else {
          return fn.call(context); // faster in Firefox.
        }
      };
    } else {
    // Strategy 2: partialApply
    ap = Array.prototype,
    args = ap.slice.call(arguments, 1);
    concat = ap.concat;
    return function() {
      return fn.apply(context,
        arguments.length === 0 ? args :
        concat.apply(args, arguments));
    };
  }
};

(function() {
	if (typeof console == 'undefined') {
		window['console'] = {};
	}
	;
	if (typeof console.debug == 'undefined') {
		window['console'].debug = function() {
			if (typeof console.log == 'undefined') {
				//								var d = "";
				//								for(var i = 0; i<arguments.length; i++){
				//									d+= arguments[i] + "\n";
				//								}
				//								alert(d);
			}
			else console.log(arguments);
		};
	}
	window.fieldsetInitState = {};
}());



//
// create closure
//
(function($) {
	var Temp = function(){
		this.add = function(key, value){
			if(typeof this.values == "undefined")
				this.values = {};
			if(typeof this.values[key] == "undefined" || typeof this.values[key] == null)
				this.values[key] = 0;
			this.values[key]+=value;
			return this.values[key];
		};
		this.get = function(key){
			if(typeof this.values == "undefined")
				this.values = {};
			if(typeof this.values[key] == "undefined")
				this.values[key] = null;
			return this.values[key];
		};
		this.set = function(key, value){
			if(typeof this.values == "undefined")
				this.values = {};
			if(typeof this.values[key] == "undefined")
				this.values[key] = value;
			return this.values[key];
		};

	};

	function getDocHash(){
		var h = document.location.hash;
		return h.substr(h.indexOf('#')+1);
	}

	function getToggleText(element){
		var r = {};
		$(element).find('input[name^=toggleText]').each(function(){
			r[this.name.substring(10).toLowerCase()] = this.value;
		});
		return r;
	};

	function getButtonSwitch(element){
		var buttonSwitch = $('<p />').addClass('buttonSwitch');
		var link = $('<a />').attr('href', 'javascript:void(0)');
		buttonSwitch.append(link);
		return {
			p: buttonSwitch,
			a: link
		};
	};

	$.getBaseUri = function(){
		var b = $("base").attr("href");
		if(b) return $("base").attr("href");
		else return "";
	};

	$.formatCurrency= function(number){
		if(number == "") return number;
		number = '' + number;
		var numberSplit = number.split('.');
		number = numberSplit[0];
		var afterComma = ',' +((!numberSplit[1] || numberSplit[1].length == 0) ? '00' :
						 (numberSplit[1].length == 1) ? numberSplit[1] + '0' :
						 numberSplit[1]);
		var laenge = number.length;
		if (laenge > 3) {
			var mod = laenge % 3;
			var output = (mod > 0 ?
						  (number.substring(0,mod)) : '');
			for (i=0 ; i < Math.floor(laenge / 3); i++) {
				if ((mod == 0) && (i == 0)) output += number.substring(mod+ 3 * i,  mod + 3 * i + 3);
				else  output+= '.' + number.substring(mod + 3 * i, mod + 3 * i + 3);
			}
			return (output + afterComma);
		}
		else return number + afterComma;
	}

	$.fn.hasElements = function() {
		return this.length > 0;
	};

	$.fn.setTableObject = function() {
		return this.each(function(){

			var $this = $(this);
			var tableObject = {};
			tableObject.valueArray = {};
			var table = $this.find('table');
			table.addClass('inv');
			tableObject.highestKey = table.find('tr:last td:first-child').text().substr( 0, table.find('tr:last td:first-child').text().indexOf(",") ).replace( /\./g, "" )/10;


			var tr = table.find('tr');
			tr.each(
				function(j){
					if(j == 0) return;
					var $trThis = $(this);
					var td = $('td', $trThis);
					if( td.length == 0 )
					{
						return;
					}
					var trArray = {};
					var valueVon = $(td[0]).text();
					valueVon = valueVon.substr( 0, valueVon.indexOf(",") );
					trArray.result = valueVon;
					valueVon = valueVon.replace( /\./g, "" );
					if(valueVon != 0){
						valueVon = valueVon / 10;
					}
			//		console.debug(valueVon);
					trArray.persons = new Array(6);
					td.each(
						function(i){
							if(i == 0) return;
							switch( i )
							{
								case 1:
									break;
								default:
									trArray.persons[i-2] = $(this).text();
									break;
							}
						}
					);
					tableObject.valueArray[valueVon] = trArray;
				}
			);
			tableObject.keys = [];
			tableObject.getValue = function(k1){
				if(k1 != undefined){
					return this.valueArray[k1];
				} else {
					return this.valueArray[0];
				}
			};
			tableObject.lowestKey = 0;
			tableObject.getKeys = function(){
				if(this.keys.length == 0){
					for(var key in this.valueArray) {
						this.keys.push(key);
						this.highestKey = (key > this.highestKey) ? key : this.highestKey;
						this.lowestKey = (key < this.lowestKey) ? key : this.lowestKey;
					}
				}
				return this.keys;
			};
			tableObject.getHighestKey = function(){
				return this.highestKey;
			};
			tableObject.getLowestKey = function(){
				return this.lowestKey;
			};
			var defaultValue = tableObject.getValue();
			for(var i = 0; i <= tableObject.getHighestKey(); i++){
				tableObject.keys[i] = i;
				if(tableObject.getValue(i) == undefined){
					tableObject.valueArray[i] = {
						result: (i*10),
						persons: defaultValue.persons
					};
				}
			}
			tableObject.getKeys();
			$this.data('tableObject', tableObject);
		});
	};

	$.fn.faq = function(handler) {
		var globLi = [];
		var globDds = $();
		var globDts = $();
		var handlerHelper = function(){
			var $this = $(this);
			return {
				init: function(condition){
					if(handler != undefined){
						return handler.delegate( $this )().init.delegate(this)(condition);
					}
				},
				doSomething: function(condition){
					if(handler != undefined){
						return handler.delegate( $this )().doSomething.delegate( this )(condition);
					}
				}
			};
		};
		var linkHelper = function($this){
			var l = $('#' + this.href.substr(this.href.indexOf('#')+1));
			if(l){
				$(globDts).each(function(){
					var li = $(this);
					if(li.hasClass('chosen')){
						li.removeClass('chosen');
						handlerHelper.delegate( $this )().doSomething.delegate( $($(this).parent()) )(false);
					}
				});
				handlerHelper.delegate( $this )().doSomething.delegate( l )(true);
				l.addClass('chosen');
			}
		};
		var chosenDt = null;
		var hasSingleExpands = false;
		this.each(function() {
			var $this = $(this);
			hasSingleExpands = $this.hasClass('singleExpands');
			//var initIsExpanded = $this.hasClass('initIsExpanded');
			var dl = $('dl', $this);
			dl.find('dt').click(function(event){
				var isChosen = $(this).hasClass('chosen');
				if(!hasSingleExpands){
					globDts.removeClass('chosen').each(function(){
						handlerHelper.delegate($this)().doSomething.delegate(this)(false);
					});
					globDds.addClass('inv');
				}
				if(isChosen){
					console.debug(this, isChosen);
					$(this).removeClass('chosen');
					$(this).next().addClass('inv');
				} else {
					$(this).addClass('chosen');
					$(this).next().removeClass('inv');
				}
				handlerHelper.delegate($this)().doSomething.delegate(this)($(this).hasClass('chosen'));
			}).each(function(){
				var hasEqualHash = (this.id != "" && this.id == getDocHash());
				globDts.push(this);
				handlerHelper.delegate($this)().init.delegate(this)();
				globDds.push($(this).next()[0]);
				if(hasEqualHash){
					chosenDt = this;
				}
			});
			return;
		});
		globDts.each(function(){
			$(this).addClass('chosen').trigger('click');
		});
//		$(globDts[0]).addClass('chosen').trigger('click');
		if(chosenDt != null){
			$(chosenDt).trigger('click');
		}
		return this;
	};


	$.fn.expanders = function(options) {
		var defaults = {
			isAccordion: false
		};
		var options = $.extend({}, defaults, options);
		return this.each(function() {
			var $this = $(this);
			var isAccordion = options.isAccordion || $(this).hasClass('accordion');
			var toExpand =$('.toExpand', this);
			if(toExpand.length > 1){
				if(isAccordion){
					function setChosen(index) {
						return $this.attr("chosen", index);
					}
					function getChosen(reJquery){
						if(reJquery)
							return $this.find(".toExpand[index='"+getChosen()+"']");
						else
							return $this.attr("chosen");
					};
					function getChosenHead(reJquery){
						if(reJquery)
							return $this.find(".toExpand[index='"+getChosen()+"'] .expHead");
						else
							return $this.find(".toExpand[index='"+getChosen()+"'] .expHead")[0];
					}
					function getChosenContent(reJquery){
						if(reJquery)
							return $this.find(".toExpand[index='"+getChosen()+"'] .expContent");
						else
							return $this.find(".toExpand[index='"+getChosen()+"'] .expContent")[0];
					}
					$this.setClassAttributs("chosen");
					toExpand.each(function(i){
						$(this).attr("index", i);
						$('.expHead', this)
							.click(function(){
								if(getChosenHead() != this){
									getChosenContent(true).slideToggle('slow');
									$('.expContent', $(this).parent()).slideToggle('slow');
									setChosen($(this).parent().attr("index"));
								} else {
									getChosenContent(true).slideToggle('slow');
									setChosen(-1);
								}
								$(this).parent().toggleClass('notExpanded');
							});
						if(getChosen(true)[0] != this)
							$(this).addClass("notExpanded");
						if(i != getChosen()){
							$('.expContent', this).css('display', 'none');
						}
					}).addClass('hasJS');
				}else {
					toExpand.each(function(){
						$('.expHead', this)
							.click(function(){
								$('.expContent', $(this).parent()).slideToggle('slow');
								$(this).parent().toggleClass('notExpanded');
							});
						$(this).addClass("notExpanded");
						$('.expContent', this).css('display', 'none');
					}).addClass('hasJS');
				}
			}
		});
	};

	$.fn.toggleHiddenContent = function(buttonSwitchAfter) {
		return this.each(function() {
			var toggleText = getToggleText(this);
			var hiddenContent = $(this).find('.hiddenContent').addClass('inv');
			var buttonSwitch = getButtonSwitch(this);
			buttonSwitch.a.text(toggleText.open).click(function(){
				if(hiddenContent.hasClass('inv')){
					hiddenContent.removeClass('inv');
					$(this).text(toggleText.close);
					$(this).addClass('close');
				} else {
					hiddenContent.addClass('inv');
					$(this).text(toggleText.open);
					$(this).removeClass('close');
				}
			});
			$(this).find(buttonSwitchAfter).after(buttonSwitch.p);
		});
	};
	$.fn.video = function() {
		var t = new Temp();
		function getId(name, rfunc){
			var newId = name+(t.add('video', 1));
			if($('#' + newId).length > 0)
				getId(name, rfunc);
			else
				rfunc(newId);
		}
		return this.each(function() {
			var $this = $(this);
			var $parent = $this.parent();
			var img = $('img', $this);
			var dimensions = {
				width: img.width(),
				height: img.height()+20
			};
			if(swfobject.getFlashPlayerVersion().major >= 9) {
				$parent.height($parent.height()+20);
				if(!$this.attr('id')) {
					getId('videoPlayer', function(id){
						$this.attr('id', id);
					});
				};
				var flashvars = {file: $this.attr('href'), "image": img.attr('src')};
				var params = {'allowfullscreen':'true'};
				var attributes = {};
				swfobject.embedSWF($.getBaseUri()+"../swf/longtail/player.swf", $this.attr('id'), dimensions.width, dimensions.height, "9.0.0", false, flashvars, params, attributes);
			}
		});
	};
	$.fn.liToSelect = function(headline) {
		return this.each(function() {
			var $this = $(this);
			var $div = $("<div />").addClass("selects");
			var $headline = $this.find(headline).addClass("inv");
			$cont = $headline.next().each(function(){
				var div = $("<div />");
				var select = $("<select />");
				$(this).find("li a").each(function(){
					select[0].options[select[0].options.length] = new Option(this.firstChild.data, $(this).attr("href"), false, false);
				});
				div.append(select).append($("<button />")
						.attr({"class":"submit"})
						.click(function(){
							location.href = select[0].value;
						})
						.append($("<span />").append($("<span />").append($("<span />").append($("<span />").text("los"))))));
				$div.append(div);
				$(this).addClass("inv");
			});
			$this.find(":first").after($div);
		});
	};
	$.fn.additionalInput = function() {
		return this.each(function() {
			var $this = $(this);
			function checkState(checked){
				if(checked){
					$this[0].disabled = false;
				} else {
					$this[0].disabled = true;
					if($this[0].nodeName == "SELECT") {
						for(var i=0; i<$this[0].options.length; i++){
							if(i==0)
								$this[0].options[i].selected = true;
							else
								$this[0].options[i].selected = false;
						};
					} else if ($this[0].nodeName == "INPUT"){;
						$this[0].value = "";
					}
				}
				return checked;
			}
			var parentInput = $($this.parents()[1]).find("p:first input");
			checkState(parentInput[0].checked);
			$($this.parents()[2]).find('input[name="'+parentInput[0].name+'"]').change(function(){
				checkState(parentInput[0].checked);
			});
		});
	};
	$.fn.externLinks = function() {
		return this.each(function() {
			var t = $(this).text();
			$(this).text("");
			$(this).append("<span>"+t+"</span>");
			$(this).removeClass("extern");
			$(this).addClass("extern2");
		});
	};
	$.fn.inpPrefilled = function() {
		return this.each(function() {
			$(this).setClassAttributs('dvalue');
			$(this).setClassAttributs('showlabel');
			if($(this).attr('showlabel') != "true"){
				$("label[for='"+this.id+"']").addClass("inv");
			};
			var dv = $(this).attr('dvalue') || $("label[for='"+this.id+"']").text();
			if(this.value == ""){
				this.value = dv;
			}
			$(this).click(function(){
				if(this.value == dv){
					this.value = "";
				}
			});
			$(this).blur(function(){
				if(this.value == ""){
					this.value = dv;
				}
			});

		});
	};
	$.fn.datepicker = function() {
		return this.each(function() {
//			$(this).addClass("hasJs");
			$(this).find("input").each(function(){
				var labels = $($(this).parents()[1]).find("label.inv[for='"+this.id+"']");
				var labelText = jQuery.trim(labels.text());
				$(this).setClassAttributs("default");
				if(this.value == "") {
					this.value = $(this).attr("default").substring(0, $(this).attr("maxlength"));
				}
			});
//			$(this).click(function(){alert("Function not available!")});
		});
	};
	$.fn.setClassAttributs = function(attributeName) {
		return this.each(function() {
			var $this = $(this);
			var splitting = this.className.split(" ");
			for(var i= 0; i<splitting.length; i++) {
				if(splitting[i].indexOf(attributeName) != -1){
					var value = splitting[i].substring(splitting[i].indexOf("(")+1, splitting[i].indexOf(")"));
					if(value != "") {
						$this.attr(attributeName, value);
					}
					$(this).removeClass(splitting[i]);
				}
			}
		});
	};
	$.fn.xslider = function(data, handlers) {
		var settings = {
			widthScale: false
		}
		var handlerObject = {
			init: function($slider){
				return $slider;
			},
			changed: function(event) {}
		};

		$.extend(handlerObject, handlers);
		function getOffsetValues($lastScale){
			var p = $lastScale.offsetParent().width();
			var s = p/(data.length-1);
			return {
				parentWidth: p,
				splitWith: s,
				factor: s/p
			};
		}
		function initSlider(){
			var $sliderCont = $('<div class="iSliderCont" />');
			var $scaleCont = $('<div class="scaleCont" />');
			var $scale = null;
			if(settings.widthScale) {
				for(var i=1;i<data.length;i++){
					$scale = $('<div class="scale" />');
					$scale.css("width", 100/(data.length-1)*i+"%");
					$scaleCont.append($scale);
				}
			} else {
				$scale = $('<div class="scale" />');
				$scale.css("width", 100+"%");
				$scaleCont.append($scale);
			}
			var $sliderThumb = $('<div class="thumb" />');
			var $lastScale = $scaleCont.find('div.scale:last');
			$scaleCont.append($sliderThumb);
			$sliderCont.append($scaleCont);
			$lastScale.bind('click', function(event){
				var oValues = getOffsetValues($(this));
				var parentWidth = oValues.parentWidth;
				var splits = oValues.splitWith;
				var thumbLeft = event.pageX-$(this).offsetParent().offset().left;
				var optLength = data.length;
				var v = Math.floor((thumbLeft)/parentWidth*(optLength-1))+((thumbLeft%splits)/splits > 0.5);
				$sliderThumb.animate({'left':(oValues.factor*100*v)+"%"}, 500, function(){
					handlerObject.changed(v);
				});
			});
//			$select.bind('keyup', function(eventObject){
//				if(eventObject.keyCode != 9){
//					var oValues = getOffsetValues($(this));
//					var v = this.options.selectedIndex;
//					$sliderThumb.css({'left': (oValues.factor*100*v)+"%"});
//					updateSpan.delegate($span)(selectOption($select[0].options, v));
//				}
//			});
			var $sCont = $('<div class="sliderCont" />');
			return handlerObject.init($sCont.append($sliderCont));
		}
		return this.each(function() {
			function getThumbValue(){
				var value =  Math.floor(moving/parentWidth*data.length);
				if(value >options.length-1) value = data.length-1;
				if(value < 0) value = 0;
				return value;
			}
			var $this = $(this);
			var $slider = initSlider();
			$(this).replaceWith($slider);
			$this = $slider;
			var $thumb = $this.find(".thumb");
			var parentLeft = $thumb.offsetParent().offset().left;
			var parentWidth = $thumb.offsetParent().width();
			var options = data;
			var moving = 0;
			var thumbValue = 0;
			handlerObject.changed(thumbValue);
			$thumb.bind('drag', function(event){
					moving = event.cursorOffsetX+event.offsetX-parentLeft;
					if(moving >= 0 && moving <= parentWidth){
						$(this).css({
							left: moving
						});
						handlerObject.changed(getThumbValue());
					}
				})
				.bind('dragend', function (){
					thumbValue = getThumbValue();
					$(this).css("left", (thumbValue/(options.length-1)*100)+"%");
					if(options.selectedIndex != thumbValue)
						handlerObject.changed(thumbValue);
				})
				.css("left", (thumbValue/(options.length-1)*100)+"%");
		});
	};
	$.fn.textMaxlength = function() {
		return this.each(function() {
			var $this = $(this);
			$this.setClassAttributs("maxlength");
			$this.setClassAttributs("translateFrom");
			$this.setClassAttributs("translateCharacter");
			if($this.attr("maxlength") != undefined) {
				function countCharacters(){
					$this.siblings().text("("+$this[0].value.length+" "+$this.attr("translatefrom")+" "+$this.attr("maxlength")+" "+$this.attr("translatecharacter")+")");
				}
				$this.wrap('<div class="textareaMaxlengthMod" />');
				$($this.parents()[0]).append($("<span />"));
				countCharacters();
				this.onkeyup = function(){
					if(this.value.length > $this.attr("maxlength")) {
						this.value = this.value.substring(0, $this.attr("maxlength"));
					}
					countCharacters();
				};
			}
		});
	};
	$.fn.moneyCalculator = function(handler) {
		var sum = 0;
		var allFields = this;
		function normalizeNumber(value){
			value = value.replace(/\./g, "");
			value = value.replace(/\,/g, ".");
//			var returnNumber = (this.ceilInputValue) ? Math.ceil(Number(value)) : Number(value);
//			var returnNumber = Number(value);
//			return (!isNaN(returnNumber)) ? returnNumber : 0;
			return Number(value);
		};
		function calculate(){
			sum = 0;
			allFields.each(function(){
				var normNum = normalizeNumber(this.value);
				if(!isNaN(normNum)){
				//	normNum = (Math.round(normNum*100)/100);
					sum+=normNum;
				}
			});
			sum = Math.round(sum*100)/100;
			handler($.formatCurrency(sum) );
		}
		if($(this).hasElements()){
			this.each(function(){
				$(this).blur(function(){
					calculate();
				});
			});
			calculate();
		}
		return this;
	};
	$.fn.slideshow = function() {
		var t = new Temp();
		if(typeof window.slideshowFlashloaded == "undefined")
			window.slideshowFlashloaded = function(flashObjId){
				function showImage(image){
					flash.setPause();
					flash.showImage(image);
					return image;
				}
				var flash = $('#'+flashObjId)[0];
				flash.loadJSON(t.get(flashObjId));
				var $p = $('#'+flashObjId).parent();
				var items = 0;
				if($p.attr('enableskip') == "true"){
					var current = showImage(0);
					items = $p.attr("items");
					if($p.find("a").length == 0) {;
						var $next = $('<a href="javascript:void(0)" class="next" />');
						$next.append('<img src="'+$.getBaseUri()+'../img/style/icons/arrow_04204E.gif" />');
						$next.bind('click', function(){
							current++;
							if(current >= items) current = 0;
							current = showImage(current);
						});
						$p.append($next);
						var $prev = $('<a href="javascript:void(0)" class="prev" />');
						$prev.append('<img src="'+$.getBaseUri()+'../img/style/icons/arrow_right_dbe2ec.gif" />');
						$prev.bind('click', function(){
							current--;
							if(current < 0) current = items-1;
							current = showImage(current);
						});
						$p.append($prev);
					}
				}
			};
		function getId(name, rfunc){
			var newId = name+(t.add('idCounter', 1));
			if($('#' + newId).length > 0)
				getId(name, rfunc);
			else
				rfunc(newId);
		}

		return this.each(function() {
			var $this = $(this);
			var images = '{"images":[';
			var dimensions = {};
			$this.wrap('<div class="'+ this.className +'" />');
			var $p = $this.parent();
			$p.setClassAttributs("enableSkip");
			$p.setClassAttributs("dimW");
			$p.setClassAttributs("dimH");
			dimensions.width = $p.attr('dimw');
			dimensions.height = $p.attr('dimh');
			var l = $("img", this).each(function(i){
				images+= ((i==0) ? '' : ',') + '{';
				if(i==0){
					if(!dimensions.height) dimensions.height = $(this).height();
					if(!dimensions.width) dimensions.width = $(this).width();
				};
				var a = $(this).parent();
				images+='"image":"'+this.src+'"';
				images+=',"url":"'+a.attr('href')+'"';
				if(a.attr('target') != "")
					images+=',"target":"'+a.attr('target')+'"';

				images+='}';
			}).length;
			$p.attr("items", l);
			images+=']}';
			$this.height(dimensions.height);
			$this.width(dimensions.width);
			$this.css("overflow", "hidden");
			if(!$this.attr('id')) {
				getId('slideshow', function(id){
					$this.attr('id', id);
				});
			};
			t.set($this.attr('id'), images);
			var attributes = {
			  id: $this.attr('id'),
			  name: $this.attr('id')
			};
			var flashvars = {
				isLoaded:"slideshowFlashloaded",
				id:$this.attr('id'),
				delayTime:"0",
				intervalTime: "3000",
				autoStart: ($p.attr("autostart") != "true") ? "true" : "false"
			};
			var params = {
				wmode:"transparent",
				scalemode:"noscale"
			};
			swfobject.embedSWF("../swf/slideshow.swf", $this.attr('id'), dimensions.width, dimensions.height, "9.0.0", "expressInstall.swf", flashvars, params, attributes);
		});
	};
})(jQuery);

/**!
 * jQuery Maxlength plugin
 * @version		$Id: jquery.maxlength.js 18 2009-05-16 15:37:08Z emil@anon-design.se $
 * @package		jQuery maxlength 1.0.5
 * @copyright	Copyright (C) 2009 Emil Stjerneman / http://www.anon-design.se
 * @license		GNU/GPL, see LICENSE.txt
 */

(function($)
{

	$.fn.maxlength = function(options)
	{
		var settings = jQuery.extend(
		{
			events:				      [], // Array of events to be triggerd
			maxCharacters:		  10, // Characters limit
			status:				      true, // True to show status indicator bewlow the element
			statusClass:		    "status", // The class on the status div
			statusText:			    "character left", // The status text
			notificationClass:	"notification",	// Will be added to the emement when maxlength is reached
			showAlert: 			    false, // True to show a regular alert message
			alertText:			    "You have typed too many characters.", // Text in the alert message
			slider:				      false // Use counter slider
		}, options );

		// Add the default event
		$.merge(settings.events, ['keyup']);

		return this.each(function()
		{
			var item = $(this);
			var charactersLength = $(this).val().length;

      // Update the status text
			function updateStatus()
			{
				var charactersLeft = settings.maxCharacters - charactersLength;

				if(charactersLeft < 0)
				{
					charactersLeft = 0;
				}

				item.next("div").html(charactersLeft + " " + settings.statusText);
			}

			function checkChars()
			{
				var valid = true;

				// Too many chars?
				if(charactersLength >= settings.maxCharacters)
				{
					// Too may chars, set the valid boolean to false
					valid = false;
					// Add the notifycation class when we have too many chars
					item.addClass(settings.notificationClass);
					// Cut down the string
					item.val(item.val().substr(0,settings.maxCharacters));
					// Show the alert dialog box, if its set to true
					showAlert();
				}
				else
				{
					// Remove the notification class
					if(item.hasClass(settings.notificationClass))
					{
						item.removeClass(settings.notificationClass);
					}
				}

				if(settings.status)
				{
					updateStatus();
				}
			}

			// Shows an alert msg
			function showAlert()
			{
				if(settings.showAlert)
				{
					alert(settings.alertText);
				}
			}

			// Check if the element is valid.
			function validateElement()
			{
				var ret = false;

				if(item.is('textarea')) {
					ret = true;
				} else if(item.filter("input[type=text]")) {
					ret = true;
				} else if(item.filter("input[type=password]")) {
					ret = true;
				}

				return ret;
			}

			// Validate
			if(!validateElement())
			{
				return false;
			}

			// Loop through the events and bind them to the element
			$.each(settings.events, function (i, n) {
				item.bind(n, function(e) {
					charactersLength = item.val().length;
					checkChars();
				});
			});

			// Insert the status div
			if(settings.status)
			{
				item.after($("<div/>").addClass(settings.statusClass).html('-'));
				updateStatus();
			}

			// Remove the status div
			if(!settings.status)
			{
				var removeThisDiv = item.next("div."+settings.statusClass);

				if(removeThisDiv) {
					removeThisDiv.remove();
				}

			}

			// Slide counter
			if(settings.slider) {
				item.next().hide();

				item.focus(function(){
					item.next().slideDown('fast');
				});

				item.blur(function(){
					item.next().slideUp('fast');
				});
			}

		});
	};
})(jQuery);

/**
 * jQuery.timers - Timer abstractions for jQuery
 * Written by Blair Mitchelmore (blair DOT mitchelmore AT gmail DOT com)
 * Licensed under the WTFPL (http://sam.zoy.org/wtfpl/).
 * Date: 2009/10/16
 *
 * @author Blair Mitchelmore
 * @version 1.2
 *
 **/

jQuery.fn.extend({
	everyTime: function(interval, label, fn, times) {
		return this.each(function() {
			jQuery.timer.add(this, interval, label, fn, times);
		});
	},
	oneTime: function(interval, label, fn) {
		return this.each(function() {
			jQuery.timer.add(this, interval, label, fn, 1);
		});
	},
	stopTime: function(label, fn) {
		return this.each(function() {
			jQuery.timer.remove(this, label, fn);
		});
	}
});

jQuery.extend({
	timer: {
		global: [],
		guid: 1,
		dataKey: "jQuery.timer",
		regex: /^([0-9]+(?:\.[0-9]*)?)\s*(.*s)?$/,
		powers: {
			// Yeah this is major overkill...
			'ms': 1,
			'cs': 10,
			'ds': 100,
			's': 1000,
			'das': 10000,
			'hs': 100000,
			'ks': 1000000
		},
		timeParse: function(value) {
			if (value == undefined || value == null)
				return null;
			var result = this.regex.exec(jQuery.trim(value.toString()));
			if (result[2]) {
				var num = parseFloat(result[1]);
				var mult = this.powers[result[2]] || 1;
				return num * mult;
			} else {
				return value;
			}
		},
		add: function(element, interval, label, fn, times) {
			var counter = 0;

			if (jQuery.isFunction(label)) {
				if (!times)
					times = fn;
				fn = label;
				label = interval;
			}

			interval = jQuery.timer.timeParse(interval);

			if (typeof interval != 'number' || isNaN(interval) || interval < 0)
				return;

			if (typeof times != 'number' || isNaN(times) || times < 0)
				times = 0;

			times = times || 0;

			var timers = jQuery.data(element, this.dataKey) || jQuery.data(element, this.dataKey, {});

			if (!timers[label])
				timers[label] = {};

			fn.timerID = fn.timerID || this.guid++;

			var handler = function() {
				if ((++counter > times && times !== 0) || fn.call(element, counter) === false)
					jQuery.timer.remove(element, label, fn);
			};

			handler.timerID = fn.timerID;

			if (!timers[label][fn.timerID])
				timers[label][fn.timerID] = window.setInterval(handler,interval);

			this.global.push( element );

		},
		remove: function(element, label, fn) {
			var timers = jQuery.data(element, this.dataKey), ret;

			if ( timers ) {

				if (!label) {
					for ( label in timers )
						this.remove(element, label, fn);
				} else if ( timers[label] ) {
					if ( fn ) {
						if ( fn.timerID ) {
							window.clearInterval(timers[label][fn.timerID]);
							delete timers[label][fn.timerID];
						}
					} else {
						for ( var fn in timers[label] ) {
							window.clearInterval(timers[label][fn]);
							delete timers[label][fn];
						}
					}

					for ( ret in timers[label] ) break;
					if ( !ret ) {
						ret = null;
						delete timers[label];
					}
				}

				for ( ret in timers ) break;
				if ( !ret )
					jQuery.removeData(element, this.dataKey);
			}
		}
	}
});

jQuery(window).bind("unload", function() {
	jQuery.each(jQuery.timer.global, function(index, item) {
		jQuery.timer.remove(item);
	});
});