/**
 * @desc        GW Object [Common]
 * @author      Christopher Sanford
 * @author      <influences noted>
 * @version     1.0.0
 * @copyright   (CC) 2005 Christopher Sanford
 * @url         http://www.christophersanford.com/
 * 
 * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General 
 * Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) 
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied 
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to 
 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 */

String.prototype.trim = function()
{
    return this.replace(/^\s+|\s+$/, '');
};
String.prototype.rtrim = function()
{
    return this.replace(/\s+$/, '');
};
String.prototype.ltrim = function()
{
    return this.replace(/^\s+/, '');
};

if (!GW) var GW = new Object;

/**
 *  GW General Functions
 *
 *  Info:
 *      DOM Functions
 *          Heavily influenced (ripped) by http://developer.mozilla.org/en/docs/Whitespace_in_the_DOM
 *              -Added scanTreeUp / scanTreeDown functions
 *
 *      Serialize/Unserialize Functions
 *          JS implementation of PHP's serialize/unserialize functions
 *              -multidimensional support
 *              -compatible with PHP
 *                  -PHP Array => JS Object
 *                  -JS Array/Object => PHP Array
 *
 *  Notes:
 *      scanTreeUp / scanTreeDown will probably change because they 
 *      technically only find first child / parent, rather than scanning
 *      all nodes. findFirstUp() / findFirstDown() maybe? 
 *
 *  Issues:
 *      12/9/2005 - DOM Functions not working in Safari.  Will look into at some point.
 *      11/29/2005 - JS and PHP handle floats differently (precision)
 *      11/29/2005 - Be careful when writing array to cookie. Use escape / unescape (JS)
 *                   AND urlencode / urldecode (PHP)
 *
 */

GW.nodeEmpty = function(node)
{
    if (typeof node.data != 'undefined') {
        return !(/[^\t\n\r ]/.test(node.data));
    } else {
        return false;
    }
};
GW.nodeSkip = function(node)
{
    return (node.nodeType == 8) || ((node.nodeType == 3) && this.nodeEmpty(node));
};
GW.nextSibling = function(node)
{
    while ((node = node.nextSibling)) {
        if (!this.nodeSkip(node)) return node;
    }
    return null;
};
GW.previousSibling = function(node)
{
    while ((node = node.previousSibling)) {
        if (!this.nodeSkip(node)) return node;
    }
    return null;
};
GW.firstChild = function(node)
{
    if (node.firstChild) {
        var child = node.firstChild;
        while (child) {
            if (!this.nodeSkip(child)) return child;
            child = child.nextSibling;
        }
    }
    return null;
};
GW.lastChild = function(node)
{
    if (node.lastChild) {
        var child = node.lastChild;
        while (child) {
            if (!this.nodeSkip(child)) return child;
            child = child.previousSibling;
        }
    }
    return null;
};
GW.scanTreeUp = function(obj, target)
{
    target = target.toUpperCase();
    if (typeof obj == 'string' &&
        document.getElementById)
        obj = document.getElementById(obj);
    if (obj && obj.parentNode) {
        obj = obj.parentNode;
        while (obj && obj.tagName) {
            if (obj.tagName.toUpperCase() == target) return obj;
            if (obj.parentNode) obj = obj.parentNode;
        }
    }
    return null;
};
GW.scanTreeDown = function(obj, target)
{
    target = target.toUpperCase();
    if (typeof obj == 'string' &&
        document.getElementById)
        obj = document.getElementById(obj);
    if (obj) {
        obj = this.firstChild(obj);
        while (obj && obj.tagName) {
            if (obj.tagName.toUpperCase() == target) return obj;
            obj = this.firstChild(obj);
        }
    }
    return null;
};
GW.serialize = function(obj)
{
    var tmp = [];
    var str = '';
    var count = 0;
    for (var o in obj) {
        if (typeof obj[o] == 'object') {
            // empty property
            if (!o.length) continue;
            // numeric key
            if (isNaN(o)) {
                // null?
                if (obj[o] == null) {
                    str += 's:'+ o.length +':"'+ o +'";N;';
                } else {
                    str += 's:'+ o.length +':"'+ o +'";'+ this.serialize(obj[o]);
                }
            // string key
            } else {
                // null
                if (obj[o] == null) {
                    str += 'i:'+ o +';N;';
                } else {
                    str += 'i:'+ o +';'+ this.serialize(obj[o]);
                }
            }                
            count++;
        } else    {
            switch (typeof obj[o]) {
                case 'number':
                    // signed / unsigned float
                    if (obj[o].toString().match(/^[+-]*\d+\.\d*?/)) {
                        // string key
                        if ( isNaN(o) ) {
                            str += 's:'+ o.length +':"'+ o +'";d:'+ parseFloat(obj[o]) +';';
                        // numeric key
                        } else {
                            str += 'i:'+ o +';d:'+ parseFloat(obj[o]) +';';
                        }
                    // integer
                    } else {
                        // string key
                        if (isNaN(o)) {
                            str += 's:'+ o.length +':"'+ o +'";i:'+ parseInt(obj[o]) +';';
                        // numeric key
                        } else {
                            str += 'i:'+ o +';i:'+ parseInt(obj[o]) +';';
                        }
                    }
                    count++;
                    break;
                case 'string':
                    // string key
                    if (isNaN(o)) {
                        // null
                        if (obj[o] == 'N') {
                            str += 's:'+ o.length +':"'+ o +'";N;';
                        } else {
                            str += 's:'+ o.length +':"'+ o +'";';
                            str += 's:'+ obj[o].length +':"'+ obj[o] +'";';
                        }
                    // numeric key
                    } else {
                        // null
                        if (obj[o] == 'N') {
                            str += 'i:'+ o +';N;';
                        } else {
                            str += 'i:'+ o +';s:'+ obj[o].length +':"'+ obj[o] +'";';
                        }
                    }
                    count++;
                    break;
            }
        }
    }
    str = 'a:'+ count +':{'+ str +'}';
    return str;
};
GW.unserialize = function(str)
{
    var str = str.toString();
    var ref = 'var obj = new Object;';
    var match = [];
    str = unescape(str);
    match = str.match(/\".+?\"/ig);
    if (match) {
        var tmp = '';
        for (var m = 0, c = match.length; m < c; m++) {
            if (match[m].indexOf(':') != -1 ||
                match[m].indexOf(';') != -1) {
                continue;
            }
            match[m] = match[m].replace(/\"/g, '');
            tmp = escape(match[m]);
            match[m] = match[m].replace(/\{/g, '\\\{');
            match[m] = match[m].replace(/\}/g, '\\\}');
            match[m] = match[m].replace(/\&/g, '\\\&');
            match[m] = match[m].replace(/\?/g, '\\\?');
            var regexp = new RegExp(match[m], 'g');
            str = str.replace(regexp, tmp);
        }
    }
    str = str.replace(/\}+$/, '');
    str = str.replace(/^\w\:\d+\:\{/, '');
    str = str.replace(/\\\+/, '');
    match = str.split(/\}+/);
    for(var m = 0, mc = match.length; m < mc; m++ ) {
        var keys = [];
        var tmp = [];
        tmp = match[m].split(/\w\:\d+\:\{/);
        for(var t = 0, tc = tmp.length; t < tc; t++) {
            tmp[t] = tmp[t].replace(/\;$/, '');
            if (tmp[t].indexOf(';') > 0) {
                tmp[t] = tmp[t].split(/\;/);
                for (var i = 0, ic = tmp[t].length; i < ic; i++ ) {
                    if (i % 2 != 0) continue;
                    var key = [];
                    key = tmp[t][i].split(':');
                    key = key[key.length-1];
                    key = key.replace(/\"/g, '');
                    keys.push(key);
                    if (typeof tmp[t][i+1] != 'undefined') {
                        var value = [];
                        value = tmp[t][i+1].split(':');
                        value = value[value.length-1];
                        value = value.replace(/\"/g, '');
                        if (value == '') {
                            keys.pop();
                            continue;
                        }
                        if (value=='N') {
                            ref += 'obj["'+ keys.join('"]["') +'"] = null;';
                        } else {
                            ref += 'obj["'+ keys.join('"]["') +'"] = '+ '"'+ unescape(value) +'";';
                        }
                        value = null;
                        keys.pop();
                    } else {
                        ref += 'obj["'+ keys.join('"]["') +'"] = {};';
                    }
                    key = null;
                }
            } else {
                var key = [];
                key = tmp[t].split(':');
                key = key[key.length-1];
                key = key.replace(/\"/g,'');
                keys.push(key);
                ref += 'obj["'+ keys.join('"]["') +'"] = {};';
                key = null;
            }
        }
        tmp = null;
    }
    eval(ref);
    return (obj) ? obj : null;
};

/**
 *  GW Cookie Object
 *
 *  Info:
 *      Heavily influenced (ripped) by http://www.phonophunk.com (John Serris)
 *      (which in turn was influenced by Shaun Inman)
 *
 *  Notes:
 *      John Serris has exceptional (pimp) skills.  Check his site out now.
 *      While you are at it, go to www.shauninman.com and learn from an 
 *      industry icon.
 *
 */

GW.Cookies = {
	setCookie: function(name, value, days) {
		var expires = '';
		if (days) {
			var date = new Date();
			date.setTime(date.getTime() + (days*24*60*60*1000));
			expires = '; expires=' + date.toGMTString();
		}
		document.cookie = name + '=' + escape(value) + '; ' + expires + '; path=/';
	},
	getCookie: function(name) {
        name = name.toLowerCase();
		var cookie = document.cookie.split(/;\s+/);
		for (var c = 0, cc = cookie.length; c < cc; c++) {
            cookie[c] = cookie[c].split('=');
            if (cookie[c][0].toLowerCase() == name) {
                return unescape(cookie[c][1]);
            }
		}
		return null;
	}
};


/**
 *  GW Nav Object
 *
 *  Info:
 *      Handles expand / contract functionality of navigation
 *      Reads / Writes information to serialized cookie
 *
 */

GW.Nav = {
    showBlock: function(obj)
    {
        var element = {};
        var parent = {};
        var nav = {};
        var cookie = GW.Cookies.getCookie('srvtree');
        if (cookie != null) {
            cookie = GW.unserialize(cookie);
            var li = GW.scanTreeUp(obj,'LI');
            if (li) {
                if (li.className.match(/hide/i)) {
                    cookie[li.id] = 1;
                    li.className = li.className.replace('hide','show');
                } else {
                    cookie[li.id] = 0;
                    li.className = li.className.replace('show','hide');
                }
            }
            cookie = GW.serialize(cookie);
            GW.Cookies.setCookie('srvtree', cookie);
        }
        obj.blur();
        return false;
    }
};
