/*	******************************
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;
        }
    }
});

/*	******************************
PLUGIN - Protect Animation
Author: Jack Lukic - KNI
Notes: Prevents stuck animations with stop
******************************	*/

jQuery.fn.extend({
    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;
    }
});
/*	******************************
PLUGIN - Default Text 
Author: Jack Lukic - KNI
Last revision: March 2009
******************************	*/

jQuery.fn.extend({
    preserveDefaultText: function(params) {
        var settings = {
            defaultValue: '',
            replaceValue: '',
            alwaysReplace: false,
            disabledClassList: '.readonly, .disabled'
        };
        jQuery.extend(settings, params);
        // no replaced start value for IE
        if ($.browser.msie) {
            settings.defaultValue = '';
            settings.replaceValue = '';
        }
        $(this).each(function() {
            if (settings.defaultValue == '') {
                settings.defaultValue = $(this).val();
            }
            $(this)
				.bind('focus', function() {
				    if (!$(this).filter(settings.disabledClassList).size() > 0) {
				        if (settings.alwaysReplace) {
				            $(this).attr('last', $(this).val());
				            $(this).val(settings.replaceValue);
				        }
				        else {
				            if ($(this).val() == settings.defaultValue) {
				                $(this).val(settings.replaceValue);
				            }
				        }
				    }
				    $(this).select();
				})
				.bind('blur', function() {
				    if (!$(this).filter(settings.disabledClassList).size() > 0) {
				        if ($(this).val() == settings.replaceValue) {
				            if (settings.alwaysReplace) {
				                $(this).val($(this).attr('last'));
				                $(this).removeAttr('last');
				            }
				            else {
				                $(this).val(settings.defaultValue);
				            }
				        }
				    }
				})
			;
        });
        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) {
                    return /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.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);
                },
                zip: function(value) {
                    return /(^\d{5}$)|(^\d{5}-\d{4}$)/.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) {
                    // cache jq
                    var $field = $('#' + fieldName);
                    var fieldValid = true;
                    // iterate over all validation types for a certain field
                    jQuery.each(field, function(i, validation) {
                        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;
    }
});

/*	******************************
PLUGIN - 
Input text prompt underlay
		
Author: Jack Lukic - KNI
Last revision: April 2010
******************************	*/

jQuery.fn.extend({
    inputPrompt: function(text, params) {
        // extensible
        var settings = {};
        jQuery.extend(settings, params);
        // iterate
        $(this).each(function() {
            // cache
            var $field = $(this);
            var $label = $field.prev('label');
            // init
            var hasUserText = true;
            if ($(this).val() == '') {
                $label.html(text);
                var hasUserText = false;
            }
            // events
            $field.keypress(function() {
                $label.html(' ');
            });
            $field.focus(function() {
                $label.addClass('focus');
                $field.addClass('focus');
            });
            $(this).blur(function() {
                $label.removeClass('focus');
                $field.removeClass('focus');
                if ($(this).val() == '') {
                    $label.html(text);
                }
                else {
                    $label.html(' ');
                }
            });
        });
        return this;
    }
});



/*	******************************
PLUGIN - 
Down / Hover / Focus Class - Add class for css down hover and focus 
Force Hover - check mouse position to trigger hover
		
Author: Jack Lukic - KNI
Last revision: November 2009
******************************	*/
jQuery.fn.extend({
    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);
        $(this).each(function() {
            if (settings.useLive) {
                $(this).live('mousedown', function() {
                    if (settings.filter == '' || $(this).filter(settings.filter).size() == 0) {
                        $this.addClass(className);
                    }
                });
                $(this).live('mouseup', function() {
                    if (settings.filter == '' || $(this).filter(settings.filter).size() == 0) {
                        $this.removeClass(className);
                    }
                });
            }
            else {
                $(this).bind('mousedown', function() {
                    if (settings.filter == '' || $(this).filter(settings.filter).size() == 0) {
                        $(this).addClass(className);
                        // bind mouseleave event to fix down sticky
                        $(this).bind('mouseleave.fix', function() {
                            $(this).removeClass(className);
                        });
                    }
                });
                $(this).bind('mouseup', function() {
                    if (settings.filter == '' || $(this).filter(settings.filter).size() == 0) {
                        $(this).removeClass(className);
                        // remove down sticky handler
                        $(this).unbind('mouseleave.fix');
                    }
                });
            }
        });
        return this;
    },
    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);
        $(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;
    },
    focusClass: function(className, params) {
        if (typeof (className) == 'undefined') {
            var className = 'focus';
        }
        if (typeof (className) == 'object') {
            params = className;
            className = 'focus';
        }
        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;
    }
});

jQuery.fn.extend({
    smoothHover: function(duration, params) {
        var settings = {
            instantOn: false,
            ieFix: false
        };
        var settings = $.extend(settings, params);
        if (settings.ieFix && $.browser.msie) {
            duration = 0;
        }
        $(this).each(function() {
            var $hover = $(this).find('.hover');
            $(this)
				.hover(function() {
				    if (!$(this).hasClass('disabled')) {
				        if (settings.instantOn) {
				            $hover.show();
				        }
				        else {
				            $hover
								.protectAnimation()
								.fadeIn(duration)
							;
				        }
				    }
				}, function() {
				    if (!$(this).hasClass('disabled')) {
				        $hover
							.fadeOut(duration)
						;
				    }
				})
			;
        });
        return this;
    },
    smoothDown: function(duration, params) {
        var settings = {
            fixClick: true,
            instantOn: false,
            ieFix: false
        };
        var settings = $.extend(settings, params);
        if (settings.ieFix && $.browser.msie) {
            duration = 0;
        }
        $(this).each(function() {
            $(this).bind('mousedown', function() {
                if (!$(this).hasClass('disabled')) {
                    if (settings.instantOn) {
                        $(this).find('.hover').hide();
                        $(this).find('.down').show();
                    }
                    else {
                        $(this).find('.hover')
							.fadeOut(duration)
						;
                        $(this).find('.down')
							.protectAnimation()
							.fadeIn(duration)
						;
                    }
                }
            });
            $(this).bind('mouseup', function() {
                if (!$(this).hasClass('disabled')) {
                    $(this)
						.forceHover()
						.unbind('mouseleave.escape')
						.find('.down')
							.fadeOut(duration)
					;
                }
            });
            $(this).bind('mouseleave.escape', function() {
                $(this).trigger('mouseup');
            });
            if (settings.fixClick) {
                $(this).find('.down').bind('mouseup', function() {
                    $(this).parent()
						.click()
					;
                });
            }
        });
        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;
    }
});
