/*	******************************
		PLUGIN - Utility Functions 
		Author: Jack Lukic - KNI (all plugins)
		Notes: Used to extend jQuery functionality and shorten code
	******************************	*/

jQuery.fn.extend({
	// test if el is animated
	animated: function() {
		if(this.filter(':animated').size() > 0) {
			return true;
		}
		else {
			return false;	
		}
	},
	// test if el is visible
	visible: function() {
		if(this.filter(':visible').size() > 0) {
			return true;
		}
		else {
			return false;	
		}
	},
	// test if el exists
	exists: function() {
		if(this.size() > 0) {
			return true;
		}
		else {
			return false;	
		}
	}
});


jQuery.fn.extend({
	smoothHover: function(duration, params) {
		var settings = {
			instantOn: false,
			ieFix: true
		};
		var settings = $.extend(settings, params);
		if(settings.ieFix && $.browser.msie) {
			duration = 0;	
		}
		$(this).each(function() {
			var $this = $(this);
			var $target = $this;
			if(typeof(settings.target) != 'undefined') {
				$target = $(this).find(settings.target);
				console.log($target.size());
			}
			var $hover = $target.find('.hover');
			$this
				.bind('mouseenter', function() {
					if(!$this.hasClass('disabled')) {
						if(settings.instantOn) {
							$hover.show();
						}
						else {
							$hover
								.protectAnimation()
								.fadeIn(duration)
							;
						}
					  }
				})
				.bind('mouseleave', function() {
					if(!$this.hasClass('disabled')) {
						$hover
							.fadeOut(duration)
						;
					}
				})
			;
		});
		return this;
	},
	smoothDown: function(duration, params) {
		var settings = {
			click: function() {},
			instantOn: false,
			ieFix: true
		};
		var settings = $.extend(settings, params);
		if(settings.ieFix && $.browser.msie) {
			duration = 0;	
		}
		var userAgent = navigator.userAgent;
		var iPad = userAgent.match(/iPad/i) != null;
		var iPhone = userAgent.match(/iPhone/i) != null;
		
		$(this).each(function() {
			var $this = $(this);
			var $target = $this;
			if(typeof(settings.target) != 'undefined') {
				$target = $(this).find(settings.target);
			}
			var $hover = $target.find('.hover'),
				$down = $target.find('.down'),
				mousedownEvent = 'mousedown',
				mouseupEvent = 'mouseup'
			;
			if(iPad || iPhone) {
				var mousedownEvent = 'touchstart';
				var mouseupEvent = 'touchend';
			}
			$this
				.bind(mousedownEvent, function() {
					if(settings.instantOn) {
						$hover.hide();
						$down.show();
					}
					else {
						$hover.hide();
						$down.fadeIn(duration);
					}
					if(!(iPad || iPhone)) {
						$this.bind('mouseleave.escape', function() {
							$down.fadeOut(duration);
						});
					}
				})
				.bind(mouseupEvent, function() {
					if(!(iPad || iPhone)) {
						$this.unbind('mouseleave.escape');
					}
					$down.fadeOut(duration);
					settings.click($this);
				})
			;
		});
		return this;
	},
	forceHover: function() {
		$(this).each(function() {
			var $this = $(this);
			var offset = $this.offset();
			var width = $this.width();
			var height = $this.height();
			// look for first mousemove event
			$(document).bind('mousemove.poll', function(e) {
				var offsetX = e.pageX - offset.left;
				var offsetY = e.pageY - offset.top;
				if( (offsetX >= 0) && (offsetX <= width) && (offsetY <= height) && (offsetY >= 0) ) {
					$this.trigger('mouseenter');
				}
				$(document).unbind('mousemove.poll');
			});
		});
		return this;
	},
	protectAnimation: function() {
		$(this).each(function() {
			// stop current animation
			if($(this).filter(':animated').size() > 0) {
				$(this).stop();	
			}
			// prevent stuck style tag
			$(this).attr('style','');
		});
		return this;
	}
});


jQuery.fn.extend({
	inputPrompt: function(text, params) {
		// extensible
		var settings = {};
		jQuery.extend(settings, params);
		// iterate
		$(this).each(function() {
			// cache
			var $field = $(this);
			var $otherInputs = $(this).siblings('input');
			var $label = $field.prev('label');
			// functions
			var alphaKey = function(keyCode) {
				return (keyCode != 16 && keyCode != 13 && keyCode != 20 && keyCode != 20 && keyCode != 13 && keyCode != 38 && keyCode != 40 && keyCode != '')
					? true
					: false
				;
			};
			var checkField = function() {
				if($field.val() == '') {
					$label.html(text);
				}		
				else {				
					$label.html('&nbsp;');	
				}
			}
			// autocomplete fix
			$otherInputs.bind('keyup', function() {
				checkField();				
			});
			// init
			checkField();		
			// events
			$field
				.bind('change', function() {
					checkField()
				})
				.bind('keydown', function(event) {
					var keyCode = event.keyCode;
					if(keyCode == 13 || alphaKey(keyCode)) {
						$label.html('&nbsp;');						
					}
				})
				.bind('focus', function(){
					$field
						.one('click', function() {
							$field
								.bind('click.autocomplete', function() {
									// poll for input value change
									var poll = setInterval(function() {
										$otherInputs.each(function() {
											var $input = $(this);
											if($input.val() != '') {
												$input.prev('label').html('&nbsp;');	
											}
										});
										if($field.val() != '') {
											$label.html('&nbsp;');
											clearInterval($field.data('poll'));
										}
									}, 50);
									$field.data('poll', poll);			
								})
							;
						})
						.addClass('focus')
					;
					$label.addClass('focus');
					checkField();
				})
				.bind('blur', function(){
					var poll = $field.data('poll');
					if(typeof(poll) == 'timer') {
						clearInterval(poll);	
					}
					$field
						.unbind('.autocomplete')
						.removeClass('focus')
					;
					$label.removeClass('focus');
					checkField();
				})
			;
		});
		return this;
	}
});


/*	******************************
		PLUGIN - Follow Link 
		Author: Jack Lukic - KNI
		Last revision: July 2010
	******************************	*/
jQuery.fn.extend({
	followLink: function(filter) {
		return $(this).each(function() {
			$(this).bind('click', function() {
				if(typeof filter == 'undefined') {
					var $link = $(this).find('a').eq(0);
					var href = $link.attr('href');
					var target = $link.attr('target');
				}
				else {
					var $link = $(this).find(filter).eq(0).attr('href');
					var href = $link.attr('href');
					var target = $link.attr('target');
				}
				if(href) {
					// find base 
					var base = $('base').attr('href');
					if(target == '_blank') {
						window.open(base + href);
					}
					else {
						window.location.href = base + href;	
					}
				}
				return false;
			});
		});
	}
});



/*	******************************
		PLUGIN - Dim Screen
		Author: Jack Lukic - KNI 
		Last revision: June 2009
	******************************	*/
jQuery.extend( {
    dimScreen: function(speed, opacity, callback) {
		if(typeof speed == 'function') {
            callback = speed;
            speed = null;
        }
        if(typeof opacity == 'function') {
            callback = opacity;
            opacity = null;
        }
        if(speed < 1 && speed > 0) {
            var placeholder = opacity;
            opacity = speed;
            speed = placeholder;
        }
        if(opacity >= 1) {
            var placeholder = speed;
            speed = opacity;
            opacity = placeholder;
        }
		
		speed = (speed >= 0) ? speed : 200;
        opacity = (opacity > 0) ? opacity : 0.22;
		
		if($('#dimmer').size() < 1) {
			jQuery('<div/>').attr('id','dimmer-wrapper').appendTo(document.body).html(jQuery('<div/>').attr('id','dimmer'));
			var curOpacity = $('#dimmer').css('opacity');
			
			if(curOpacity != opacity) {
				if(speed == 0) {
					$('#dimmer').css({ opacity: opacity, visibility: 'visible' });
					$('#dimmer-wrapper').css({ visibility: 'visible' });
				}
				else {
					$('#dimmer, #dimmer-wrapper').css({	visibility: 'visible'});
					$('#dimmer').css({ opacity: '0.00'});
					
					$('#dimmer').fadeTo(speed, opacity, callback);
				}			
			}
		}
	},
    unDimScreen: function(speed) {
		speed = (speed >= 0 && typeof(speed) != 'undefined') ? speed : 200;
		if($('#dimmer').size() > 0) {
			if(speed == 0) {
				return $('#dimmer, #dimmer-wrapper').css({
					visibility: 'hidden'
				});
				$('#dimmer, #dimmer-wrapper').remove();
			}
			else {
				$('#dimmer').fadeTo(speed, '0.00', function(){					
					$('#dimmer, #dimmer-wrapper').remove();
				});
			}
		}
	}
});



/*	******************************
		PLUGIN - 
		Hover / Focus Class - Add class for css hover and focus 
		Force Hover - check mouse position to trigger hover
		
		Author: Jack Lukic - KNI
		Last revision: November 2009
	******************************	*/
	
jQuery.fn.extend({
	hoverClass: function(className, params) {
		if(typeof(className) == 'undefined') {
			var className = 'hover';
		}
		if(typeof(className) == 'object') {
			params = className;
			className = 'hover';
		}
		var settings = {
			useLive: false,
			filter: ''
		}
		$.extend(settings, params);
		
		var userAgent = navigator.userAgent;
		var iPad = userAgent.match(/iPad/i) != null;
		var iPhone = userAgent.match(/iPhone/i) != null;
		
		if(!iPad && !iPhone) {
			$(this).each(function() {
				if(settings.useLive) {	
					$(this).live('mouseover',function(){
						if(settings.filter == '' || $(this).filter(settings.filter).size() == 0) { 
							$this.addClass(className);
						}
					});
					$(this).live('mouseout', function() {
						if(settings.filter == '' || $(this).filter(settings.filter).size() == 0) {
							$this.removeClass(className);							  
						}
					});	
				}
				else {
					$(this).hover(function(){
						if(settings.filter == '' || $(this).filter(settings.filter).size() == 0) {
							$(this).addClass(className);							  
						}				   
					},
					function() {
						if(settings.filter == '' || $(this).filter(settings.filter).size() == 0) {
							$(this).removeClass(className);							  
						}
					});
				}
			});
		}
		return this;
	},
	touchClass: function(className, params) {
		if(typeof(className) == 'undefined') {
			var className = 'hover';
		}
		if(typeof(className) == 'object') {
			params = className;
			className = 'hover';
		}
		var settings = {
			filter: ''
		}
		$.extend(settings, params);
		
		var userAgent = navigator.userAgent;
		var iPad = userAgent.match(/iPad/i) != null;
		var iPhone = userAgent.match(/iPhone/i) != null;
		
		if(iPad || !iPhone) {
			$(this).each(function() {
				$(this)
					.bind('touchstart', function(){
						if(settings.filter == '' || $(this).filter(settings.filter).size() == 0) {
							$(this).addClass(className);							  
						}				   
					})
					.bind('touchend', function() {
						if(settings.filter == '' || $(this).filter(settings.filter).size() == 0) {
							$(this).removeClass(className);							  
						}
					})
				;
			});
		}
		return this;
	},
	downClass: function(className, params) {
		if(typeof(className) == 'undefined') {
			var className = 'down';
		}
		if(typeof(className) == 'object') {
			params = className;
			className = 'down';
		}
		var settings = {
			useLive: false,
			filter: ''
		}
		$.extend(settings, params);
		
		var userAgent = navigator.userAgent,
			iPad = userAgent.match(/iPad/i) != null,
			iPhone = userAgent.match(/iPhone/i) != null,
			downEvent = 'mousedown',
			upEvent = 'mouseup'
		;			
		if(iPad || iPhone) {
			downEvent = 'touchstart';
			upEvent = 'touchend';	
		}
		
		$(this).each(function() {
			if(settings.useLive) {	
				$(this).live(downEvent,function(){
					if(settings.filter == '' || $(this).filter(settings.filter).size() == 0) { 
						$this.addClass(className);
					}
				});
				$(this).live(upEvent, function() {
					if(settings.filter == '' || $(this).filter(settings.filter).size() == 0) {
						$this.removeClass(className);							  
					}
				});	
			}
			else {
				$(this)
					.bind(downEvent, function(){
						if(settings.filter == '' || $(this).filter(settings.filter).size() == 0) {
							$(this).addClass(className);							  
						}				   
					})
					.bind(upEvent, function() {
						if(settings.filter == '' || $(this).filter(settings.filter).size() == 0) {
							$(this).removeClass(className);							  
						}
					})
				;
			}
		});
		return this;
	},
	focusClass: function(className, params) {
		if(typeof(className) == 'undefined') {
			var className = 'active';
		}
		if(typeof(className) == 'object') {
			params = className;
			className = 'active';
		}
		var settings = {
			filter: ''
		}
		$.extend(settings, params);
		
		$(this).each(function() {
			$(this)
				.focus(function(){
					if(settings.filter == '' || $(this).filter(settings.filter).size() == 0) {
						$(this).addClass(className);							  
					}				   
				})
				.blur(function() {
					if(settings.filter == '' || $(this).filter(settings.filter).size() == 0) {
						$(this).removeClass(className);							  
					}
				})
			;
		});
		return this;
	},
	forceHover: function() {
		$(this).each(function() {
			var $this = $(this);
			var offset = $this.offset();
			var width = $this.width();
			var height = $this.height();
			// look for first mousemove event
			$(document).bind('mousemove.poll', function(e) {
				var offsetX = e.pageX - offset.left;
				var offsetY = e.pageY - offset.top;
				if( (offsetX >= 0) && (offsetX <= width) && (offsetY <= height) && (offsetY >= 0) ) {
					$this.trigger('mouseover');
				}
				$(document).unbind('mousemove.poll');
			});
		});
		return this;
	}
});

/*	******************************
		PLUGIN - 
		Validate Form
		
		Author: Jack Lukic - KNI
		Last revision: April 2010
	******************************	*/

jQuery.fn.extend({
	validateForm: function(fields, params) {
		// extensible
		var settings = {
			animateSpeed: 150,
			inlinePrompt: true,
			promptClass: 'prompt',
			onValid: function($field) {
				$field.removeClass('warn');
			},
			onInvalid: function($field) {
				$field.addClass('warn');
			},
			onSuccess: function() {
				return true;
			},
			onFailure: function() {
				return false;	
			},
			validate: {
				empty: function(value) {
					return !(typeof(value) == 'undefined' || '' == value);
				},
				email: function(value){
					var regex = new RegExp("[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?");	
					return regex.test(value);
				},
				match: function(value, matchingField) {
					var matchingValue = $('#'+matchingField).val();
					return (value.toString() == matchingValue.toString());
				},
				not: function(value, notValue) {
					return (value != notValue);	
				},
				url: function(value) {
					var regexp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/;
					return regexp.test(value);
				}
			}
		};	
		jQuery.extend(settings, params);
		// reduce object depth to validation (performance)
		var validate = settings.validate;
		// init blank errors object
		// iterate over all forms
		$(this).each(function() {
			// attach event handler
			$(this).submit(function() {
				// start off with a clean record
				var errors = [];
				var allValid = true;
				jQuery.each(fields, function(fieldName, field) {
					var fieldValid = true;
					// cache jq
					var $field = $('#'+field[0].identifier);
					// iterate over all validation types for a certain field
					jQuery.each(field, function(i, validation) {
						if($field.size() > 0) {
							var $promptField = $field.next('.' + settings.promptClass);	
							var promptExists = ($promptField.size() != 0);
							// vars				
							var type = validation.type;
							var value = $field.val();
							// pull out bracketed data
							var bracketRegExp = /\[(.*?)\]/i;
							var bracket = bracketRegExp.exec(type);
							// if bracket notation is used, pass in extra parameters
							if(typeof(bracket) != 'undefined' && bracket != null) {
								var ancillary = bracket[1];
								var functionType = type.replace(bracket[0],'');
								var isValid = validate[functionType](value, ancillary);
							}
							else {
								// call validate function specified to determine validness
								var isValid = validate[type](value);	
							}
							if(!isValid) {
								if(settings.inlinePrompt) {
									// create message container on first invalid validation attempt	
									if(!promptExists) {
										var $promptField = $('<div />')
											.addClass(settings.promptClass)
											.insertAfter($field)
										;
									}
									// add prompt message
									$promptField
										.html(validation.prompt)
										.fadeIn(settings.animateSpeed)
									;
								}
								// Add error
								errors.push(validation.prompt);
								// form invalid
								fieldValid = false;
								allValid = false;								
								// break each loop for this field
								return false;
							}
							else {
								// hide prompt
								if(settings.inlinePrompt) {
									$promptField.hide();
								}
							}
						}
					});
					// Field callback
					if(fieldValid) {
						settings.onValid($field);
					}
					else {
						settings.onInvalid($field);
					}
				});
				// Evaluate form callbacks
				if(allValid) {
					return settings.onSuccess();	
				}
				else {
					return settings.onFailure(errors);	
				}
			});				
		});		
		return this;
	}
});

/*
 * jQuery.Preload
 * Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com
 * Dual licensed under MIT and GPL.
 */
;(function($){var n=$.preload=function(c,d){if(c.split)c=$(c);d=$.extend({},n.defaults,d);var f=$.map(c,function(a){if(!a)return;if(a.split)return d.base+a+d.ext;var b=a.src||a.href;if(typeof d.placeholder=='string'&&a.src)a.src=d.placeholder;if(b&&d.find)b=b.replace(d.find,d.replace);return b||null}),g={loaded:0,failed:0,next:0,done:0,total:f.length};if(!g.total)return m();var h='<img/>',j=d.threshold;while(--j>0)h+='<img/>';h=$(h).load(k).error(k).bind('abort',k).each(l);function k(e){g.found=e.type=='load';g.image=this.src;var a=g.original=c[this.index];g[g.found?'loaded':'failed']++;g.done++;if(d.placeholder&&a.src)a.src=g.found?g.image:d.notFound||a.src;if(d.onComplete)d.onComplete(g);if(g.done<g.total)l(0,this);else{if(h.unbind)h.unbind('load').unbind('error').unbind('abort');h=null;m()}};function l(i,a,b){if($.browser.msie&&g.next&&g.next%n.gap==0&&!b){setTimeout(function(){l(i,a,1)},0);return!1}if(g.next==g.total)return!1;a.index=g.next;a.src=f[g.next++];if(d.onRequest){g.image=a.src;g.original=c[g.next-1];d.onRequest(g)}};function m(){if(d.onFinish)d.onFinish(g)}};n.gap=14;n.defaults={threshold:2,base:'',ext:'',replace:''};$.fn.preload=function(a){n(this,a);return this}})(jQuery);

