/*
	Author: Dan McKinnon (dan@danmckinnon.net)
	Creation Date: January 12th, 2009
	Description: Main JavaScript entry point for Planes Project.
		
*/
//
//	DanMcKinnon.net - CORE 'Ajax' API 
//	

// essential global JSON object
if (!this.JSON) { JSON = {}; }(function () {

    function f(n) {
        // Format integers to have at least two digits.
        return n < 10 ? '0' + n : n;
    }

    if (typeof Date.prototype.toJSON !== 'function') {

        Date.prototype.toJSON = function (key) {

            return this.getUTCFullYear()   + '-' +
                 f(this.getUTCMonth() + 1) + '-' +
                 f(this.getUTCDate())      + 'T' +
                 f(this.getUTCHours())     + ':' +
                 f(this.getUTCMinutes())   + ':' +
                 f(this.getUTCSeconds())   + 'Z';
        };

        String.prototype.toJSON =
        Number.prototype.toJSON =
        Boolean.prototype.toJSON = function (key) {
            return this.valueOf();
        };
    }

    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        escapeable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        gap,
        indent,
        meta = {    // table of character substitutions
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"' : '\\"',
            '\\': '\\\\'
        },
        rep;


    function quote(string) {

// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.

        escapeable.lastIndex = 0;
        return escapeable.test(string) ?
            '"' + string.replace(escapeable, function (a) {
                var c = meta[a];
                if (typeof c === 'string') {
                    return c;
                }
                return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
            }) + '"' :
            '"' + string + '"';
    }


    function str(key, holder) {

// Produce a string from holder[key].

        var i,          // The loop counter.
            k,          // The member key.
            v,          // The member value.
            length,
            mind = gap,
            partial,
            value = holder[key];

// If the value has a toJSON method, call it to obtain a replacement value.

        if (value && typeof value === 'object' &&
                typeof value.toJSON === 'function') {
            value = value.toJSON(key);
        }

// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.

        if (typeof rep === 'function') {
            value = rep.call(holder, key, value);
        }

// What happens next depends on the value's type.

        switch (typeof value) {
        case 'string':
            return quote(value);

        case 'number':

// JSON numbers must be finite. Encode non-finite numbers as null.

            return isFinite(value) ? String(value) : 'null';

        case 'boolean':
        case 'null':

// If the value is a boolean or null, convert it to a string. Note:
// typeof null does not produce 'null'. The case is included here in
// the remote chance that this gets fixed someday.

            return String(value);

// If the type is 'object', we might be dealing with an object or an array or
// null.

        case 'object':

// Due to a specification blunder in ECMAScript, typeof null is 'object',
// so watch out for that case.

            if (!value) {
                return 'null';
            }

// Make an array to hold the partial results of stringifying this object value.

            gap += indent;
            partial = [];

// If the object has a dontEnum length property, we'll treat it as an array.

            if (typeof value.length === 'number' &&
                    !value.propertyIsEnumerable('length')) {

// The object is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.

                length = value.length;
                for (i = 0; i < length; i += 1) {
                    partial[i] = str(i, value) || 'null';
                }

// Join all of the elements together, separated with commas, and wrap them in
// brackets.

                v = partial.length === 0 ? '[]' :
                    gap ? '[\n' + gap +
                            partial.join(',\n' + gap) + '\n' +
                                mind + ']' :
                          '[' + partial.join(',') + ']';
                gap = mind;
                return v;
            }

// If the replacer is an array, use it to select the members to be stringified.

            if (rep && typeof rep === 'object') {
                length = rep.length;
                for (i = 0; i < length; i += 1) {
                    k = rep[i];
                    if (typeof k === 'string') {
                        v = str(k, value);
                        if (v) {
                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
                        }
                    }
                }
            } else {

// Otherwise, iterate through all of the keys in the object.

                for (k in value) {
                    if (Object.hasOwnProperty.call(value, k)) {
                        v = str(k, value);
                        if (v) {
                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
                        }
                    }
                }
            }

// Join all of the member texts together, separated with commas,
// and wrap them in braces.

            v = partial.length === 0 ? '{}' :
                gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
                        mind + '}' : '{' + partial.join(',') + '}';
            gap = mind;
            return v;
        }
    }

// If the JSON object does not yet have a stringify method, give it one.

    if (typeof JSON.stringify !== 'function') {
        JSON.stringify = function (value, replacer, space) {

// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a JSON text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.

            var i;
            gap = '';
            indent = '';

// If the space parameter is a number, make an indent string containing that
// many spaces.

            if (typeof space === 'number') {
                for (i = 0; i < space; i += 1) {
                    indent += ' ';
                }

// If the space parameter is a string, it will be used as the indent string.

            } else if (typeof space === 'string') {
                indent = space;
            }

// If there is a replacer, it must be a function or an array.
// Otherwise, throw an error.

            rep = replacer;
            if (replacer && typeof replacer !== 'function' &&
                    (typeof replacer !== 'object' ||
                     typeof replacer.length !== 'number')) {
                throw new Error('JSON.stringify');
            }

// Make a fake root object containing our value under the key of ''.
// Return the result of stringifying the value.

            return str('', {'': value});
        };
    }


// If the JSON object does not yet have a parse method, give it one.

    if (typeof JSON.parse !== 'function') {
        JSON.parse = function (text, reviver) {

// The parse method takes a text and an optional reviver function, and returns
// a JavaScript value if the text is a valid JSON text.

            var j;

            function walk(holder, key) {

// The walk method is used to recursively walk the resulting structure so
// that modifications can be made.

                var k, v, value = holder[key];
                if (value && typeof value === 'object') {
                    for (k in value) {
                        if (Object.hasOwnProperty.call(value, k)) {
                            v = walk(value, k);
                            if (v !== undefined) {
                                value[k] = v;
                            } else {
                                delete value[k];
                            }
                        }
                    }
                }
                return reviver.call(holder, key, value);
            }


// Parsing happens in four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.

            cx.lastIndex = 0;
            if (cx.test(text)) {
                text = text.replace(cx, function (a) {
                    return '\\u' +
                        ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
                });
            }

// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with '()' and 'new'
// because they can cause invocation, and '=' because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.

// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.

            if (/^[\],:{}\s]*$/.
test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {

// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.

                j = eval('(' + text + ')');

// In the optional fourth stage, we recursively walk the new structure, passing
// each name/value pair to a reviver function for possible transformation.

                return typeof reviver === 'function' ?
                    walk({'': j}, '') : j;
            }

// If the text is not JSON parseable, then a SyntaxError is thrown.

            throw new SyntaxError('JSON.parse');
        };
    }
})();



//json_encode( obj )
// 		Serializes an object.  
//		In other words converts an object into a 'json' string.
//
//		Arguments:
//			obj					- the object to encode
//		Returns:
//			The encoded string.

function json_encode( obj ){
	return JSON.stringify(obj);
}

//json_decode( string )
//		Deserializes a string
//		In other words converts a 'json' string into an object
//
//		Arguments:
//			string				- the string you want to decode
//		Returns:
//			The decoded object
//
//
function json_decode( str ){
	return JSON.parse(str);
}

//get_http( uri, [done_function], [receive_function], [waiting_function], [done_function] )
//		Sends a GET command to an HTTP server
//		Arguments:
//			uri 				- the page you are requesting
//			done_function 		- function run when a response is caught
//			receiving_function	- function run when receiving a response
//			waiting_function	- function run when waiting to receive a response
//			sending_function	- function run when sending the request
//		Returns:
//			a copy of the raw xmlHttpRequest object
//
function get_http( uri, done_function, receiving_function, waiting_function, sending_function ){
	var request = false;
	/*@cc_on @*/
	/*@if (@_jscript_version >= 5)
	// JScript gives us Conditional compilation, we can cope with old IE versions.
	// and security blocked creation of the objects.
	 try {
	  request = new ActiveXObject("Msxml2.XMLHTTP");
	 } catch (exception1) {
	  try {
	   request = new ActiveXObject("Microsoft.XMLHTTP");
	  } catch (exception2) {
	   request = false;
	  }
	 }
	@end @*/
	if ( typeof XMLHttpRequest!=='undefined') {
		try {
			request = new XMLHttpRequest();
		} catch (exception3) {
			request=false;
		}
	}
	if (window.createRequest) {
		try {
			request = window.createRequest();
		} catch (exception4) {
			request=false;
		}
	}
	request.open("GET", uri ,true);
	request.onreadystatechange = function(){
			switch ( request.readyState ){
				case 1:
					if (typeof sending_function === 'function'){
						sending_function();
					}
				break;
				case 2:
					if (typeof waiting_function === 'function'){
						waiting_function();
					}
				break;
				case 3:
					if (typeof receiving_function === 'function'){
						receiving_function();
					}
				break;
				case 4:
					if (typeof done_function === 'function'){
						done_function( request.responseText );
					}
				break;
			}
	};
	
	request.send(null);	
	return request;
}




//post_http( uri, [done_function], [receive_function], [waiting_function], [done_function] )
//		Sends a POST command to an HTTP server, posting variables
//		in JSON format.
//
//		Arguments:
//			uri 				- the page you are requesting
//			object				- an object to send to the server
//			done_function 		- function run when a response is caught
//			receiving_function	- function run when receiving a response
//			waiting_function	- function run when waiting to receive a response
//			sending_function	- function run when sending the request
//		Returns:
//			a copy of the raw xmlHttpRequest object
//
function post_http( uri, object, done_function, receiving_function, waiting_function, sending_function ){
	var params = "";
	if(typeof object==='object')
	params="&data=" + encodeURIComponent(json_encode(object));
	else
	params=object;
	var request = false;
	/*@cc_on @*/
	/*@if (@_jscript_version >= 5)
	// JScript gives us Conditional compilation, we can cope with old IE versions.
	// and security blocked creation of the objects.
	 try {
	  request = new ActiveXObject("Msxml2.XMLHTTP");
	 } catch (exception1) {
	  try {
	   request = new ActiveXObject("Microsoft.XMLHTTP");
	  } catch (exception2) {
	   request = false;
	  }
	 }
	@end @*/
	if (typeof XMLHttpRequest!=='undefined') {
		try {
			request = new XMLHttpRequest();
		} catch (exception3) {
			request=false;
		}
	}
	if (window.createRequest) {
		try {
			request = window.createRequest();
		} catch (exception4) {
			request=false;
		}
	}
	request.open("POST", uri ,true);
	request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	request.setRequestHeader("Content-length", params.length);
	request.setRequestHeader("Connection", "close");
	request.onreadystatechange = function(){
			switch ( request.readyState ){
				case 1:
					if (typeof sending_function === 'function'){
						sending_function();
					}
				break;
				case 2:
					if (typeof waiting_function === 'function'){
						waiting_function();
					}
				break;
				case 3:
					if (typeof receiving_function === 'function'){
						receiving_function();
					}
				break;
				case 4:
					if (typeof done_function === 'function'){
						done_function( request.responseText );
					}
				break;
			}
	};
	request.send(params);
	return request;
}

//include( script )
//		Runs an external javascript
//
//		Arguments:
//			script - a script file
//		Returns:
//			none
function include( script_file ){
	get_http(script_file,function(text){
		eval(text);
	}
	);
}


//element( id )
//		synonym for document.getElementById(id)
//
//		Arguments:
//			id - an object id from the DOM
//		Returns:
//			The DOM element Javascript object.
//
function element( id ){
	return document.getElementById(id);
}


//load_element( id, xhtml, script )
//		Loads an element from an external XHTML file
//		displaying it's status along the way
//		
//		Arguments:
//			id - the object id for the DOM element that you want to replace
//			xhtml - an .xhtml file to replace the DOM object
//			script - a .js file to run when finished loading the element.
//		Returns:
//			Nothing
//
function load_element( id, xhtml, script ){
	if ( xhtml.length > 0 ){
		
		get_http(xhtml, 
			//done
			function(text){
				element(id).innerHTML = text;
				
				if (script.length > 0 ){
					include(script);
				}
			},
			//receiving
			function(){
				element(id).innerHTML = "<div class=\"loading\">Receiving...</div>";
			},
			//waiting
			function(){
				element(id).innerHTML = "<div class=\"loading\">Waiting...</div>";
			},
			//sending
			function(){
				element(id).innerHTML = "<div class=\"loading\">Sending...</div>";
			}
		);
	}
}




//set_select_box( id, value )
//		Sets a select box's selection to a specific value based
//		on it's value.
//
//		Arguments:
//			id - the select boxes DOM id.
//			value - the value you wish to switch it to
//		Returns:
//			Nothing
//

function set_select_box( id, value){
	var e = element(id);
	for ( i in e.options ){
		if ( e.options[i].value === value ){
			e.selectedIndex = i;
		}
	}
}
//validate_email(email_address)
//		Checks if an email address is valid or not
//
//		Arguments:
//			email_address - the email address to validate
//		Returns:
//			True if the email address is valid
//			False if the email address is invalid.
//
function validate_email_address(email_address) {
	var at="@";
	var dot=".";
	var lat=email_address.indexOf(at);
	var lemail_address=email_address.length;
	
	if (email_address.indexOf(at) === -1){
	   return false;
	}

	if (email_address.indexOf(at) === -1 || email_address.indexOf(at) === 0 || email_address.indexOf(at) === lemail_address){
	   return false;
	}

	if (email_address.indexOf(dot) === -1 || email_address.indexOf(dot) === 0 || email_address.indexOf(dot) === lemail_address){
		return false;
	}

	 if (email_address.indexOf(at,(lat+1)) !== -1){
		return false;
	 }



	 if (email_address.indexOf(dot,(lat+2)) === -1){
		return false;
	 }
	
	 if (email_address.indexOf(" ") !== -1){
		return false;
	 }

	 return true;				
}

/*
	Project: Clockie v2.0
	Author: Dan McKinnon (dan@danmckinnon.net)
	Creation Date: December 31st, 2008
	Description:
		Main javascript entry point for DanMcKinnon.net - Advanced Clock
*/

//
//	DanMcKinnon.net - CORE 'Ajax' API 
//	
