/*
 * Copyright (c) 2009, embeddednode. All rights reserved.
 * Code licensed under the EPL License: http://www.eclipse.org/legal/epl-v10.html
 * version: 2.4
**/

/**
  * The <i>algorithm-javascript</i> module provides some functions for each of browser platforms in order to process data and fixed features.
  * @module algorithm-javascript
***/

/**
  * The <i>Math</i> class is a JavaScript object, which allows you to perform mathematical tasks.
  * @class Math
***/ 

/**
  * The <i>xor</i> method is used to do XOR operation 
  * @method xor
  * @for Math
  * @static
  * @param {Boolean} x is true or false
  * @param {Boolean} y is true or false
  * @return {Boolean} the value true if <i>x</i> and <i>y</i> are same, otherwise the value false
***/
Math.xor = function(x, y) {
	return !x != !y;
};


/**
  * The <i>Array</i> class is a JavaScript object, which is used to store multiple values in a single variable.
  * @class Array
***/ 

/**
  * The <i>max</i> method can find out maximum value in array.
  * @method max
  * @for Array
  * @return {String | Number} a maximum value in array 
***/ 
Array.prototype.max = function() {
	var tmp = this[0x00000000];  
	for(var i=0x00000001; i<this.length; i++)
    if(tmp.compare(this[i]) < 0x00000000)
		tmp = this[i];
	return tmp;
};

/**
  * The <i>min</i> method can find out minimum value in array.
  * @method min
  * @for Array
  * @return {String | Number} a minimum value in array 
***/ 
Array.prototype.min = function() {
	var tmp = this[0x00000000];  
	for(var i=0x00000001; i<this.length; i++)
		if(tmp.compare(this[i]) > 0x00000000)
		tmp = this[i];
	return tmp;
};

/**
  * The <i>swap</i> method can swaps the contents of two elements.
  * @method swap
  * @for Array
  * @param {Number} x is a position index of element
  * @param {Number} y is a position index of element
  * @return {void}
***/
Array.prototype.swap = function(x, y) {
	var temp = this[y];
	this[y]  = this[x];
	this[x]  = temp;
};

/**
  * The <i>shuffle</i> method can randomly permutes the specified list.
  * @method shuffle
  * @for Array
  * @return {void}
***/
Array.prototype.shuffle = function() {
	var i = this.length;
	while(--i>0x00000000)
		this.swap(i, Math.floor(Math.random()*i));
};

/**
  * The <i>quicksort</i> method is a implemented of the <i>Quicksort</i> algorithm.
  * @method quicksort
  * @for Array
  * @return {void}
***/
Array.prototype.quicksort = function() {
	var low        = arguments[0x00000000] == undefined ? 0x00000000  : arguments[0x00000000];
	var high       = arguments[0x00000001] == undefined ? this.length : arguments[0x00000001];
	var partition  = function(low, high) {
		var pivotpoint = low;
		for(var i = low+0x00000001; i<=high && this[i] != undefined; i++) {
			if(this[i] < this[low])
				this.swap(i, ++pivotpoint);
		}
		this.swap(low, pivotpoint);
		return pivotpoint;
	};
	
	if(high > low) {
		pivotpoint = partition.call(this, low, high);
		this.quicksort(low, pivotpoint+~0x00000000);
		this.quicksort(pivotpoint+0x00000001, high);
	}
};

/**
  * The <i>binarySearch</i> method is a implemented of the <i>Binary Search</i> algorithm.
  * @method binarySearch
  * @for Array
  * @param {String | Number} key the value to be searched for
  * @return {Number} a sorted position index of element if it's contained in the array, otherwise -1
***/
Array.prototype.binarySearch = function(key) {
	var low  = arguments[0x00000001] == undefined ? 0x00000000  : arguments[0x00000001];
	var high = arguments[0x00000002] == undefined ? this.length : arguments[0x00000002];
	if(high >= low) {
		var mid = Math.floor((low + high) >> 0x00000001);
		if(this[mid] == key)
			return mid;
		else if(this[mid] > key)
			high = mid + ~0x00000000;
		else
			low  = mid + 0x00000001;
		return this.binarySearch(key, low, high); 
	}
	return ~0x00000000;
};

/**
  * The <i>item</i> method is appended with browsers of unimplemented that.
  * @method item
  * @for Array
  * @param {Number} index a position index of element
  * @return {Any} a object of specified type
***/
if(!Array.item)
	Array.prototype.item = function(index) {
		return this[index];
	};

/**
  * The <i>String</i> class is a JavaScript object, which is used to manipulate a stored piece of text.
  * @class String
***/

/**
  * The <i>compare</i> method can compare another <i>String</i> object per the <i>Unicode</i> of the character at a specified position.
  * @method compare
  * @for String
  * @param {String} another a specified text
  * @return {Number} the value 0 if itself is equals than another; the value 1 if itself is great than another; otherwise, the value -1
***/
String.prototype.compare = function(another) {
	if(this > another)
		return 0x00000001;
	else if(this == another)
		return 0x00000000;
	return ~0x00000000;
};

/**
  * The <i>byteLength</i> method is used to count length of bytes each of chars.
  * @method byteLength
  * @for String
  * @return {Number} a count of bytes
***/
String.prototype.byteLength = function() {
	 var result = this.length;
	 var tmp;
	 for(var i=0x00000000; i<this.length; i++) {
	 	 tmp = this.charCodeAt(i);
		 if(tmp > 0x00FFFFFF)
		 	result += 0x00000003;
		 else if(tmp > 0x0000FFFF)
		 	result += 0x00000002;
		 else if(tmp > 0x000000FF)
		 	result++;
	 }
	 return result;
};

/**
  * The <i>byteSlice </i> method is used to extract a part of a string and returns the extracted part in a new string per bytes of each of chars.
  * @method byteSlice
  * @for String
  * @param {Number} start a start point to be extracted for
  * @param {Number} end a end point to be extracted for
  * @return {String} a extracted part of the text
***/
String.prototype.byteSlice = function(start, end) {
	if(end == 0x00000000) return '';
  
	var offset = function(index) {
		var tmp;
		var i = 0x00000000;
		while(i<this.length & index > ~0x00000000) {
			tmp  = this.charCodeAt(i++);
			if(tmp > 0x00FFFFFF)
				index -= 0x00000004;
			else if(tmp > 0x0000FFFF)
				index -= 0x00000003;
			else if(tmp > 0x000000FF)
				index -= 0x00000002;
			else index--;
		}
		return index > ~0x00000000 ? i : i + ~0x00000000;
  	};
  	
	return end ? this.slice(offset.call(this, start), offset.call(this, end)) : this.slice(offset.call(this, start));
};

/**
  * The <i>trim</i> method can erase chars of this text bound within less then 33 <i>ASCII</i> code.
  * @method trim
  * @for String
  * @return {String} a erased text
***/
String.prototype.trim = function() {
	var begin = ~0x00000000, end = this.length;
	while(this.charCodeAt(++begin) < 0x00000021);
	while(this.charCodeAt(--end)   < 0x00000021);
	return this.slice(begin, end + 0x00000001);
};

/**
  * The <i>isInteger</i> method is used to valid the text whether match integer style.
  * @method isInteger
  * @for String
  * @return {Boolean} the value true if this text is mathced, otherwise the value false
***/
String.prototype.isInteger = function() {
	return new RegExp(/^-?\d+$/g).test(this);
};

/**
  * The <i>isDecimal</i> method is used to valid the text whether match decimal style.
  * @method isDecimal
  * @for String
  * @return {Boolean} the value true if this text is mathced, otherwise the value false
***/
String.prototype.isDecimal = function() {
	return new RegExp(/^-?\d+\.\d+$/g).test(this);
};

/**
  * The <i>isNumber</i> method is used to valid the text whether match number style.
  * @method isNumber
  * @for String
  * @return {Boolean} the value true if this text is mathced, otherwise the value false
***/
String.prototype.isNumber = function() {
	return new RegExp(/^-?\d+(\.\d+)?$/g).test(this);
};

/**
  * The <i>isPositiveInteger</i> method is used to valid the text whether match positive integer style.
  * @method isPositiveInteger
  * @for String
  * @return {Boolean} the value true if this text is mathced, otherwise the value false
***/
String.prototype.isPositiveInteger = function() {
	return new RegExp(/^\d+$/g).test(this);
};

/**
  * The <i>isPositiveDecimal</i> method is used to valid the text whether match positive decimal style.
  * @method isPositiveDecimal
  * @for String
  * @return {Boolean} the value true if this text is mathced, otherwise the value false
***/
String.prototype.isPositiveDecimal = function() {
	return new RegExp(/^\d+\.\d+$/g).test(this);
};

/**
  * The <i>isPositiveNumber</i> method is used to valid the text whether match positive number style.
  * @method isPositiveNumber
  * @for String
  * @return {Boolean} the value true if this text is mathced, otherwise the value false
***/
String.prototype.isPositiveNumber = function() {
	return new RegExp(/^\d+(\.\d+)?$/g).test(this);
};

/**
  * The <i>isNegativeInteger</i> method is used to valid the text whether match negative integer style.
  * @method isNegativeInteger
  * @for String
  * @return {Boolean} the value true if this text is mathced, otherwise the value false
***/
String.prototype.isNegativeInteger = function() {
	return new RegExp(/^-\d+$/g).test(this);
};

/**
  * The <i>isNegativeDecimal</i> method is used to valid the text whether match negative decimal style.
  * @method isNegativeDecimal
  * @for String
  * @return {Boolean} the value true if this text is mathced, otherwise the value false
***/
String.prototype.isNegativeDecimal = function() {
	return new RegExp(/^-\d+\.\d+$/g).test(this);
};

/**
  * The <i>isNegativeNumber</i> method is used to valid the text whether match negative number style.
  * @method isNegativeNumber
  * @for String
  * @return {Boolean} the value true if this text is mathced, otherwise the value false
***/
String.prototype.isNegativeNumber = function() {
	return new RegExp(/^-\d+(\.\d+)?$/g).test(this);
};

/**
  * The <i>Navigator</i> class is a DOM object, which is automatically created by the JavaScript runtime engine and contains information about the client browser.
  * @class Navigator
***/

/**
  * The <i>isInternetExplorer</i> property is used to know browsers whether the <i>Internet Explorer</i>.
  * @property isInternetExplorer
  * @for Navigator
  * @static
  * @type {Boolean}
***/
navigator.isInternetExplorer = (function() {
  return new RegExp(/MSIE/).test(navigator.userAgent);
})();

/**
  * The <i>isFirefox</i> property is used to know browsers whether the <i>Firefox</i>.
  * @property isFirefox
  * @for Navigator
  * @static
  * @type {Boolean}
***/
navigator.isFirefox = (function() {
  return new RegExp(/Firefox/).test(navigator.userAgent);
})();

/**
  * The <i>isOpera</i> property is used to know browsers whether the <i>Opera</i>.
  * @property isOpera
  * @for Navigator
  * @static
  * @type {Boolean}
***/
navigator.isOpera = (function() {
    return new RegExp(/Opera/).test(navigator.userAgent);
})();

/**
  * The <i>isChrome</i> property is used to know browsers whether the <i>Chrome</i>.
  * @property isChrome
  * @for Navigator
  * @static
  * @type {Boolean}
***/
navigator.isChrome = (function() {
    return new RegExp(/Chrome/).test(navigator.userAgent);
})();

/**
  * The <i>isSafari</i> property is used to know browsers whether the <i>Safari</i>.
  * @property isSafari
  * @for Navigator
  * @static
  * @type {Boolean}
***/
navigator.isSafari = (function() {
	return Math.xor(navigator.isChrome, new RegExp(/Safari/).test(navigator.userAgent));
})();

/**
  * The <i>version</i> property is used to know browsers whether version code.
  * @property version
  * @for Navigator
  * @static
  * @type {String | Number} the value -1 if found not out
***/
navigator.version = (function() {
	var version = (version = navigator.userAgent.match(new RegExp(/MSIE\s([\d\.]+)/)))    ? version[0x1] : 
    	     	  (version = navigator.userAgent.match(new RegExp(/Firefox\/([\d\.]+)/))) ? version[0x1] : 
         		  (version = navigator.userAgent.match(new RegExp(/Opera\/([\d\.]+)/)))   ? version[0x1] :
         		  (version = navigator.userAgent.match(new RegExp(/Chrome\/([\d\.]+)/)))  ? version[0x1] :
         		  (version = navigator.userAgent.match(new RegExp(/([\d\.]+)\sSafari/)))  ? version[0x1] : ~0x00000000;
	return version; 
})();

/**
  * The <i>Window</i> is a DOM object which is the top level object in the JavaScript hierarchy.
  * @class Window
***/


/**
  * The <i>attachEvent</i> method is appended with browsers of unimplemented that.
  * @method attachEvent
  * @for Window
  * @param {String} event a specified event type
  * @param {Function} handler a specified function point
  * @param {Boolean} userCapture true is capture and false is bubbing if the borswer has support this feature
  * @return {void}
***/
if(!window.attachEvent)
	window.attachEvent = function(event, handler) {
		window.addEventListener(event.slice(0x00000002), handler, arguments[0x00000002]);
	};

/**
  * The <i>detachEvent</i> method is appended with browsers of unimplemented that.
  * @method detachEvent
  * @for Window
  * @param {String} event a specified event type
  * @param {Function} handler a specified function point
  * @return {void}
***/
if(!window.detachEvent)
	window.detachEvent = function(event, handler) {
		window.removeEventListener(event.slice(0x00000002), handler, arguments[0x00000002]);
	};

/**
  * The Document is a DOM object, which represents the entire HTML document and can be used to access all elements in a page.
  * @class Document
***/

/**
  * The getElementsByName method is overwrited on the <i>Internet Explorer</i> in order to get able outside elements of the <i>&lt;form&gt;</i> element.
  * @method getElementsByName
  * @for Document
  * @param {String} name a specified name
  * @return {Array} a collection of objects if the name is matched each of elements in <i>&lt;body&gt;</i> element; otherwise, the value is empty
***/
if(navigator.isInternetExplorer) {
	
	document.getElementsByName = function(input) {
 		var node   = arguments[0x00000001] == undefined ? document.body.childNodes : arguments[0x00000001].childNodes; 
		var result = arguments[0x00000002] == undefined ? [] : arguments[0x00000002];
		for(var i=0x00000000; i<node.length; i++) {
			if(node[i].nodeType == 0x00000003 || node[i].nodeType == 0x00000008) continue;
			if(node[i].getAttribute('name') == input) result.push(node[i]);
			if(node[i].hasChildNodes()) this.getElementsByName(input, node[i], result);
		}
		return result;
	};
}

/**
  * The <i>loadXML</i> method is appended with browsers of unimplemented that.
  * @method loadXML
  * @for Document
  * @param {String} text a XML document
  * @return {void}
***/

/**
  * The <i>selectNodes</i> method is appended with browsers of unimplemented that.
  * @method selectNodes
  * @for Document
  * @param {String} xpath a XPath expression
  * @return {Array}
***/

/**
  * The <i>selectSingleNode</i> method is appended with browsers of unimplemented that.
  * @method selectSingleNode
  * @for Document
  * @param {String} xpath a XPath expression
  * @return {Node}
***/


/**
  * The <i>Element</i> class is a DOM object, which allows you to access any element within a form generically.
  * @class Element
***/

/**
  * The <i>selectNodes</i> method is appended with browsers of unimplemented that.
  * @method selectNodes
  * @for Element
  * @param {String} xpath a XPath expression
  * @return {Array}
***/

/**
  * The <i>selectSingleNode</i> method is appended with browsers of unimplemented that.
  * @method selectSingleNode
  * @for Element
  * @param {String} xpath a XPath expression
  * @return {Node}
***/

if(document.implementation) {

	if(document.implementation.createDocument)
		Document.prototype.loadXML = function(text) {
			while(this.firstChild) this.removeChild(this.firstChild);
			this.appendChild(this.importNode(new DOMParser().parseFromString(text, "text/xml").documentElement, true));
		};
		
	if(document.implementation.hasFeature("XPath", "3.0")) {
		
		Document.prototype.selectNodes = function(xpath) {
		    var xis = this.evaluate(xpath, 
		    						this,
		    						this.createNSResolver(this.documentElement), 
		    						XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
		    						null);
		    var result = [];
		    for(var i=0x00000000; i<xis.snapshotLength; i++)
		        result[i] =  xis.snapshotItem(i);
		    return result;
		};
		
		Document.prototype.selectSingleNode = function(xpath) {
		    var xis = this.evaluate(xpath, 
		    						this,
		    						this.createNSResolver(this.documentElement), 
		    						XPathResult.FIRST_ORDERED_NODE_TYPE,
		    						null);
			return xis.singleNodeValue;
		};
		
		Element.prototype.selectNodes = function(xpath) {
			var xis = this.ownerDocument.evaluate(xpath, 
		    									  this,
		    									  this.ownerDocument.createNSResolver(this.ownerDocument.documentElement), 
		    									  XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
		    									  null);
		    var result = [];
		    for(var i=0x00000000; i<xis.snapshotLength; i++)
		        result[i] =  xis.snapshotItem(i);
		    return result;
		};
		
		Element.prototype.selectSingleNode = function(xpath) {
			var xis = this.ownerDocument.evaluate(xpath, 
		    									  this,
		    									  this.ownerDocument.createNSResolver(this.ownerDocument.documentElement), 
												  XPathResult.FIRST_ORDERED_NODE_TYPE,
												  null);
			return xis.singleNodeValue;
		};
	}
}

/**
  * The <i>Macro</i> class isn't really a custom object, it seem like the macro conception of the <i>C++</i> in order to fixed some feature in each of browser plaforms.
  * @class Macro
***/

/**
  * The <i>Form</i> property represent handler of the <i>&lt;form&gt;</i> element.
  * @property Form
  * @for Macro
  * @final
  * @static
  * @type {Macro.Form}
***/

/**
  * The <i>Macro.Form</i> class is inlined in <i>Macro</i> class.
  * @constructor
  * @class Macro.Form
***/

/**
  * The <i>init</i> method is included this module after to automatic call back, in order to fixed behaviour of the <i>&lt;form&gt;</i> element of the <i>Firefox</i> that only work on exist the <i>submit</i> type of the <i>&lt;Input&gt;</i> element.
  * @method init
  * @return {void}
***/
(function() {
	
	var Form = (function() {
		var init = function() {
			var element;
			var hasSubmit;
		    for(var i=0x00000000; i<document.forms.length; i++) {
		   		hasSubmit = false;
				for(var j=0x00000000; j<document.forms[i].childNodes.length; j++)
					if(!(document.forms[i].childNodes[j].nodeType == 0x00000003 || document.forms[i].childNodes[j].nodeType == 0x00000008) && document.forms[i].childNodes[j].getAttribute('type') == 'submit') {
						hasSubmit = true;
						break;
					}
				if(hasSubmit) continue;
				element = document.createElement('input');
				element.setAttribute('type', 'submit');
				element.style.display = 'none';
		        document.forms[i].appendChild(element);
		    }
		};
		return {'init' : init}; 
	})();
	window.attachEvent('onload', Form.init);
})();

