/**
 * ajaxSubmit() provides a mechanism for submitting an HTML form using AJAX.
 * @author jQuery Community
 */
jQuery.fn.ajaxSubmit = function(target, post_cb, pre_cb, url, mth, semantic) {
    var a = this.formToArray(semantic);
    
    // give pre-callback opportunity to abort the submit
    if (pre_cb && pre_cb.constructor == Function && pre_cb(a, this) === false) return;

    url = url || this.attr('action') || '';
    mth = (mth || this.attr('method') || 'GET').toUpperCase();
    var q = jQuery.param(a);
    var get = mth == 'GET';

    if (get) url = url + '?' + q;
    
    // if no target or 'post' callback was provided then default to a callback
    // that evals the response
    var t = target || post_cb || function(r) {
            if (r.responseText) eval.call(window, r.responseText)
        };
    if (t && t.constructor != Function)
        jQuery(t).load(url, get ? null : a, post_cb);
    else       
		jQuery.ajax({ url: url, success: t, data: get ? null : q, type: mth });
    return this;
};


/**
 * ajaxForm() provides a mechanism for fully automating form submission.
 * @author jQuery Community
 */
jQuery.fn.ajaxForm = function(target, post_cb, pre_cb, semantic) {
    return this.each(function() {
        jQuery("input[@type=submit],input[@type=image]", this).click(function(ev) {
            this.form.clk = this;
            
            if (ev.offsetX != undefined) {
                this.form.clk_x = ev.offsetX;
                this.form.clk_y = ev.offsetY;
            } else if (typeof jQuery.fn.offset == 'function') { // use dimensions plugin if it's installed
                var offset = $(this).offset();
                this.form.clk_x = ev.pageX - offset.left;
                this.form.clk_y = ev.pageY - offset.top;
            } else {
                this.form.clk_x = ev.pageX - this.offsetLeft;
                this.form.clk_y = ev.pageY - this.offsetTop;
            }
        })
    }).submit(function(e) {
        jQuery(this).ajaxSubmit(target, post_cb, pre_cb, null, null, semantic);
        return false;
    });
};


/**
 * formToArray() gathers form element data into an array of objects that can
 * be passed to any of the following ajax functions: $.get, $.post, or load.
 * @author jQuery Community
 */
jQuery.fn.formToArray = function(semantic) {
    var a = [];
    var q = semantic ? ':input' : 'input,textarea,select,button';
    
    jQuery(q, this).each(function() {
        var n = this.name;
        var t = this.type;

        if ( !n || this.disabled || t == 'reset' ||
            (t == 'checkbox' || t == 'radio') && !this.checked ||
            (t == 'submit' || t == 'image' || t == 'button') && this.form && this.form.clk != this ||
            this.tagName.toLowerCase() == 'select' && this.selectedIndex == -1)
            return;

        if (t == 'image' && this.form.clk_x != undefined)
            return a.push(
                {name: n+'_x', value: this.form.clk_x},
                {name: n+'_y', value: this.form.clk_y}
            );

        if (t == 'select-multiple') {
            jQuery('option:selected', this).each( function() {
                a.push({name: n, value: this.value});
            });
            return;
        }
        a.push({name: n, value: this.value});
    });
    return a;
};

/**
 * serializes form data into a 'submittable' string.  This method will return a string 
 * in the format: name1=value1&name2=value2 
 * @author jQuery Community
 */
jQuery.fn.serialize = function(semantic) {
    //hand off to jQuery.param for proper encoding
    return jQuery.param(this.formToArray(semantic));
};

/** 
 * This plugin overrides jQuery's height() and width() functions and
 * adds more handy stuff for cross-browser compatibility.
 */

/**
 * Returns the css height value for the first matched element.
 * If used on document, returns the document's height (innerHeight)
 * If used on window, returns the viewport's (window) height
 */
jQuery.fn.height = function() {
	if ( this.get(0) == window )
		return self.innerHeight ||
			jQuery.boxModel && document.documentElement.clientHeight ||
			document.body.clientHeight;
	
	if ( this.get(0) == document )
		return Math.max( document.body.scrollHeight, document.body.offsetHeight );
	
	return this.css("height");
};

/**
 * Returns the css width value for the first matched element.
 * If used on document, returns the document's width (innerWidth)
 * If used on window, returns the viewport's (window) width
 */
jQuery.fn.width = function() {
	if ( this.get(0) == window )
		return self.innerWidth ||
			jQuery.boxModel && document.documentElement.clientWidth ||
			document.body.clientWidth;
	
	if ( this.get(0) == document )
		return Math.max( document.body.scrollWidth, document.body.offsetWidth );
	
	return this.css("width");
};

/**
 * Returns the inner height value (without border) for the first matched element.
 * If used on document, returns the document's height (innerHeight)
 * If used on window, returns the viewport's (window) height
 */
jQuery.fn.innerHeight = function() {
	return this.get(0) == window || this.get(0) == document ?
		this.height() :
		this.get(0).offsetHeight - parseInt(this.css("borderTop") || 0) - parseInt(this.css("borderBottom") || 0);
};

/**
 * Returns the inner width value (without border) for the first matched element.
 * If used on document, returns the document's Width (innerWidth)
 * If used on window, returns the viewport's (window) width
 */
jQuery.fn.innerWidth = function() {
	return this.get(0) == window || this.get(0) == document ?
		this.width() :
		this.get(0).offsetWidth - parseInt(this.css("borderLeft") || 0) - parseInt(this.css("borderRight") || 0);
};

/**
 * Returns the outer height value (including border) for the first matched element.
 * Cannot be used on document or window.
 */
jQuery.fn.outerHeight = function() {
	return this.get(0) == window || this.get(0) == document ?
		this.height() :
		this.get(0).offsetHeight;	
};

/**
 * Returns the outer width value (including border) for the first matched element.
 * Cannot be used on document or window.
 */
jQuery.fn.outerWidth = function() {
	return this.get(0) == window || this.get(0) == document ?
		this.width() :
		this.get(0).offsetWidth;	
};

/**
 * Returns how many pixels the user has scrolled to the right (scrollLeft).
 * Works on containers with overflow: auto and window/document.
 */
jQuery.fn.scrollLeft = function() {
	if ( this.get(0) == window || this.get(0) == document )
		return self.pageXOffset ||
			jQuery.boxModel && document.documentElement.scrollLeft ||
			document.body.scrollLeft;
	
	return this.get(0).scrollLeft;
};

/**
 * Returns how many pixels the user has scrolled to the bottom (scrollTop).
 * Works on containers with overflow: auto and window/document.
 */
jQuery.fn.scrollTop = function() {
	if ( this.get(0) == window || this.get(0) == document )
		return self.pageYOffset ||
			jQuery.boxModel && document.documentElement.scrollTop ||
			document.body.scrollTop;

	return this.get(0).scrollTop;
};

/**
 * This returns an object with top, left, width, height, borderLeft,
 * borderTop, marginLeft, marginTop, scrollLeft, scrollTop, 
 * pageXOffset, pageYOffset.
 * @author Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
 */
jQuery.fn.offset = function(refElem) {
	if (!this[0]) throw 'jQuery.fn.offset requires an element.';
	
	refElem = (refElem) ? jQuery(refElem)[0] : null;
	var x = 0, y = 0, elm = this[0], parent = this[0], pos = null, borders = [0,0], isElm = true, sl = 0, st = 0;
	do {
		if (parent.tagName == 'BODY' || parent.tagName == 'HTML') {
			// Safari and IE don't add margin for static and relative
			if ((jQuery.browser.safari || jQuery.browser.msie) && pos != 'absolute') {
				x += parseInt(jQuery.css(parent, 'marginLeft')) || 0;
				y += parseInt(jQuery.css(parent, 'marginTop'))  || 0;
			}
			break;
		}
		
		pos    = jQuery.css(parent, 'position');
		border = [parseInt(jQuery.css(parent, 'borderLeftWidth')) || 0,
							parseInt(jQuery.css(parent, 'borderTopWidth'))  || 0];
		sl = parent.scrollLeft;
		st = parent.scrollTop;
		
		x += (parent.offsetLeft || 0) + border[0] - sl;
		y += (parent.offsetTop  || 0) + border[1] - st;
		
		// Safari and Opera include the border already for parents with position = absolute|relative
		if ((jQuery.browser.safari || jQuery.browser.opera) && !isElm && (pos == 'absolute' || pos == 'relative')) {
			x -= border[0];
			y -= border[1];
		}
		
		parent = parent.offsetParent;
		isElm  = false;
	} while(parent);
	
	if (refElem) {
		var offset = jQuery(refElem).offset();
		x  = x  - offset.left;
		y  = y  - offset.top;
		sl = sl - offset.scrollLeft;
		st = st - offset.scrollTop;
	}
	
	return {
		top:  y,
		left: x,
		width:  elm.offsetWidth,
		height: elm.offsetHeight,
		borderTop:  parseInt(jQuery.css(elm, 'borderTopWidth'))  || 0,
		borderLeft: parseInt(jQuery.css(elm, 'borderLeftWidth')) || 0,
		marginTop:  parseInt(jQuery.css(elm, 'marginTopWidth'))  || 0,
		marginLeft: parseInt(jQuery.css(elm, 'marginLeftWidth')) || 0,
		scrollTop:  st,
		scrollLeft: sl,
		pageYOffset: window.pageYOffset || document.documentElement.scrollTop  || document.body.scrollTop  || 0,
		pageXOffset: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0
	};
};

$.fn.pause = function(milli,type) {
	milli = milli || 1000;
	type = type || "fx";
	return this.queue(type,function(){
		var self = this;
		setTimeout(function(){
			$.dequeue(self);
		},milli);
	});
};

$.fn.clearQueue = $.fn.unpause = function(type) {
	return this.each(function(){
		type = type || "fx";
		if(this.queue && this.queue[type]) {
			this.queue[type].length = 0;
		}
	});
};


/**
 * This initialises the appointbar ready to handle all events and user action,
 * Validates user input
 * Displays Call back
 * Handles AJAX
 */
function initApptCallback(){
		
		// do stuff to handle UI input getting focus etc
		if (document.getElementById('thecallbackform')){		
		
		//clear name field when user puts focus on field
		document.getElementById('handle').onfocus = function()
			{
			if(this.value == "Enter full name of patient here"){this.value = "";}{this.style.background = "#fff";}{this.style.border = "1px solid #8dc5e8";}
			};
	
		//return value to default text if field loses focus and is still empty	
		document.getElementById('handle').onblur = function()
			{
			if(this.value == ""){this.value = "Enter full name of patient here";}{this.style.background = "#fff";}{this.style.border = "1px solid #8dc5e8";}
			};
		//clear email field when user puts focus on field
		document.getElementById('figures').onfocus = function()
			{
			if(this.value == "Enter contact telephone number here"){this.value = "";}{this.style.background = "#fff";}{this.style.border = "1px solid #8dc5e8";}
			};
	
		//return value to default text if field loses focus and is still empty	
		document.getElementById('figures').onblur = function()
			{
			if(this.value == ""){this.value = "Enter contact telephone number here";}{this.style.background = "#fff";}{this.style.border = "1px solid #8dc5e8";}
			};		

		}		
		
	 // doc-ready initialization: wire up form for ajax submitting
    $(function() {
        // #formpanel is the target element; data returned from a form submit will be
        // placed in the #formpanel div (to replace the form)
        
        
		// wire up form using the 'ajaxForm' method
        $('#thecallbackform').ajaxForm('#formpanel', after, before, false); // true == 'semantic' serialization
		
        // wire the 'Loading...' ajax indicator
        $('<div id="busy"><img src="/i/indicator_big.gif" alt="progress animation" /></div>')
            .ajaxStart(function() {$(this).show();})
			.ajaxStop(function() {$(this).hide();})
            .appendTo('#formpanel');
    });
    
    // pre-submit callback
    function before(formData) { 

		// formData is an array; use $.param to convert it to a string (form plugin does this
        // automatically when it submits the data)
        //alert('About to submit: \n' + $.param(formData)); 
        
        		var strhandle=document.getElementById('handle');
				var strfigures=document.getElementById('figures');
				var handlefilter=/^([a-zA-Z.\s']{1,50})$/;   		
    			var strippedfigures = strfigures.value.replace(/[\(\)\.\-\ ]/g, ''); 
				var testresults = true;
				if (!(handlefilter.test(strhandle.value))) {
				alert("There is a wee problem with your request - Please input your name, so we can check your file. This has to be just your first name and surname e.g. Laura Jones");
				strhandle.focus();
				strhandle.style.background = '#8dc5e8';
				strhandle.style.border = '3px solid #cc0000';
				testresults=false;
				return (testresults);
				}
				else if ((strhandle.value == "") || (strhandle.value == "Enter full name of patient here")) {
				alert("There is a wee problem with your request - Please input full name of patient here, so we can check their file");
				strhandle.focus();
				strhandle.style.background = '#8dc5e8';
				strhandle.style.border = '3px solid #cc0000';
				testresults=false;
				return (testresults);
				}
				else if (strfigures.value == "") {
       			alert("There is a wee problem with your request - Please enter you contact number so we can phone you back.");
				strfigures.focus();
				strfigures.style.background = '#8dc5e8';
				strfigures.style.border = '3px solid #cc0000';
				testresults=false; 
				return (testresults);
				} 
				else if (isNaN(parseInt(strippedfigures))) {
        		alert("There is a wee problem with your request - The phone number is not valid, please use numbers only not letters or special characters.");
				strfigures.focus();
				strfigures.style.background = '#8dc5e8';
				strfigures.style.border = '3px solid #cc0000';
				testresults=false;
				return (testresults);
				}
				else if (!(strippedfigures.length > 6)) {
        		alert("There is a wee problem with your request - The phone number is not a recognised format. Sorry about this, please bear with us. We do this check to help ensure you have entered you phone number correctly, so you can be sure we will call you back");
				strfigures.focus();
				strfigures.style.background = '#8dc5e8';
				strfigures.style.border = '3px solid #cc0000';
				testresults=false;
				return (testresults);
    			}
				
				// this could be a wee message but as we are validating input better not to use it here
				//$('#formpanel').html("we're checking your input please wait...");
				return true; // here I could return false to prevent the form from being submitted
				
				
    }
    
    // post-submit callback
    function after(responseText, statusText)  { 
        //alert('status: ' + statusText + 
            //'\n\nresponseText: \n' + 
            //responseText + '\n\nThe #formpanel div should have already been updated with the responseText.'); 
    }
}

/**
 * This initialises the appointbar to slide open and close,
 * Thanks jQuery you rock!
 */
  function prepareAppointmentCallback(){	  
	if ($("#callbackbutton a")) {
		//$("#callbackbutton a").attr({ href: "#" });	
		$("#callbackbutton a").click(function(){
		$("#appointmentbar").slideToggle("slow");
		//$("#appointmentbar").slideToggle("slow",function(){ alert("Animation Done."); });
		$("#callbackbutton a").toggleClass("close")	
	return false;
	});

}}
		