/**
 * Common JavaScript library.
 *
 * @author     Svec Jiri <jiri.svec@livesport.cz>
 * @copyright  (c) 2008 LiveSport, s.r.o. 2008 <http://www.livesport.eu/>
 * @version    1.1.1  (2008-11-19)
 */

/**
 * Common JavaScript library.
 *
 * @constructor
 */
cJsLib = function()
{
    // initialization of object
    this._init();
};

/**
 * Get DOM object of requested element if exists.
 *
 * @param  {String} element   ID of requested element.
 * @return {Mixed}   Returns the DOM object if element exists, otherwise returns null.
 */  
cJsLib.prototype.getElement = function(element)
{
    if (!this.empty(element)) {
        var obj = document.getElementById(element);
        
        return (this.isObject(obj) ? obj : null);
    }
    
    return null;
};

/**
 * Alias for getting DOM object of element.
 *
 * @param  {String} element   ID of requested element.
 * @return {Mixed}   Returns the DOM object if element exists, otherwise returns null. 
 */
cJsLib.prototype.$ = function(element)
{
    return this.getElement(element);
};

/**
 * Get element by defined rule.
 * 
 * <b>Example:</b>
 * <code>
 * # get one element indetified by ID
 * var obj = cJsLib.$$('#search');
 * 
 * # get all inputs
 * var obj = cJsLib.$$('input');
 * 
 * # get all inputs with CSS class `text'
 * var obj = cJsLib.$$('input.text'); 
 * </code>
 *  
 * @param  {String} rule   Rule for getting elements.
 * @return {null|Array}   Returns NULL when no element exists, otherwise returns array of DOM elements.
 */
cJsLib.prototype.$$ = function(rule)
{
    var obj = null;
    
    if (! this.empty(rule)) {
        if (rule.indexOf('#') != -1) {
            obj = this.$(rule.slice(1));
            
            if (! this.isNull(obj) && this.isObject(obj)) {
                return new Array(obj);
            }
        } else if (rule.indexOf('.') != -1) {
            var tmp = rule.split('.');
            
            if (tmp.length >= 1) {
                var elem = this.empty(tmp[0]) ? null : tmp[0];
                var cls  = this.empty(tmp[1]) ? null : tmp[1];
                obj      = new Array();
                
                if (! this.isNull(elem) && ! this.isNull(cls)) {
                    tmp   = document.getElementsByTagName(elem);
                    var t = null;
                    
                    for (var i = 0; i < tmp.length; ++i) {
                        t = this.getCls(tmp.item(i));
                        if (! this.isNull(t) && t.indexOf(cls) != -1) {
                            obj.push(tmp.item(i));
                        }
                    }
                }
                
                return (! obj.length ? null : obj); 
            }
        } else {
            obj = document.getElementsByTagName(rule);
            
            return (! obj.length ? null : obj);
        }
    }
    
    return null;
};

/**
 * Check if object is DOM element.
 * 
 * @param  {Mixed} object   Object to test.
 * @return {Boolean}   Returns <b>TRUE</b> if object is DOM element, otherwise returns <b>FALSE</b>.
 */
cJsLib.prototype.isElement = function(object)
{
    return object && object.nodeType == 1;
};

/**
 * Check if object is array.
 * 
 * @param  {Mixed} object   Object to test.
 * @return {Boolean}   Returns <b>TRUE</b> if object is array, otherwise returns <b>FALSE</b>.
 */
cJsLib.prototype.isArray = function(object)
{
    return object != null && typeof object == 'object' && 'splice' in object && 'join' in object;
};

/**
 * Check if object is a function.
 * 
 * @param  {Mixed} object   Object to test.
 * @return {Boolean}   Returns <b>TRUE</b> if object is a function, otherwise returns <b>FALSE</b>.
 */
cJsLib.prototype.isFunction = function(object)
{
    return typeof object == 'function';
};

/**
 * Check if object is a string.
 * 
 * @param  {Mixed} object   Object to test.
 * @return {Boolean}   Returns <b>TRUE</b> if object is a string, otherwise returns <b>FALSE</b>. 
 */
cJsLib.prototype.isString = function(object)
{
    return typeof object == 'string';
};

/**
 * Check if object is a number.
 * 
 * @param  {Mixed} object   Object to test.
 * @return {Boolean}   Returns <b>TRUE</b> if object is a number, otherwise returns <b>FALSE</b>.
 */
cJsLib.prototype.isNumber = function(object)
{
    return typeof object == 'number';
};

/**
 * Get the CSS class name.
 *
 * @param  {Object} element   Target element object.
 * @return {Mixed}   Returns the CSS class name, otherwise returns empty string.
 */
cJsLib.prototype.getCls = function(element)
{
    if (this.isObject(element)) {
        return (this._browser['ie'] && this._browser['ieVersion'] < 8 ? element.getAttribute('className') : element.getAttribute('class'));
    }
    
    return '';
};

/**
 * Remove the CSS class name.
 * 
 * @param  {Object} element   Target element object.
 * @return {cJsLib}   Returns a fluent interface.
 */
cJsLib.prototype.rmCls = function(element, clsName)
{
    if (this.isObject(element)) {
        // remove all CSS classes
        if (this.empty(clsName)) {
            (this._browser['ie'] && this._browser['ieVersion'] < 8 ? element.removeAttribute('className') : element.removeAttribute('class'));
        } else {
            var cls  = this.getCls(element);
            cls = cls.replace(clsName, '');
            this.setCls(element, cls);
        }
    }
    
    return this;
};

/**
 * Set the CSS class name.
 *
 * @param  {Object} element   Target element object.
 * @param  {String} clsName   Name of the CSS class.
 * @return {cJsLib}   Returns a fluent interface.
 */
cJsLib.prototype.setCls = function(element, clsName)
{
    if (this.isObject(element) && !this.isNull(clsName)) {
        if (this._browser['ie'] && this._browser['ieVersion'] < 8) {
            element.setAttribute('className', clsName);
        } else {
            element.setAttribute('class', clsName);
        }
    }
    
    return this;
};

/**
 * Ass a new the CSS class name.
 *
 * @param  {Object} element   Target element object.
 * @param  {String} clsName   Name of the CSS class.
 * @return {cJsLib}   Returns a fluent interface.
 */
cJsLib.prototype.addCls = function(element, clsName)
{
    if (this.isObject(element) && !this.isNull(clsName)) {
        var cls = this.getCls(element);
        
        this.setCls(element, (! this.empty(cls) ? cls + ' ' : '') + clsName);
    }

    return this;
};

/**
 * Get the CSS style.
 *
 * @param {Object} element   DOM object of target element.
 * @return {String}   Returns CSS style.
 */
cJsLib.prototype.getCls = function(element)
{
    if (this.isObject(element)) {
        return (this._browser['ie'] && this._browser['ieVersion'] < 8 ? element.getAttribute('className') : element.getAttribute('class'));
    }
    
    return '';
};

/**
 * Set the CSS style on parent element.
 *
 * @param {Object} element   DOM object of target element.
 * @param {String} newStyle  The new CSS style.
 */
cJsLib.prototype.setStyle = function(element, newStyle)
{
    if (this.isObject(element)) {
        if (this._browser['ie']) {
            element.style.cssText = newStyle;
        } else {
            element.setAttribute('style', newStyle);
        }
    }
    
    return this;
};

/**
 * Delete the CSS style.
 *
 * @param {Object} element   DOM object of target element.
 */
cJsLib.prototype.rmStyle = function(element)
{
    if (this.isObject(element)) {
        if (this._browser['ie']) {
            element.style.cssText = '';
        } else {
            element.removeAttribute('style');
        }
    }
};

/**
 * Destroy element (remove it from DOM).
 * 
 * @param {Mixed} element   String with name of element or DOM object.
 */
cJsLib.prototype.destroyObj = function(element)
{
    if (!this.empty(element) && this.isObject(this.$(element))) {
        element = this.$(element);
    }
     
    if (this.isObject(element)) {
        var pElement = element.parentNode;
        
        // remove element from DOM
        pElement.removeChild(element);
    }
};

/**
 * Show / hide element.
 * 
 * Note: The CSS class name for hidden element must be `none`.
 * 
 * @param {String}    element        ID of element to show / hide.
 * @param {show|hide} targetStatus   OPTIONAL - Element's target status (if entered, element will be have a selected CSS class always).
 * @param {cJsLib}    Returns a fluent interface.
 */
cJsLib.prototype.sh = function(element, targetStatus)
{
    if (this.isString(element)) {
        element = this.$(element);
    }
    
    if (this.isObject(element)) {
        var clsName = this.getCls(element);
        
        targetStatus = ! this.empty(targetStatus) && targetStatus.toLowerCase() == 'hide' ? 'hide' : (! this.empty(targetStatus) && targetStatus.toLowerCase() == 'show' ? 'show' : null);
        
        if (clsName == 'none' && (targetStatus == null || targetStatus == 'show')) {
            this.rmCls(element);
        } else if (clsName != 'none' && (targetStatus == null || targetStatus == 'hide')) {
            this.setCls(element, 'none');
        }
    }
    
    return this;
};

/**
 * Read the cookie value.
 *
 * @param  {String} cookieName   Name of cookie.
 * @return {Mixed}   Return the cookie value if exists, otherwise returns null.
 */
cJsLib.prototype.getCookie = function(cookieName)
{
	var cookieValue = null;
	var search      = cookieName + "=";
	
	if (document.cookie.length > 0) { 

        offset = document.cookie.indexOf(search);
		
        if (offset != -1) { 
            offset += search.length;
            end = document.cookie.indexOf(";", offset);

            if (end == -1) {
                end = document.cookie.length;
            }

            cookieValue = unescape(document.cookie.substring(offset, end))
		}
	}
	
	return cookieValue;
};

/**
 * Set the cookie.
 *
 * @param {String} cookieName    Cookie name.
 * @param {String} cookieValue   Cookie value.
 * @param {Date}   expires       Cookie expires.
 * @param {cJsLib} Returns a fluent interface.
 */
cJsLib.prototype.setCookie = function(cookieName, cookieValue, expires)
{
    if (!this.isNull(cookieName)) {
	    // no expiration date specified? use this date and it will just be deleted soon
	    if (this.empty(expires)) {
	        expires = new Date();
	    }
	    
	    if (this.isNull(cookieValue)) {
	        cookieValue = '';
	    }    
	     
	    document.cookie = cookieName + '=' + escape(cookieValue) + '; expires=' + expires.toGMTString() + '; path=/';
    }
    
    return this;
};

/**
 * Set the onClick function.
 *
 * @param {Object} element   DOM object of parent element.
 * @param {String} onAction  Action for onclick event.
 * @param {cJsLib} Returns a fluent interface.
 */
cJsLib.prototype.setOnClick = function(element, onAction)
{
    if (this._browser['ie']) {
        element.onclick = new Function("env", onAction);
    } else {
        element.setAttribute('onclick', onAction);
    }
    
    return this;
};

/**
 * Set the onMouseOver function.
 *
 * @param {Object} element    DOM object of parent element.
 * @param {String} onAction   Action for onclick event.
 * @param {cJsLib} Returns a fluent interface.
 */
cJsLib.prototype.setOnMouseOver = function(element, onAction)
{
    if (this._browser['ie']) {
        element.onmouseover = new Function("env", onAction);
    } else {
        element.setAttribute('onmouseover', onAction);
    }
    
    return this;
};

/**
 * Set the onMouseOut function.
 *
 * @param {Object} element    DOM object of parent element.
 * @param {String} onAction   Action for onclick event.
 * @param {cJsLib} Returns a fluent interface.
 */
cJsLib.prototype.setOnMouseOut = function(element, onAction)
{
    if (this._browser['ie']) {
        element.onmouseout = new Function("env", onAction);
    } else {
        element.setAttribute('onmouseout', onAction);
    }
    
    return this;
};

/**
 * Finds whether the given variable is object.
 *
 * @param {Mixed}    variableToTest   The variable being evaluated.
 * @return {Boolean} Returns TRUE if element is object, FALSE otherwise. 
 */
cJsLib.prototype.isObject = function(variableToTest)
{
	if (this.isIE())
	{
		return (!this.isNull(variableToTest) && typeof variableToTest == 'object' ? true : false);
	}
	else
	{
		return (!this.isNull(variableToTest) && variableToTest instanceof Object ? true : false);
	}
	
	// return (!this.isNull(variableToTest) && typeof variableToTest == 'object' ? true : false);
};

/**
 * Finds whether the given variable is string.
 * 
 * @param {Mixed}    variableToTest   The variable being evaluated.
 * @return {Boolean} Returns TRUE if element is object, FALSE otherwise.
 */
cJsLib.prototype.isString = function(variableToTest)
{
    return (!this.empty(variableToTest) && typeof variableToTest == 'string' ? true : false);
};

/**
 * Finds whether the given variable is NULL.
 * 
 * @param {Mixed}    variableToTest   The variable being evaluated.
 * @return {Boolean} Returns TRUE if element is null, FALSE otherwise.
 */
cJsLib.prototype.isNull = function(variableToTest)
{
    return ((typeof variableToTest == 'object' && variableToTest == null) || typeof variableToTest == 'undefined' ? true : false); 
};

/**
 * Finds whether the given variable is empty.
 *
 * @param {Mixed}    variableToTest   The variable being evaluated.
 * @return {Boolean} Returns TRUE if element is empty (null or empty string), FALSE otherwise. 
 */
cJsLib.prototype.empty = function(variableToTest)
{
    return ((this.isNull(variableToTest) || variableToTest == '') ? true : false); 
};

/**
 * Center element on page.
 * 
 * @param {Object}  element       DOM object of requsted element to center.
 * @param {Boolean} scrollToTop   Scroll page to top (optional, default is FALSE)?
 * @param {cJsLib}  Returns a fluent interface.
 */
cJsLib.prototype.center = function(element, scrollToTop)
{
    scrollToTop = (!this.empty(scrollToTop) && scrollToTop === true) ? true : false;  
    
    if (this.isObject(element)) {
        pageSize   = this.getPageSize();
        pageScroll = this.getPageScroll();
        
        posLeft = pageScroll.scrollX + (pageSize.windowWidth / 2) - (element.offsetWidth / 2);
        posTop  = pageScroll.scrollY + (pageSize.windowHeight / 2) - (element.offsetHeight / 2);
        
        element.style.left = posLeft.toString() + 'px';
        element.style.top  = posTop.toString() + 'px';
        
        if (scrollToTop) {
            window.scroll(0, 0);
        }
        
        delete scrollToTop, pageSize, pageScroll, posLeft, posTop;
    }
    
    return this;
}

/**
 * Returns page scroll values.
 * 
 * @return {Object}   Returns a object with scroll values (scrollX, scrollY).
 */
cJsLib.prototype.getPageScroll = function()
{
    scrollX = 0;
    scrollY = 0;

    if (self.pageYOffset) {
        scrollY = self.pageYOffset;
        scrollX = self.pageXOffset;
    } else if (document.documentElement && document.documentElement.scrollTop){  // Explorer 6 Strict
        scrollY = document.documentElement.scrollTop;
        scrollX = document.documentElement.scrollLeft;
    } else if (document.body) {// all other Explorers
        scrollY = document.body.scrollTop;
        scrollX = document.body.scrollLeft; 
    }

    return {scrollX: scrollX, scrollY:scrollY};
}

/**
 * Returns page and window dimension.
 * 
 * @return {Object}   Returns object with page and window dimensions (pageWidth, pageHeight, windowWidth, windowHeight).
 */
cJsLib.prototype.getPageSize = function()
{
    scrollX      = 0;
    scrollY      = 0;
    windowWidth  = 0;
    windowHeight = 0;
    
    if (window.innerHeight && window.scrollMaxY) {  
        scrollX = window.innerWidth + window.scrollMaxX;
        scrollY = window.innerHeight + window.scrollMaxY;
    } else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
        scrollX = document.body.scrollWidth;
        scrollY = document.body.scrollHeight;
    } else { // Explorer Mac... would also work in Explorer 6 Strict, Mozilla and Safari
        scrollX = document.body.offsetWidth;
        scrollY = document.body.offsetHeight;
    }
    
    if (self.innerHeight) { // all except Explorer
        if( document.documentElement.clientWidth){
            windowWidth = document.documentElement.clientWidth; 
        } else {
            windowWidth = self.innerWidth;
        }
        
        windowHeight = self.innerHeight;
    } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
        windowWidth  = document.documentElement.clientWidth;
        windowHeight = document.documentElement.clientHeight;
    } else if (document.body) { // other Explorers
        windowWidth  = document.body.clientWidth;
        windowHeight = document.body.clientHeight;
    }   
    
    // for small pages with total height less then height of the viewport
    if(scrollY < windowHeight){
        pageHeight = windowHeight;
    } else { 
        pageHeight = scrollY;
    }

    // for small pages with total width less then width of the viewport
    if (scrollX < windowWidth) {  
        pageWidth = scrollX;        
    } else {
        pageWidth = windowWidth;
    }

    return {pageWidth: pageWidth, pageHeight: pageHeight, windowWidth: windowWidth, windowHeight: windowHeight};
}

/**
 * Get dimension of document.
 * 
 * @return {Object}   Returns object with document dimensions (width, height).
 */
cJsLib.prototype.getDocSize = function()
{
    width  = 0;
    height = 0;
    
    if (document.width && document.height) {
        width  = document.width;
        height = document.height; 
    } else if (document.body.scrollWidth && document.body.scrollHeight) {
        width  = document.body.scrollWidth;
        height = document.body.scrollHeight;
    }
    
    return {width: width, height: height};
};

/**
 * Get DOM element dimensions.
 * 
 * @param  {Object|String} element   DOM object or ID of element.
 * @return {Object}   Returns object with dimensions (width, height).
 */
cJsLib.prototype.getElementSize = function(element)
{
    var width  = 0;
    var height = 0;
    
    if (! this.isObject(element)) {
        element = this.$(element);
    }
    
    if (this.isObject(element)) {
        width  = element.offsetWidth;
        height = element.offsetHeight;
    }
    
    return {width: width, height: height};
};

/**
 * Create DOM element with defined type and attributes.
 *
 * @param {String} type   Type of a new DOM element (e.g. a, div, span etc.). 
 * @param {Object} args   Array with parameters.
 * <br />Possible values are (possible all values defined in DocType):
 * <ul>
 *  <li><b>atext</b> - text of link element,</li>
 *  <li><b>href</b> - URL of link element,</li>
 *  <li><b>id</b> - ID of link element,</li>
 *  <li><b>name</b> - name of link element,</li>
 *  <li><b>title</b> - title of link element,</li>
 *  <li><b>onclick</b> - onClick mouse event action,</li>
 *  <li><b>onmouseover</b> - onMouseOver mouse event action,</li>
 *  <li><b>onmouseout</b> - onMouseOut mouse event action,</li>
 *  <li><b>text</b> - text representation of link.</li>
 * </ul>
 * @return {Object}   Returns the DOM object of URL link.
 */
cJsLib.prototype.createElement = function(type, args)
{
    var element = document.createElement(type);

    if (this.isObject(args)) {
        var attrs = new Array();
        
	    for (var i in args) {
	        if (typeof args[i] != 'function') {
	            tmp       = new Object();
	            tmp.attr  = i.toLowerCase();
	            tmp.value = args[i];
	            
	            attrs.push(tmp);
	        }
	    }
	
	    // append attributes
		for (var i = 0; i < attrs.length; i++) {
		    switch (attrs[i].attr) {
		    	case 'onclick':
		    		this.setOnClick(element, attrs[i].value)
		    		break;
		    		
		    	case 'onmouseover':
		    	    this.setOnMouseOver(element, attrs[i].value);
		    	    break;
		    	    
		    	case 'onmouseout':
		    	    this.setOnMouseOut(element, attrs[i].value);
		    	    break

                case 'atext':
                    element.appendChild(document.createTextNode(attrs[i].value));
                    break;
                    
		    	default:
		    	    element.setAttribute(attrs[i].attr, attrs[i].value);
		    		break;
		    }
		}
    }

    return element;
};

/**
 * Get element position.
 *
 * @param {String}  element         ID of parent element.
 * @param {Boolean} parentOffsets   OPTIONAL - Add parent elements offset <i>(default: false)</i>).
 * @param {Object} Returns array with element position.
 */
cJsLib.prototype.getElementPosition = function(element, parentOffsets)
{
    var left = 0;
    var top  = 0;
    parentOffsets = ! cJsLib.isNull(parentOffsets) && parentOffsets == true ? true : false;
    
    if (! this.isObject(element)) {
        element = this.$(element);
    }
    
    if (this.isObject(element) && element.offsetParent) {
        left = element.offsetLeft;
        top  = element.offsetTop;

        if (parentOffsets) {
            while (element = element.offsetParent) {
                left += element.offsetLeft;
                top  += element.offsetTop;
            }
        }
    }

    return {left:left, top:top};
};

/**
 * Init a automatic show / hide .
 * 
 * @param {String}    elem      ID of element for action.
 * @param {Integer}   timeOut   Time out in seconds.
 * @param {show|hide} type      OPTIONAL - Kind of timed action.
 * @param {cJsLib}    Returns a fluent interface.
 */
cJsLib.prototype.registerTimeOutSh = function(elem, timeOut, type)
{
    if (! this.timeOutInited && this.isObject(this.$(elem))) {
        type    = this.empty(type) || type.toLowerCase() == 'show' ? 'show' : 'hide';
        timeOut = this.empty(timeOut) || timeOut <= 0 ? new Number(1000) : new Number(timeOut);
        
        this.timeOutAction  = type; // store kind of timed action
        this.timeOutElement = elem; // store element ID
        this.timeOut        = timeOut;
        this.timeOutInited  = true;
    }
    
    if (this.timeOutInited) {
        if (this.timeOut > 0) {
            --this.timeOut;
            this.timeOutId = window.setTimeout('cJsLib.registerTimeOutSh()', 1000);
        } else {
            hideExpress(this.timeOutElement.slice(this.timeOutElement.indexOf('-', 2) + 1));

            // default values
            this.resetTimeOut();
        }
    }
};

/**
 * Test if active any timed action.
 * 
 * @return {Boolean}
 */
cJsLib.prototype.isActiveTimeOut = function()
{
    return this.timeOutId == null ? false : true;
};

/**
 * Destroy a pointer to window timeout function.
 * 
 * @return {cJsLib}   Returns a fluent interface.
 */
cJsLib.prototype.destroyTimeOut = function()
{
    if (this.isActiveTimeOut()) {
        window.clearTimeout(this.timeOutId);
        this.resetTimeOut();
    }
    
    return this;
};

/**
 * Reset timed function for show / hide element.
 * 
 * @return {cJsLib}   Returns a fluent interface.
 */
cJsLib.prototype.resetTimeOut = function()
{
    this.timeOutId      = null;  // ID of pointer to window.setInterval()
    this.timeOut        = null;  // time out for automatic show / hide elements
    this.timeOutAction  = null;  // time out for automatic show / hide elements
    this.timeOutElement = null;  // ID of timed element
    this.timeOutInited  = false; // is inited a timed action
    
    return this;
};

/**
 * Check if user navigator is MS IE.
 * 
 * @return {Boolean}
 */
cJsLib.prototype.isIE = function()
{
    return this._browser['ie'];
}

// Private methods {{{
/**
 * Initialization of the object.
 * 
 * @returns cJsLib   Returns a fluent interface.
 */
cJsLib.prototype._init = function()
{
    this._detectBrowser();
    this.resetTimeOut();
    
    return this;
};

/**
 * Detect user browser.
 * 
 * @returns cJsLib   Returns a fluent interface.
 */
cJsLib.prototype._detectBrowser = function()
{
    this._browser   = new Array();
    var pattBrowser = new RegExp(/MSIE (\d+)\.\d+/gi);
    
    this._browser['ie']        = false;
    this._browser['ieVersion'] = new Number(0);
    
    if (navigator.userAgent.match(pattBrowser)) {
        this._browser['ie']        = true;
        this._browser['ieVersion'] = new Number(RegExp.$1);
    }
    
    return this;
};
// END: Private methods }}}


// overload of basic javascript objects {{{

/**
 * Encode string to HTML entities.
 *
 * @return {String}
 */
String.prototype.htmlEntities = function()
{
	var chars    = new Array('<', '>', '&');
	var entities = new Array('lt', 'gt', 'amp');

	newString = this;

	for (var i = 0; i < chars.length; i++) {
		myRegExp = new RegExp();
		myRegExp.compile(chars[i], 'g');
		newString = newString.replace(myRegExp, '&' + entities[i] + ';');
	}

	return newString;
};

/**
 * Checks if a value exists in an array.
 *
 * @param {String} needle  The searched value.
 * @param {Boolean} strictSearch   Search by the first occurrence of the specified value in index array.
 * @return {Boolean}   Returns TRUE if needle is found in the array, FALSE otherwise.
 */
Array.prototype.inArray = function(needle, strictSearch)
{
    exists       = false;
    strictSearch = cJsLib.isNull(strictSearch) || strictSearch != false ? true : false;
    
    if (!cJsLib.isNull(needle) && cJsLib.isObject(this) && this.length > 0) {
        for (i in this) {
            if (typeof this[i] != 'function') {
                if (!strictSearch) {
                    if (this[i].indexOf(needle) > -1) {
                        exists = true;
                        break ;
                    }
                } else {
                    if (this[i] == needle) {
                        exists = true;
                        break ;
                    }
                }
            }
        }
        
        delete i;
    }
    
    return exists;
};

/**
 * Searches the array for a given value and returns the corresponding key if successful.
 *
 * @param {Mixed} needle   The searched value.
 * @param {Boolean} strictSearch   Search by the first occurrence of the specified value in index array.
 * @return {Mixed}   Returns the key for needle if it is found in the array, FALSE otherwise.
 */
Array.prototype.search = function(needle, strictSearch)
{
    key          = false;
    strictSearch = cJsLib.isNull(strictSearch) || strictSearch != false ? true : false;
    
    if (!cJsLib.isNull(needle) && cJsLib.isObject(this) && this.length > 0) {
        for (i = 0; i < this.length; i++) {
            if (!strictSearch) {
                if (this[i].indexOf(needle) > -1) {
                    key = i;
                    break ;
                }
            } else {
                if (this[i] == needle) {
                    key = i;
                    break ;
                }
            }
        }
        
        delete i;
    }
    
    return key;
};

// END: overload of basic javascripts object }}}