// JavaScript Document

// AJAX makeRequest

function makeRequest(locationURL, parameters, onComplete, doPost, dataPackage) {

    var http_request = false;
    try {
        http_request = new ActiveXObject("Msxml2.XMLHTTP");
    } catch (e1) {
        try {
            http_request= new ActiveXObject("Microsoft.XMLHTTP");
        } catch (e2) {
            http_request = new XMLHttpRequest();
        }
    }

    //if (http_request.overrideMimeType) { // optional
    //  http_request.overrideMimeType('text/xml');
    //}

    if (!http_request) {
      alert('Cannot create XMLHTTP instance');
      return false;
    }

    completeListener = function() {
        if (http_request.readyState == 4) {
            if (http_request.status == 200) {
                if (onComplete) onComplete(http_request, http_request ? http_request.responseText : null, dataPackage);
            }
        }
    };

    //var salt = hex_md5(new Date().toString());
    http_request.onreadystatechange = completeListener;
    if (doPost) {
		http_request.open('POST', locationURL, true);
		http_request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
		http_request.setRequestHeader("Content-length", parameters.length);
		http_request.setRequestHeader("Connection", "close");
		http_request.send(parameters);
    } else {
    	http_request.open('GET', locationURL + (parameters ? ("?" + parameters) : ""), true);
    	//http_request.open('GET', './proxy.php?' + parameters +
                    // "&salt=" + salt, true);
    	http_request.send(null);                        
    } 
   
}

/* Usage:
    
        projectionalReplace('%name% %lname%, %suffix%; Mr. %lname%',
            {
                'lname': 'Smith',
                'name': 'John',
                'suffix': 'Jr.',
            });
    
        => John Smith, Jr.; Mr. Smith
        
        projectionalReplace('{zip}; {city}, {country}; {street} {house}, {app}',
            {
                'zip': '12245',
                'country': 'England',
                'street': 'Baker Str.',
                'city': 'London',
                'house': '235b',
                'app': '16',
            }, '{', '}');
    
        => 12245; London, England; Baker Str. 235b, 16
        
        projectionalReplace('I'm /0/ now. I'm going to /1/ then',
            ['walking', 'run'], '/');
        =>  I'm walkin now. I'm going to run then.     

*/

function projectionalReplace(string, values, delimR) {
    var pStr = string;
    var delimL = delimL || '%';
    var delimR = delimR || delimL; 
    for (valueLabel in values) {
        var pattern = "\\" + delimL + valueLabel + "\\" + delimR;
        pStr = pStr.replace(new RegExp(pattern, "g"), values[valueLabel]);
    }
    return pStr;
}

/* URLEncode */ // TODO: encoding/decoding fails on cyrillyc characters, correct this

/*
function urlEncode(clearString) { // http://cass-hacks.com/articles/code/js_url_encode_decode/
  var output = '';
  var x = 0;
  clearString = clearString.toString();
  // var regex = /(^[a-zA-Z0-9_.]*)/;
  var regex = /(^[a-zA-Z0-9_]*)/;
  while (x < clearString.length) {
    var match = regex.exec(clearString.substr(x));
    if (match != null && match.length > 1 && match[1] != '') {
    	output += match[1];
      x += match[1].length;
    } else {
      if (clearString[x] == ' ')
        output += '+';
      else {
        var charCode = clearString.charCodeAt(x);
        var hexVal = charCode.toString(16);
        output += '%' + ( hexVal.length < 2 ? '0' : '' ) + hexVal.toUpperCase();
      }
      x++;
    }
  }
  return output;
} */

function urlEncode(encodeStr) {
    return encodeURI(encodeStr);
}

/*  OOP Support

	from: http://www.ajaxpath.com/javascript-inheritance,
	see also: http://ajaxpatterns.org/Javascript_Inheritance */

function Class() {

}

Class.prototype.construct = function() {

};

Class.extend = function(def) {
    var classDef = function() {
        if (arguments[0] !== Class) {
            this.construct.apply(this, arguments);
        }
    };

    var proto = new this(Class);
    var superClass = this.prototype;

    for (var n in def) {
        var item = def[n];
        if (item instanceof Function) item.$ = superClass; else classDef[n] = item;
        proto[n] = item;
    }

    classDef.prototype = proto;

    classDef.extend = this.extend;
    return classDef;
};

function createMethodReference(object, methodName) {
    return function () {
        return object[methodName].apply(object, arguments);
    };
};

function createMethodReference_(object, methodName, someData) {
    return function () {
        arguments[0] = someData;
        arguments[1] = arguments;
        return object[methodName].apply(object, arguments);
    };
};

function htmlentities( string ){
    // http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +    revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: nobbler
    // +    tweaked by: Jack
    // +   bugfixed by: Onno Marsman
    // %          note: table from http://www.the-art-of-web.com/html/character-codes/
    // *     example 1: htmlentities('Kevin & van Zonneveld');
    // *     returns 1: 'Kevin &amp; van Zonneveld'
 
    var histogram = {}, code = 0, tmp_arr = [], i = 0;
    var stringl = 0;
 
    histogram['34'] = 'quot';
    histogram['38'] = 'amp';
    histogram['60'] = 'lt';
    histogram['62'] = 'gt';
    histogram['160'] = 'nbsp';
    histogram['161'] = 'iexcl';
    histogram['162'] = 'cent';
    histogram['163'] = 'pound';
    histogram['164'] = 'curren';
    histogram['165'] = 'yen';
    histogram['166'] = 'brvbar';
    histogram['167'] = 'sect';
    histogram['168'] = 'uml';
    histogram['169'] = 'copy';
    histogram['170'] = 'ordf';
    histogram['171'] = 'laquo';
    histogram['172'] = 'not';
    histogram['173'] = 'shy';
    histogram['174'] = 'reg';
    histogram['175'] = 'macr';
    histogram['176'] = 'deg';
    histogram['177'] = 'plusmn';
    histogram['178'] = 'sup2';
    histogram['179'] = 'sup3';
    histogram['180'] = 'acute';
    histogram['181'] = 'micro';
    histogram['182'] = 'para';
    histogram['183'] = 'middot';
    histogram['184'] = 'cedil';
    histogram['185'] = 'sup1';
    histogram['186'] = 'ordm';
    histogram['187'] = 'raquo';
    histogram['188'] = 'frac14';
    histogram['189'] = 'frac12';
    histogram['190'] = 'frac34';
    histogram['191'] = 'iquest';
    histogram['192'] = 'Agrave';
    histogram['193'] = 'Aacute';
    histogram['194'] = 'Acirc';
    histogram['195'] = 'Atilde';
    histogram['196'] = 'Auml';
    histogram['197'] = 'Aring';
    histogram['198'] = 'AElig';
    histogram['199'] = 'Ccedil';
    histogram['200'] = 'Egrave';
    histogram['201'] = 'Eacute';
    histogram['202'] = 'Ecirc';
    histogram['203'] = 'Euml';
    histogram['204'] = 'Igrave';
    histogram['205'] = 'Iacute';
    histogram['206'] = 'Icirc';
    histogram['207'] = 'Iuml';
    histogram['208'] = 'ETH';
    histogram['209'] = 'Ntilde';
    histogram['210'] = 'Ograve';
    histogram['211'] = 'Oacute';
    histogram['212'] = 'Ocirc';
    histogram['213'] = 'Otilde';
    histogram['214'] = 'Ouml';
    histogram['215'] = 'times';
    histogram['216'] = 'Oslash';
    histogram['217'] = 'Ugrave';
    histogram['218'] = 'Uacute';
    histogram['219'] = 'Ucirc';
    histogram['220'] = 'Uuml';
    histogram['221'] = 'Yacute';
    histogram['222'] = 'THORN';
    histogram['223'] = 'szlig';
    histogram['224'] = 'agrave';
    histogram['225'] = 'aacute';
    histogram['226'] = 'acirc';
    histogram['227'] = 'atilde';
    histogram['228'] = 'auml';
    histogram['229'] = 'aring';
    histogram['230'] = 'aelig';
    histogram['231'] = 'ccedil';
    histogram['232'] = 'egrave';
    histogram['233'] = 'eacute';
    histogram['234'] = 'ecirc';
    histogram['235'] = 'euml';
    histogram['236'] = 'igrave';
    histogram['237'] = 'iacute';
    histogram['238'] = 'icirc';
    histogram['239'] = 'iuml';
    histogram['240'] = 'eth';
    histogram['241'] = 'ntilde';
    histogram['242'] = 'ograve';
    histogram['243'] = 'oacute';
    histogram['244'] = 'ocirc';
    histogram['245'] = 'otilde';
    histogram['246'] = 'ouml';
    histogram['247'] = 'divide';
    histogram['248'] = 'oslash';
    histogram['249'] = 'ugrave';
    histogram['250'] = 'uacute';
    histogram['251'] = 'ucirc';
    histogram['252'] = 'uuml';
    histogram['253'] = 'yacute';
    histogram['254'] = 'thorn';
    histogram['255'] = 'yuml';
 
    string += '';
    stringl = string.length
    for (i = 0; i < stringl; ++i) {
        code = string.charCodeAt(i);
        if (code in histogram) {
            tmp_arr[i] = '&'+histogram[code]+';';
        } else {
            tmp_arr[i] = string.charAt(i);
        }
    }
 
    return tmp_arr.join('');
}

var IS_IE = !!(window.attachEvent && !window.opera);

function div(numerator, denominator) {
    // http://www.augustana.ab.ca/~mohrj/courses/2000.fall/csc110/JavaScript/examples/integer_division.html
    var remainder = numerator % denominator;
    var quotient = ( numerator - remainder ) / denominator;
    if ( quotient >= 0 )
        quotient = Math.floor( quotient );
    else  // negative
        quotient = Math.ceil( quotient );
    return {q: quotient, r: remainder};
}

function div_(numerator, denominator) {
	if (numerator == 0) return 1;
    var quotient = numerator / denominator;
    if ( quotient >= 0 )
        quotient = Math.ceil( quotient );
    else  // negative
        quotient = Math.floor( quotient );
    return quotient;
}

function objPropsCount(obj) {
    var count = 0;
    for (k in obj) if (obj.hasOwnProperty(k)) count++;
    return count;
}

Number.prototype.NaN0=function(){return isNaN(this)?0:this;}

var inArray = function (array,value,caseSensitive)
// Returns true if the passed value is found in the
// array. Returns false if it is not.
{
    var i;
    for (i=0; i < array.length; i++) {
        // use === to check for Matches. ie., identical (===),
        if(caseSensitive){ //performs match even the string is case sensitive
            if (array[i].toLowerCase() == value.toLowerCase()) {
                return true;
            }
        } else {
            if (array[i] == value) {
                return true;
            }
        }
    }
    return false;
};

function findPos(e) {
	//var conPrefix = "";
	var baseEl = e;
	// var curleft = curtop = 0;
	var curleft = 0;
	var curtop = 0;
	if (e.offsetParent) {
		do {		
			curleft += e.offsetLeft;
			curtop += e.offsetTop;
			//console.log(conPrefix + (e.id ? e.id : e) + '>' + curleft + ':' + curtop);
			//conPrefix += "....";
		} while (e = e.offsetParent);
	}
	var docBody = document.documentElement ? document.documentElement : document.body;
	if (docBody) {
		curleft += (baseEl.currentStyle?(parseInt(baseEl.currentStyle.borderLeftWidth)).NaN0():0) +
				   (IS_IE ? (parseInt(docBody.scrollLeft)).NaN0() : 0) - (parseInt(docBody.clientLeft)).NaN0();
		curtop  += (baseEl.currentStyle?(parseInt(baseEl.currentStyle.borderTopWidth)).NaN0():0) +
				   (IS_IE ? (parseInt(docBody.scrollTop)).NaN0() : 0) - (parseInt(docBody.clientTop)).NaN0();
	}	
	//console.log(conPrefix + '>>>' + curleft + ':' + curtop); 
	return {x: curleft, y:curtop};
}

/* ------------ SYSTEM.JS -------- */


// JavaScript Document

// variables to store cached elements
var errOutput = null;
var infoOutput = null;
var infoClearTimeout = null;

/* filtering numbers for keydown */

function filterNumberis(e, elm) { // based on example from http://www.w3schools.com/jsref/jsref_onkeydown.asp
    var keynum = window.event ? e.keyCode : e.which; // ? IE : others
    if ((keynum < 19) || ((keynum > 34) && (keynum < 47))) return true; 
    return /\d/.test(String.fromCharCode(keynum));
}

/* Showing Info/Errors */

function showError(errStr) {    
    if (errOutput == null) errOutput = document.getElementById('errOutput');  
    if (errOutput) {
        errOutput.appendChild(document.createTextNode(errStr));
        errOutput.appendChild(document.createElement('BR'));
        errOutput.className = '';
    };
}

function showInfo(infoStr, delay) {    
    if (infoOutput == null) infoOutput = document.getElementById('infoOutput');
    infoOutput.innerHTML = '';  
    if (infoOutput) {
        infoOutput.appendChild(document.createTextNode(infoStr));
        if (infoClearTimeout) clearTimeout(infoClearTimeout);
        infoClearTimeout = setTimeout(function() { infoOutput.innerHTML = ''; }, delay || 5000)
    };
}

/* filtering numbers for keydown */

function filterNumbers(e, elm) { // based on example from http://www.w3schools.com/jsref/jsref_onkeydown.asp
    var keynum = window.event ? e.keyCode : e.which; // ? IE : others
    var e = e || window.event;    
    if ((keynum < 19) || ((keynum > 34) && (keynum < 47))) return true;
    if ((keynum == 190) && elm && (elm.value == '') && !evt.shiftKey) return true;  
    return /\d/.test(String.fromCharCode(keynum));
}

var email_re = /^[a-zA-Z][\w\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]$/;

function validateInput(inputElm, re) {
    // console.log('validating value: ', inputElm.value);
    var isValid = (inputElm.value == '') || re.test(inputElm.value);
    // console.log('re passed: ', isValid);     
    if (isValid) {
        if (inputElm.className.search(/\sinvalid/) > 0) inputElm.className = inputElm.className.replace(/\sinvalid/, '');
    } else {        
        if (inputElm.className.search(/\sinvalid/) == -1) inputElm.className += ' invalid';
    };
    
    // return isValid;
    return true;
}

function checkEmail(e, elm) {
    return validateInput(elm, email_re);    
}

function checkPwd(e, elm) {
    return validateInput(elm, /^[A-Za-z0-9]*$/);    
}

function checkCaptcha(e, elm) {
    return validateInput(elm, /^[A-Za-z]{6}$/);    
}

/* function validVal(event, keyRE) { // from http://www.overset.com/2006/12/01/simple-javascript-form-field-onkeydown-regular-expression-wrapper/    
    if ( ( typeof(event.keyCode) != 'undefined' && event.keyCode > 0 && String.fromCharCode(event.keyCode).search(keyRE) != (-1) ) ||
        ( typeof(event.charCode) != 'undefined' && event.charCode > 0 && String.fromCharCode(event.charCode).search(keyRE) != (-1) ) ||
        ( typeof(event.charCode) != 'undefined' && event.charCode != event.keyCode && typeof(event.keyCode) != 'undefined' && event.keyCode.toString().search(/^(8|9|13|45|46|35|36|37|39)$/) != (-1) ) ||
        ( typeof(event.charCode) != 'undefined' && event.charCode == event.keyCode && typeof(event.keyCode) != 'undefined' && event.keyCode.toString().search(/^(8|9|13)$/) != (-1) ) ) {
        return true;
    } else {
        return false;
    }
} */

/* function filterEmail(e, elm) { 
    var keynum = window.event ? e.keyCode : e.which; // ? IE : others
    if ((keynum < 19) || ((keynum > 34) && (keynum < 47))) return true; 
    // return /^[\.\-_A-Za-z0-9]+?@[\.\-A-Za-z0-9]+?[\.A-Za-z0-9]{2,}$/.test(elm.value + String.fromCharCode(keynum));
    return /^[.-@a-zA-Z0-9]*$/.test(elm.value + String.fromCharCode(keynum)); // TODO: check whole input value + keynum
} */

/* function filterPwd(e, elm) { 
    var keynum = window.event ? e.keyCode : e.which; // ? IE : others
    if ((keynum < 19) || ((keynum > 34) && (keynum < 47))) return true; 
    return /^[A-Za-z0-9]*$/.test(elm.value + String.fromCharCode(keynum)); // TODO: check whole input value + keynum
} */

/* function filterCaptcha(e, elm) { 
    var keynum = window.event ? e.keyCode : e.which; // ? IE : others
    if ((keynum < 19) || ((keynum > 34) && (keynum < 47))) return true; 
    return /[A-Za-z]/.test(String.fromCharCode(keynum)); // TODO: check whole input value + keynum
} */

/* ------------ / SYSTEM.JS -------- */

function clearContents(elm) {
    if (IS_IE) {
        var nElm = elm.cloneNode(false);
	    elm.parentNode.insertBefore(nElm,elm);
	    elm.parentNode.removeChild(elm);
	    return nElm;
    } else {
        elm.innerHTML = '';
        return elm;
    }
}

/* function replaceElm(elm1, elm2) {
    elm1.parentNode.insertBefore(elm2,elm1);
	elm1.parentNode.removeChild(elm1);
} */

/* Element Wrapper class to wrap any DOM element */

var ElementWrapper = Class.extend({

	construct: 
		function(elementId) {
			this.elementId = elementId;
			this.element = null;
			this._initializeElement();
		},
		
	_initializeElement: 
		function() {
		
			if (!document.getElementById(this.elementId)) {
				this.element = document.createElement('div');
				this.element.id = this.elementId;
				this._prepareElement();
			} else {
				this.element = document.getElementById(this.elementId);
			}
			
		},
		
	_prepareElement:
	   function() {
	       document.body.appendChild(this.element);
	   }

});


