/* 
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */


(function($){$.fn.caret=function(begin,end){if(this.length==0)return;if(typeof begin=='number'){end=(typeof end=='number')?end:begin;return this.each(function(){if(this.setSelectionRange){this.focus();this.setSelectionRange(begin,end);}else if(this.createTextRange){var range=this.createTextRange();range.collapse(true);range.moveEnd('character',end);range.moveStart('character',begin);range.select();}});}else{if(this[0].setSelectionRange){begin=this[0].selectionStart;end=this[0].selectionEnd;}else if(document.selection&&document.selection.createRange){var range=document.selection.createRange();begin=0-range.duplicate().moveStart('character',-100000);end=begin+range.text.length;}return{begin:begin,end:end};}};var charMap={'9':"[0-9]",'a':"[A-Za-z]",'*':"[A-Za-z0-9]"};$.mask={addPlaceholder:function(c,r){charMap[c]=r;}};$.fn.unmask=function(){return this.trigger("unmask");};$.fn.mask=function(mask,settings){settings=$.extend({placeholder:"_",completed:null},settings);var re=new RegExp("^"+$.map(mask.split(""),function(c,i){return charMap[c]||((/[A-Za-z0-9]/.test(c)?"":"\\")+c);}).join('')+"$");return this.each(function(){var input=$(this);var buffer=new Array(mask.length);var locked=new Array(mask.length);var valid=false;var ignore=false;var firstNonMaskPos=null;$.each(mask.split(""),function(i,c){locked[i]=(charMap[c]==null);buffer[i]=locked[i]?c:settings.placeholder;if(!locked[i]&&firstNonMaskPos==null)firstNonMaskPos=i;});function focusEvent(){checkVal();writeBuffer();setTimeout(function(){$(input[0]).caret(valid?mask.length:firstNonMaskPos);},0);};function keydownEvent(e){var pos=$(this).caret();var k=e.keyCode;ignore=(k<16||(k>16&&k<32)||(k>32&&k<41));if((pos.begin-pos.end)!=0&&(!ignore||k==8||k==46)){clearBuffer(pos.begin,pos.end);}if(k==8){while(pos.begin-->=0){if(!locked[pos.begin]){buffer[pos.begin]=settings.placeholder;if($.browser.opera){s=writeBuffer();input.val(s.substring(0,pos.begin)+" "+s.substring(pos.begin));$(this).caret(pos.begin+1);}else{writeBuffer();$(this).caret(Math.max(firstNonMaskPos,pos.begin));}return false;}}}else if(k==46){clearBuffer(pos.begin,pos.begin+1);writeBuffer();$(this).caret(Math.max(firstNonMaskPos,pos.begin));return false;}else if(k==27){clearBuffer(0,mask.length);writeBuffer();$(this).caret(firstNonMaskPos);return false;}};function keypressEvent(e){if(ignore){ignore=false;return(e.keyCode==8)?false:null;}e=e||window.event;var k=e.charCode||e.keyCode||e.which;var pos=$(this).caret();if(e.ctrlKey||e.altKey){return true;}else if((k>=41&&k<=122)||k==32||k>186){var p=seekNext(pos.begin-1);if(p<mask.length){if(new RegExp(charMap[mask.charAt(p)]).test(String.fromCharCode(k))){buffer[p]=String.fromCharCode(k);writeBuffer();var next=seekNext(p);$(this).caret(next);if(settings.completed&&next==mask.length)settings.completed.call(input);}}}return false;};function clearBuffer(start,end){for(var i=start;i<end&&i<mask.length;i++){if(!locked[i])buffer[i]=settings.placeholder;}};function writeBuffer(){return input.val(buffer.join('')).val();};function checkVal(){var test=input.val();var pos=0;for(var i=0;i<mask.length;i++){if(!locked[i]){while(pos++<test.length){var reChar=new RegExp(charMap[mask.charAt(i)]);if(test.charAt(pos-1).match(reChar)){buffer[i]=test.charAt(pos-1);break;}}}}var s=writeBuffer();if(!s.match(re)){input.val("");clearBuffer(0,mask.length);valid=false;}else
valid=true;};function seekNext(pos){while(++pos<mask.length){if(!locked[pos])return pos;}return mask.length;};input.one("unmask",function(){input.unbind("focus",focusEvent);input.unbind("blur",checkVal);input.unbind("keydown",keydownEvent);input.unbind("keypress",keypressEvent);if($.browser.msie)this.onpaste=null;else if($.browser.mozilla)this.removeEventListener('input',checkVal,false);});input.bind("focus",focusEvent);input.bind("blur",checkVal);input.bind("keydown",keydownEvent);input.bind("keypress",keypressEvent);if($.browser.msie)this.onpaste=function(){setTimeout(checkVal,0);};else if($.browser.mozilla)this.addEventListener('input',checkVal,false);checkVal();});};})(jQuery);


/** JQUERY TIMER **/


			jQuery.fn.extend({
				everyTime: function(interval, label, fn, times, belay) {
					return this.each(function() {
						jQuery.timer.add(this, interval, label, fn, times, belay);
					});
				},
				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: {
					guid: 1,
					global: {},
					regex: /^([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 = parseInt(result[1], 10);
							var mult = this.powers[result[2]] || 1;
							return num * mult;
						} else {
							return value;
						}
					},
					add: function(element, interval, label, fn, times, belay) {
						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 (times && times.constructor != Number) {
							belay = !!times;
							times = 0;
						}

						times = times || 0;
						belay = belay || false;

						if (!element.$timers)
							element.$timers = {};

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

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

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

						handler.$timerID = fn.$timerID;

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

						if ( !this.global[label] )
							this.global[label] = [];
						this.global[label].push( element );

					},
					remove: function(element, label, fn) {
						var timers = element.$timers, 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 )
								element.$timers = null;
						}
					}
				}
			});

			if (jQuery.browser.msie)
				jQuery(window).one("unload", function() {
					var global = jQuery.timer.global;
					for ( var label in global ) {
						var els = global[label], i = els.length;
						while ( --i )
							jQuery.timer.remove(els[i], label);
					}
				});





(function($) {



        $.fn.inputUpdater = function(options) {

        var main_options = $.extend({}, $.fn.inputUpdater.defaults, options);

        //clear errors
        $(".iu_validate_error").remove();

            return this.each(function() {
                $this = $(this);
                 // if metadata is present, extend main_opts, otherwise just use main_opts
                var options = $.meta ? $.extend({}, main_options, $this.data()) : main_options;


                if($this.attr('type')=='text')
                {
                     $this.unbind().focus(function(){$.fn.inputUpdater.focus(this,options);return false;});
                     $this.unbind().keyup(function(){$.fn.inputUpdater.keyup(this,options);return false;});
                }
                else if ($this.attr('class').match(/save/i))
                {
                     $this.unbind().click(function(){$.fn.inputUpdater.update(this,options);return false;});
                }
                else if ($this.attr('class')=='load')
                {
                    $.fn.inputUpdater.update(this,options);
                }
                else if ($this.attr('class').match(/insert/) !=null)
                {
                     $this.unbind().click(function(){$.fn.inputUpdater.full(this,options);return false;});
                }
                else if($this.attr('type') =='radio')
                {
                     $this.unbind().click(function(){$.fn.inputUpdater.radio(this,options);return true;});
                }
                else
                {

                     $this.unbind().change(function(){$.fn.inputUpdater.keyup(this,options);return false;});
                }
            });
        };

        $.fn.inputUpdater.focus = function(el,options) {  //on focus
           var $this = $(el);
        };

        $.fn.inputUpdater.keyup = function(el,options) { //if length is > 0 and check option setting for validation
                   $.fn.inputUpdater.clearTimer(el,options);
                   $.fn.inputUpdater.setTimer(el,options);
        };

        $.fn.inputUpdater.radio = function(el,options) { //if length is > 0 and check option setting for validation
                var $this = $(el);
                $this.attr('checked','checked');
                $.fn.inputUpdater.update($this,options);

        };

        $.fn.inputUpdater.validate = function(val, type) { //decide which validations to use
            var t = type.split(' ');
            var canSubmit = true;
            for(i=0;i<t.length;i++)
            {
                    if(t[i] == 'required') canSubmit = $.fn.inputUpdater.isRequired(val);
                    if(t[i] == 'alpha') canSubmit = $.fn.inputUpdater.isAlpha(val);
                    if(t[i] == 'numeric') canSubmit = $.fn.inputUpdater.isNumeric(val);
                    if(t[i].match(/date/gi)!=null) canSubmit = $.fn.inputUpdater.isDate(val);
                    if(t[i].match(/length/gi)!=null) canSubmit = $.fn.inputUpdater.isLength(val, t[i]);
                    if(t[i].match(/creditcarddate/gi)!=null) canSubmit = $.fn.inputUpdater.isCreditcarddate(val);
            }
        //    console.log(val+':'+canSubmit)
            return canSubmit;

        };

        $.fn.inputUpdater.isRequired = function(val) { //make sure value is not empty
         //   console.log(val.length)
            if(val.length > 0) return true;
            else return false;
        };

        $.fn.inputUpdater.isNumeric = function(val) { //make sure value is a digit
          //  console.log(val.match(/^\d*$/))
            if(val.match(/^\d*$/)!=null && val.match(/^\d*$/)!="") return true;
            else return false;
        };

        $.fn.inputUpdater.isAlpha = function(val) { //make sure value is a letter

            if(val.match(/\w/)!=null) return true;
            else return false;
        };

        $.fn.inputUpdater.isAlphaNumeric = function(val) { //make sure value is a letter or number
             if(val.match(/\d\w/)!=null) return true;
             else return false;
        };

        $.fn.inputUpdater.isDate = function(val) { //make sure value is a date
            //requires date.js
            val = ''+val;
            if(Date.parse(val) == null) return false;
            else return true;

        };


        $.fn.inputUpdater.isCreditcarddate = function(val) { //make sure value is a valid date for creditcard - date must be > today
            //requires date.js
            var today = Date.today().set({day:1});
            var future = Date.parse(''+val);
            if(Date.today().set({day:1}).compareTo(future) < 1) return true;
            else return false;

        };

        $.fn.inputUpdater.isLength = function(val,len) { //make sure value is a digit
            var s = len.split('_');
            if(val.length == s[1]) return true;
            else return false;
        };

        $.fn.inputUpdater.error = function(el,options){
            var $this = $(el);
            var id = $this.attr('id');
          //  console.log(id)

           // $("body").append('<div class="iu_validate_error body_validate" id="error_'+id+'" title="'+options.errorMessage+'">'+options.errorMessage+'</div>');

            $("body").append('<div id="error_'+id+'" class="iu_validate_error fg-tooltip ui-widget ui-widget-content ui-corner-all">'+options.errorMessage+'<div class="fg-tooltip-pointer-down ui-widget-content"><div class="fg-tooltip-pointer-down-inner"></div></div></div>')

            $("#error_"+id).alignElements(el,{alignHorizontal:'top',alignVertical:'center',modifyHorizontal:-5});

        };

         $.fn.inputUpdater.update = function(el,options){
            var $this = $(el);
            var form = {};
            var name = $this.attr('name');
            var value = $this.attr('value');

            if(value==null)
            {
                //see if there is a form field behind it
                value=$this.prev().val();
                name=$this.prev().attr('name');
            }


            var parent = $.fn.inputUpdater.getParent(el,options);
            parent.children('div').children('div.iu_validate_error').remove();
          //  debug(parent)
            var id = parent.attr('id');
            var id_split= id.split('_');
            form['id'] = id_split[1];
            form[name] = value;
            form['action'] = options.actionType;

            //convert date entries
            if(options.valueType.match(/creditcarddate/gi))
                {
                    var date = Date.parse(''+value);
                    if(date!=null) value = date.toString('MM / yyyy');
                    form[name] = value;
                    if($this.prev().attr('type')=='text') $this.prev().val(''+value);
                }

            var canSubmit = true;
            if($.isFunction(options.presubmitCallback)) canSubmit = options.presubmitCallback(el,parent,options);

            if(options.valueType!='')
                {

                    canSubmit = $.fn.inputUpdater.validate(value,options.valueType);
                }
            if(canSubmit) $.fn.inputUpdater.submit(el,options,form);
            else $.fn.inputUpdater.error($this,options);
        };

        $.fn.inputUpdater.getName = function(el)
        {
            var field = $(el).attr('name');
            var field_split = field.split('_');
            return field_split[0];
        }


        $.fn.inputUpdater.full = function(el,options){
            var $this = $(el);
            var form = {};

            var parent = $.fn.inputUpdater.getParent(el,options);
            var pID = parent.attr('id');

            var e = 0;

           $('#'+pID+' input').each(function(){
                var field = $.fn.inputUpdater.getName(this);



                if($(this).attr('type') == 'radio')
                {
                    if($(this).is(':checked')) form[field] = $(this).val();
                }
                else
                {
                     form[field] = $(this).val();
                }


                if($(this).attr('rel'))
                {
                    var type= $(this).attr('rel');
                    options.errorMessage = $(this).attr('msg');
                  //  console.log(options.errorMessage)
                    if(options.errorMessage == '' || options.errorMessage=='undefined') options.errorMessage = 'This field is required';

                    var canSubmit= $.fn.inputUpdater.validate(form[field],type);
                    if(!canSubmit)
                        {
                            $.fn.inputUpdater.error($(this),options);
                            e++;
                        }
                }

            });

            $('#'+pID+' select').each(function(){
               var field = $.fn.inputUpdater.getName(this);
               form[field] = $(this).val();

                if($(this).attr('rel'))
                {
                    var type= $(this).attr('rel');

                    var canSubmit= $.fn.inputUpdater.validate(form[field],type);
                    if(!canSubmit)
                        {
                            $.fn.inputUpdater.error($(this),options);
                            e++;
                        }
                }

            });

            form['action'] = options.actionType;
            if(options.actionType!='insert')
                {
                    var sid = pID.split('_');
                    form['id'] = sid[1];
                }

            if(e==0) $.fn.inputUpdater.submit(el,options,form);
        };


        $.fn.inputUpdater.submit = function(el,options,form)
        {
            $.ajax({
                url: options.submitPath,
                data:form,
                dataType: options.dataType,
				success: function (data, textStatus) {
                    $.fn.inputUpdater.responseSuccess(el,options,data)
                },
				error: function(XMLHttpRequest, textStatus, errorThrown){
                    $.fn.inputUpdater.responseError(el,options)
                },
				beforeSend: function (XMLHttpRequest) {
                    $.fn.inputUpdater.ajaxLoading(el,options)
                },
				complete: function (XMLHttpRequest) {
                    $.fn.inputUpdater.ajaxComplete(el,options)
                }
			});
        }


        $.fn.inputUpdater.getParent = function(el,options)
        {
            var $this=$(el);
            if(options.parent!='')
                {
                    //another hack :)
                    var theparent = $this.parents(options.parent);
                    if($this.parent().attr('class').match(/saveBTN/g)!='' && $this.parent().attr('class').match(/saveBTN/g)!=null)
                    {
                       theparent = $this.parent().next();
                    }

                    return theparent;
                }
            else return $this;
        }

        $.fn.inputUpdater.responseSuccess = function(el,options,data)
        {
            var $this = $(el);
            var parent = $.fn.inputUpdater.getParent(el,options);

            if(data.success==false)
            {
                $.fn.inputUpdater.jsonFail(el,options,data);
            }
            else
            {

            if(options.parent =='tr') parent.children('td').effect("highlight",{},2000);
            else  parent.effect("highlight",{},2000);


            $this.after('<div class="response_success"><img src="'+options.successImagePath+'"  /></div>');
            if($this.attr('name') == 'quantity' && $this.val()==0) $this.attr('name','delete');

            $this.siblings('div.response_success').oneTime(1000, function() {
                $(this).fadeOut(200,function(){
                    $(this).remove();
                    if($this.attr('name') == 'delete')
                    {
                        $this.parents(options.parent).fadeOut(500,function(){$(this).remove()});
                    }
                     if($.isFunction(options.submitCallback)) options.submitCallback(el,parent,options, data);
                });
            });

            }

        }

        $.fn.inputUpdater.jsonFail = function(el,options,data)
        {
            if(data.error == "Address not found")
                {

                    var html = '<li class="address_not_found" style="width:100%"><div class="alert"><input type="checkbox" name="overrideAddress" id="f_overrideAddressFailure" value="true" /> This address was not found in the USPS database. Please check this box and resubmit if you would like to use this address.</div></li>';
                    var parent = $.fn.inputUpdater.getParent(el,options);
                    if(parent.children('li').children('div.alert').length == 0) {
                        parent.prepend(html);
                        if($(".saveBTN").length > 0)
                        {
                         var t =  $(".saveBTN").offset();
                         $(".saveBTN").css({top:t.top + 20})
                        }
                    }
                }
            else
                {
                    options.errorMessage = data.error;
                     $.fn.inputUpdater.error(el,options);
                }
        }

        $.fn.inputUpdater.responseError = function(el,options)
        {
            var $this = $(el);
            var parent = $.fn.inputUpdater.getParent(el,options);
            if(options.parent =='tr') parent.children('td').effect("highlight",{color:'#f4760f'},2000);
            else  parent.effect("highlight",{color:'#f4760f'},2000);

            $this.after('<div class="response_error" title="there has been an error updating the database. please try again"><img src="'+options.errorImagePath+'"  /></div>');


            $this.siblings('div.response_error').oneTime(1000, function() {
                $(this).fadeOut(500,function(){$(this).remove()});
            });

        }

        $.fn.inputUpdater.ajaxLoading = function(el,options)
        {
            var $this = $(el);
            $this.after('<div class="loading"><img src="'+options.loadingImagePath+'" /></div>');
        }

        $.fn.inputUpdater.ajaxComplete = function(el,options)
        {
            var $this = $(el);
            if($this.siblings('div.loading').html()!=null) $this.siblings('div.loading').remove();
        }

        $.fn.inputUpdater.defaults = {
            valueType: '', //possible values = numeric, alpha, alphanumeric. any
            ajaxSubmit:'true', //submit the changes - for real-time updates, otherwise can use this for validation
            dataType: 'json', //how form submit data is returned - same params as jquery ajax object http://docs.jquery.com/Ajax/jQuery.ajax#options
            errorMessage: 'this field is required',
            actionType: 'update', //action taken by SQL
            submitSuccessMessage: null, //message for users when form submission succeeds
  			submitCallback: null, //callback function for submit
            presubmitCallback: null, //callback function for use before the submit - good for specialty validation
  			loadingImagePath: 'images/ajax-loader.gif', //location of loading animated gif
            errorImagePath: 'images/indicator_error.gif', //location of loading animated gif
            successImagePath: 'images/indicator_success.gif', //location of loading animated gif
            parent: ''
        };


       $.fn.inputUpdater.setTimer = function(el,options) {
			     	$(el).oneTime(500,"timer_",function () {

                        var $this = $(el);
                        var value = $this.val();
                        if(value.length > 0)
                        {

                         if($this.next().attr('class','iu_validate_error')) $this.next().remove();
                         var valid = $.fn.inputUpdater.validate(value,options.valueType);
                         if(valid) $.fn.inputUpdater.update($this,options);
                         else $.fn.inputUpdater.error($this,options);
                       }

			      	});

				}

		$.fn.inputUpdater.clearTimer = function(el){
					$(el).stopTime('timer_');
				}


        function debug($obj) {
          if (window.console && window.console.log)
            window.console.log($obj);
        };

    })(jQuery);
