// TOOLBOX namespace, for all new functions to go in
TOOLBOX = (typeof TOOLBOX !== 'undefined') ? TOOLBOX  : {};
// setup a window.onload to flag when loaded
TOOLBOX.windowLoaded = false;
YAHOO.util.Event.addListener(window, 'load', function() { TOOLBOX.windowLoaded=true; });
TOOLBOX.cookiePath = "";
TOOLBOX.Events = {};
TOOLBOX.Events.BeforePrint = new YAHOO.util.CustomEvent('beforePrint');
TOOLBOX.confirmDelete = function(link,confirm_text) {
    if (typeof confirm_text=='undefined') {
        confirm_text = 'Are you sure you want to delete this item?';
    }
    TOOLBOX.confirm({ text : confirm_text,
                      handleYes : function() { this.hide(); document.location.href = link; }
    });
};
TOOLBOX.confirm = function(config)
{
    TOOLBOX.globals = TOOLBOX.globals || {};
    TOOLBOX.globals.simpleConfirm = TOOLBOX.globals.simpleConfirm || new YAHOO.widget.SimpleDialog('simpleConfirm',
			 { width: "300px",
			   fixedcenter: true,
			   visible: false,
			   draggable: true,
			   close: true,
               modal : true,
			   text: 'Are you sure?', // this should be set in config.text
			   icon: 'hlpicon',
			   constraintoviewport: true,
			   buttons: [ { text:TOOLBOX.Lang.yes, handler: null, isDefault:true },
						  { text:TOOLBOX.Lang.no,  handler: function() { this.hide(); } } ]
			 } );
    if (typeof config.header == 'undefined') {
        TOOLBOX.globals.simpleConfirm.setHeader(TOOLBOX.Lang.alert);
    }
    else {
        TOOLBOX.globals.simpleConfirm.setHeader(config.header);
    }
    // check for config.handleYes function
    if (typeof config.handleYes != 'undefined') {
        var buttons = TOOLBOX.globals.simpleConfirm.cfg.getProperty('buttons');
        buttons[0].handler = config.handleYes;
        config.buttons = buttons;
    }
    // merge config
    TOOLBOX.globals.simpleConfirm.cfg.applyConfig(config);
    TOOLBOX.globals.simpleConfirm.render(document.body);
    TOOLBOX.globals.simpleConfirm.show();
};
TOOLBOX.alert = function(text)
{
    TOOLBOX.globals = TOOLBOX.globals || {};
    TOOLBOX.globals.alertDialog = TOOLBOX.globals.alertDialog || new YAHOO.widget.SimpleDialog('alertDialog',
			 { width: "300px",
			   fixedcenter: true,
			   visible: false,
			   draggable: true,
			   close: true,
               modal : true,
			   text: 'Warning!', // this will be over-written
			   icon: 'alrticon',
			   constraintoviewport: true,
			   buttons: [ { text:TOOLBOX.Lang.ok,  handler: function() { this.hide(); } } ]
			 } );
    TOOLBOX.globals.alertDialog.setHeader(TOOLBOX.Lang.alert);
    TOOLBOX.globals.alertDialog.cfg.applyConfig({text:text});
    TOOLBOX.globals.alertDialog.render(document.body);
    TOOLBOX.globals.alertDialog.show();
};
YAHOO.util.Event.addListener(window, 'load', function() { window.alert = TOOLBOX.alert });
TOOLBOX.print = function()
{
    TOOLBOX.Events.BeforePrint.fire();
    window.print();
}
TOOLBOX.multipleSelectReplace = function(ele) {
    if (typeof ele.tagName == 'undefined') {
        ele = document.getElementById(ele);
        if (ele==null) {
            return false;
        }
    }
    if (typeof ele.tagName != 'undefined' && ele.tagName.toLowerCase()=='select') {
        if (ele.className.match('MultipleSelectReplace')) {
            multiple_select_replace(ele);
        }
    }
    return true;
};
TOOLBOX.registerListingTable = function(tableName,tbl) {
    // clean up table name
    tableName = tableName.replace(/[^A-z]/g,'_').toLowerCase();
    if (typeof window.listingTables == 'undefined') {
        window.listingTables = {};
    }
    var count;
    if (1 || (typeof window.listingTables[tableName]=='undefined')) {
        window.listingTables[tableName] = tbl
        count = 0;
    }
    else {
        window.listingTables[tableName] = [window.listingTables[tableName], tbl];
        count = window.listingTables[tableName].length-1;
    }

    return tableName + count.toString();
};
TOOLBOX.getListingTable = function(tableName) {
    tableName = tableName.replace(/[^A-z]/g,'_').toLowerCase();
    return (typeof window.listingTables!='undefined'
            &&typeof window.listingTables[tableName]!='undefined') ? window.listingTables[tableName]
                                                                   : false;
};
TOOLBOX.registerFormTable = function(formName,frm) {
    // clean up table name
    formName = formName.replace(/[^A-z]/g,'_').toLowerCase();
    if (typeof window.formTables == 'undefined') {
        window.formTables = {};
    }
    var count;
    if (typeof window.formTables[formName]=='undefined') {
        window.formTables[formName] = frm
        count = 0;
    }
    else {
        window.formTables[formName] = [window.formTables[formName], frm];
        count = window.formTables[formName].length-1;
    }

    return formName + count.toString();
};
TOOLBOX.getFormTable = function(formName) {
    formName = formName.replace(/[^A-z]/g,'_').toLowerCase();
    return (typeof window.formTables!='undefined'
            &&typeof window.formTables[formName]!='undefined') ? window.formTables[formName]
                                                               : false;
};
TOOLBOX.blurField = function(fld) {
    DOM_Editor.removeClass(fld,'fieldFocus');
};
TOOLBOX.focusField = function(fld) {
    DOM_Editor.addClass(fld,'fieldFocus');
};
TOOLBOX.mergeConfig = function(config,default_config)
{
    if (typeof config == 'undefined') {
        config = {};
    }
    for (var i in default_config) {
        if (typeof config[i] == 'undefined') {
            config[i] = default_config[i];
        }
    }
    return config;
};
TOOLBOX.setCookie = function(cName,value,expireSeconds)
{
    var _cookie = cName+ "=" +escape(value);
    if (typeof expireSeconds != 'undefined') {
        var exdate=new Date();
        exdate.setTime(exdate.getTime() + (expireSeconds * 1000));
        _cookie += ";expires="+exdate.toGMTString();
    }
    _cookie += ";path="+TOOLBOX.cookiePath;
    document.cookie = _cookie;
};
TOOLBOX.getCookie = function(name)
{
    var theCookies = document.cookie.split(/[; ]+/);
    var returnVal = null;
    for (var i = 0 ; i < theCookies.length; i++) {
        var aName = theCookies[i].substring(0,theCookies[i].indexOf('='));
        if (aName == name) {
            returnVal = unescape(theCookies[i].substring(theCookies[i].indexOf('=')+1));
        }
    }
    return returnVal;

};
TOOLBOX.clearContainer = function(containerName)
{
    var el = document.getElementById(containerName);
    if (el != null) {
        while (el.childNodes.length > 0) {
            el.removeChild(el.firstChild);
        }
    }
};
TOOLBOX.showSystemMessage = function(message, status)
{
    var el = document.getElementById("app-system-message");
    el.innerHTML = message;
    if (status == 'error') {
        el.className = 'message statusError';
    }
    else if (status=='progress') {
        el.className = 'message statusProgress';
    } else { // info status
        el.className = 'message statusInfo';
    }
    el.style.display = "";
    var timerId = window.setInterval(function() {
       window.clearInterval(timerId);
       el.style.display = "none";
    }, 10000);
    return timerId;
};
TOOLBOX.hideSystemMessage = function(timerId)
{
    var el = document.getElementById('app-system-message');
    if (el != null) {
        el.style.display = 'none';
    }
    if ((typeof timerId != 'undefined') && (timerId != null)) {
        window.clearInterval(timerId);
    }
};
TOOLBOX.LoadingMessage = ( function()
{
    var config = {};
    var defaultConfig = {
        loadingElName     : 'app-system-loader',
        loadingTextElName : 'app-system-loader-text',
        stillWorkingDelay : 5000
    };
    var stillWorkingTimerId = false;
    var initCalled = false;
    return {
        init : function(options) {
            if (typeof options != 'undefined') {
                config = options;
            }
            config = TOOLBOX.mergeConfig(config, defaultConfig);
            initCalled = true;
        },
        show : function() {
            if (!initCalled) {
                this.init();
            }
            var loadingEl = document.getElementById(config.loadingElName);
            var loadingTextEl = document.getElementById(config.loadingTextElName);
            if (loadingEl && loadingTextEl) {
                loadingTextEl.innerHTML = TOOLBOX.Lang.loading;
                loadingEl.style.display = '';
                stillWorkingTimerId = window.setInterval(function() {
                    window.clearInterval(stillWorkingTimerId);
                    loadingTextEl.innerHTML = TOOLBOX.Lang.stillWorking;
                }, config.stillWorkingDelay);
            }
        },
        hide : function() {
            if (!initCalled) {
                this.init();
            }
            var loadingEl = document.getElementById(config.loadingElName);
            if (loadingEl) {
                loadingEl.style.display = 'none';
                if (stillWorkingTimerId) {
                    window.clearInterval(stillWorkingTimerId);
                }
            }
        }
    };
})();
TOOLBOX.Notify = {};
TOOLBOX.Notify.show = function(message)
{
    var notifyPanel = new YAHOO.widget.Panel(
        "message-notify-div",
        {
            width : "180px",
            height : "160px",
            fixedcenter : false,
            close : true,
            draggable : false,
            modal : false,
            visible : false,
            context : ["bottom-right", "br", "tr"],
            effect : {effect : YAHOO.widget.ContainerEffect.FADE, duration : 0.75}
        }
    );
    notifyPanel.setHeader('&nbsp;');
    notifyPanel.setBody(message);
    notifyPanel.render(document.body);
    window.setTimeout(function() {notifyPanel.show();}, 300);
    window.setTimeout(function() {notifyPanel.hide();}, 5000);
};
TOOLBOX.navigateSecurely = function(link, hashParam, secureCookieName)
{
    var e = window.event,
        middleClick = false,
        ctrlClick = false,
        shiftClick = false,
        newWindow = false;
    if (e) {
        middleClick = (e.which==2 && e.target && e.target.nodeName &&
                                'a'===e.target.nodeName.toLowerCase());
        
        ctrlClick = e.ctrlKey;
        shiftClick = e.shiftKey;
    }
    if (middleClick || ctrlClick || shiftClick) {
        // Open in a new window.
        window.open(TOOLBOX.hashUrl(link, hashParam, secureCookieName));
    }
    else {
        // Navigate to as normal.
        document.location.href = TOOLBOX.hashUrl(link, hashParam, secureCookieName);
    }
};
TOOLBOX.hashUrl = function(link, hashParam, secureCookieName)
{
    if (typeof hashParam == 'undefined') {
        hashParam = 'j';
    }
    var hashValue = TOOLBOX.hashValue(link, secureCookieName);
    var href = link;    
    if (href.indexOf('?') > 0) {
        href += '&' + hashParam + '=' + hashValue;
    }
    else {
        href += '/' + hashParam + '/' + hashValue;
    }
    return href;
};
TOOLBOX.hashValue = function(link, secureCookieName)
{
    // get just the 'relative' part of the link
    var linkParts = link.parseUrl();
    var hashPart = linkParts.path;
    if (linkParts.query) {
        hashPart += '?' + linkParts.query;
    }
    if (typeof secureCookieName == 'undefined') {
        secureCookieName = 'NID';
    }
    return md5(TOOLBOX.getCookie(secureCookieName) + hashPart);
};
TOOLBOX.current = function(obj)
{
    for (var i in obj) {
        return obj[i];
    }
    return false;
};
TOOLBOX.isArray = function(v)
{ 
    return (v.constructor.toString().indexOf("Array") >= 0)
};
TOOLBOX.createColourPickerSingle = function(hiddenId,containerId,buttonId,config)
{
    config.hiddenField     = hiddenId;
    config.colourContainer = containerId;
    config.button          = buttonId;
    var cp = new TOOLBOX.ColourPicker(config); // DIV style
    // cp.writeDiv();
    // add the action
    (function(cp)
    {
        YAHOO.util.Event.addListener(buttonId,
                                     'click',
                                     function(e,o)
                                     {
                                         o.show();
                                     }
                                     ,
                                     cp
        );
    })(cp);
};
TOOLBOX.require = function(filename) {
    var d = window.document;
    var js_code = TOOLBOX.fileGetContents(filename);
    var script_block = d.createElementNS ? d.createElementNS('http://www.w3.org/1999/xhtml', 'script') : d.createElement('script');
    script_block.type = 'text/javascript';
    var client_pc = navigator.userAgent.toLowerCase();
    if ((client_pc.indexOf('msie') !== -1) && (client_pc.indexOf('opera') === -1)) {script_block.text = js_code;
    } else {
        script_block.appendChild(d.createTextNode(js_code));
    }
        if (typeof(script_block) != "undefined") {
        d.getElementsByTagName('head')[0].appendChild(script_block);
    }
    return 0;
};
TOOLBOX.requireOnce = function(filename) {
    TOOLBOX.globals = TOOLBOX.globals || {};
    TOOLBOX.globals.requireOnceFiles = TOOLBOX.globals.requireOnceFiles || [];
    var d = window.document;

    if (TOOLBOX.globals.requireOnceFiles.length==0) {
        // check the DOM for script tags with a src
        var scripts = d.getElementsByTagName('head')[0].getElementsByTagName('script');
        for (var i=0; i<scripts.length; i++) {
            if (scripts[i].getAttribute('src')) {
                TOOLBOX.globals.requireOnceFiles.push(scripts[i].getAttribute('src'));
            }
        }
    }

    if (TOOLBOX.globals.requireOnceFiles.inArray(filename)==-1) {
        TOOLBOX.require(filename);
        TOOLBOX.globals.requireOnceFiles.push(filename);
    }
};
TOOLBOX.evalScriptTag = function(script)
{
    if (script.innerHTML) {
        var d = window.document;
        var js_code = script.innerHTML;
        var script_block = d.createElementNS ? d.createElementNS('http://www.w3.org/1999/xhtml', 'script') : d.createElement('script');
        script_block.type = 'text/javascript';
        var client_pc = navigator.userAgent.toLowerCase();
        if ((client_pc.indexOf('msie') !== -1) && (client_pc.indexOf('opera') === -1)) {script_block.text = js_code;
        } else {
            script_block.appendChild(d.createTextNode(js_code));
        }
            if (typeof(script_block) != "undefined") {
            d.getElementsByTagName('head')[0].appendChild(script_block);
        }
    }
    return 0;
};
// http://phpjs.org/functions/file_get_contents:400
TOOLBOX.fileGetContents = function (url, flags, context, offset, maxLen)
{
    // Read the entire file into a string
    //
    // version: 906.111
    // discuss at: http://phpjs.org/functions/file_get_contents
    // +   original by: Legaev Andrey
    // +      input by: Jani Hartikainen
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +   input by: Raphael (Ao) RUDLER
    // +   bugfixed by: Brett Zamir (http://brett-zamir.me)
    // %        note 1: This function uses XmlHttpRequest and cannot retrieve resource from different domain without modifications.
    // %        note 2: Synchronous by default (as in PHP) so may lock up browser. Can
    // %        note 2: get async by setting a custom "phpjs.async" property to true and "notification" for an
    // %        note 2: optional callback (both as context params, with responseText, and other JS-specific
    // %        note 2: request properties available via 'this'). Note that file_get_contents() will not return the text
    // %        note 2: in such a case (use this.responseText within the callback). Or, consider using
    // %        note 2: jQuery's: $('#divId').load('http://url') instead.
    // %        note 3: The context argument is only implemented for http, and only partially (see below for
    // %        note 3: "Presently unimplemented HTTP context options"); also the arguments passed to
    // %        note 3: notification are incomplete
    // *     example 1: file_get_contents('http://kevin.vanzonneveld.net/pj_test_supportfile_1.htm');
    // *     returns 1: '123'
    // Note: could also be made to optionally add to global $http_response_header as per http://php.net/manual/en/reserved.variables.httpresponseheader.php

    var tmp, headers = [], newTmp = [], k=0, i=0, href = '', pathPos = -1, flagNames = 0, content = null, http_stream = false;
    var func = function (value) {return value.substring(1) !== '';};

    // BEGIN REDUNDANT
    this.php_js = this.php_js || {};
    this.php_js.ini = this.php_js.ini || {};
    // END REDUNDANT

    var ini = this.php_js.ini;
    context = context || this.php_js.default_streams_context || null;

    if (!flags) {flags = 0;}
    var OPTS = {
        FILE_USE_INCLUDE_PATH : 1,
        FILE_TEXT : 32,
        FILE_BINARY : 64
    };
    if (typeof flags === 'number') { // Allow for a single string or an array of string flags
        flagNames = flags;
    }
    else {
        flags = [].concat(flags);
        for (i=0; i < flags.length; i++) {
            if (OPTS[flags[i]]) {
                flagNames = flagNames | OPTS[flags[i]];
            }
        }
    }

    if (flagNames & OPTS.FILE_BINARY && (flagNames & OPTS.FILE_TEXT)) { // These flags shouldn't be together
        throw 'You cannot pass both FILE_BINARY and FILE_TEXT to file_get_contents()';
    }

    if ((flagNames & OPTS.FILE_USE_INCLUDE_PATH) && ini.include_path &&
            ini.include_path.local_value) {
        var slash = ini.include_path.local_value.indexOf('/') !== -1 ? '/' : '\\';
        url = ini.include_path.local_value+slash+url;
    }
    else if (!/^(https?|file):/.test(url)) { // Allow references within or below the same directory (should fix to allow other relative references or root reference; could make dependent on parse_url())
        href = window.location.href;
        pathPos = url.indexOf('/') === 0 ? href.indexOf('/', 8)-1 : href.lastIndexOf('/');
        url = href.slice(0, pathPos+1)+url;
    }

    if (context) {
        var http_options = context.stream_options && context.stream_options.http;
        http_stream = !!http_options;
    }

    if (!context || http_stream) {
        var req = window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest();
        if (!req) {throw new Error('XMLHttpRequest not supported');}

        var method = http_stream ? http_options.method : 'GET';
        var async = !!(context && context.stream_params && context.stream_params['phpjs.async']);

        if (ini['phpjs.ajaxBypassCache'] && ini['phpjs.ajaxBypassCache'].local_value) {
            url += (url.match(/\?/) == null ? "?" : "&") + (new Date()).getTime(); // Give optional means of forcing bypass of cache
        }

        req.open(method, url, async);
        if (async) {
            var notification = context.stream_params.notification;
            if (typeof notification === 'function') {
                // Fix: make work with req.addEventListener if available: https://developer.mozilla.org/En/Using_XMLHttpRequest
                if (0 && req.addEventListener) { // Unimplemented so don't allow to get here
                    /*
                    req.addEventListener('progress', updateProgress, false);
                    req.addEventListener('load', transferComplete, false);
                    req.addEventListener('error', transferFailed, false);
                    req.addEventListener('abort', transferCanceled, false);
                    */
                }
                else {
                    req.onreadystatechange = function (aEvt) { // aEvt has stopPropagation(), preventDefault(); see https://developer.mozilla.org/en/NsIDOMEvent

    // Other XMLHttpRequest properties: multipart, responseXML, status, statusText, upload, withCredentials
    /*
    PHP Constants:
    STREAM_NOTIFY_RESOLVE   1       A remote address required for this stream has been resolved, or the resolution failed. See severity  for an indication of which happened.
    STREAM_NOTIFY_CONNECT   2     A connection with an external resource has been established.
    STREAM_NOTIFY_AUTH_REQUIRED 3     Additional authorization is required to access the specified resource. Typical issued with severity level of STREAM_NOTIFY_SEVERITY_ERR.
    STREAM_NOTIFY_MIME_TYPE_IS  4     The mime-type of resource has been identified, refer to message for a description of the discovered type.
    STREAM_NOTIFY_FILE_SIZE_IS  5     The size of the resource has been discovered.
    STREAM_NOTIFY_REDIRECTED    6     The external resource has redirected the stream to an alternate location. Refer to message .
    STREAM_NOTIFY_PROGRESS  7     Indicates current progress of the stream transfer in bytes_transferred and possibly bytes_max as well.
    STREAM_NOTIFY_COMPLETED 8     There is no more data available on the stream.
    STREAM_NOTIFY_FAILURE   9     A generic error occurred on the stream, consult message and message_code for details.
    STREAM_NOTIFY_AUTH_RESULT   10     Authorization has been completed (with or without success).

    STREAM_NOTIFY_SEVERITY_INFO 0     Normal, non-error related, notification.
    STREAM_NOTIFY_SEVERITY_WARN 1     Non critical error condition. Processing may continue.
    STREAM_NOTIFY_SEVERITY_ERR  2     A critical error occurred. Processing cannot continue.
    */
                        var objContext = {
                            responseText : req.responseText,
                            responseXML : req.responseXML,
                            status : req.status,
                            statusText : req.statusText,
                            readyState : req.readyState,
                            evt : aEvt
                        }; // properties are not available in PHP, but offered on notification via 'this' for convenience

                        // notification args: notification_code, severity, message, message_code, bytes_transferred, bytes_max (all int's except string 'message')
                        // Need to add message, etc.
                        var bytes_transferred;
                        switch (req.readyState) {
                            case 0: //     UNINITIALIZED     open() has not been called yet.
                                notification.call(objContext, 0, 0, '', 0, 0, 0);
                                break;
                            case 1: //     LOADING     send() has not been called yet.
                                notification.call(objContext, 0, 0, '', 0, 0, 0);
                                break;
                            case 2: //     LOADED     send() has been called, and headers and status are available.
                                notification.call(objContext, 0, 0, '', 0, 0, 0);
                                break;
                            case 3: //     INTERACTIVE     Downloading; responseText holds partial data.
                                bytes_transferred = req.responseText.length*2; // One character is two bytes
                                notification.call(objContext, 7, 0, '', 0, bytes_transferred, 0);
                                break;
                            case 4: //     COMPLETED     The operation is complete.
                                if (req.status >= 200 && req.status < 400) {
                                    bytes_transferred = req.responseText.length*2; // One character is two bytes
                                    notification.call(objContext, 8, 0, '', req.status, bytes_transferred, 0);
                                }
                                else if (req.status === 403) { // Fix: These two are finished except for message
                                    notification.call(objContext, 10, 2, '', req.status, 0, 0);
                                }
                                else { // Errors
                                    notification.call(objContext, 9, 2, '', req.status, 0, 0);
                                }
                                break;
                            default:
                                throw 'Unrecognized ready state for file_get_contents()';
                        }
                    }
                }
            }
        }

        if (http_stream) {
            var sendHeaders = http_options.header && http_options.header.split(/\r?\n/);
            var userAgentSent = false;
            for (i=0; i < sendHeaders.length; i++) {
                var sendHeader = sendHeaders[i];
                var breakPos = sendHeader.search(/:\s*/);
                var sendHeaderName = sendHeader.substring(0, breakPos);
                req.setRequestHeader(sendHeaderName, sendHeader.substring(breakPos+1));
                if (sendHeaderName === 'User-Agent') {
                    userAgentSent = true;
                }
            }
            if (!userAgentSent) {
                var user_agent = http_options.user_agent ||
                                                                    (ini.user_agent && ini.user_agent.local_value);
                if (user_agent) {
                    req.setRequestHeader('User-Agent', user_agent);
                }
            }
            content = http_options.content || null;
            /*
            // Presently unimplemented HTTP context options
            var request_fulluri = http_options.request_fulluri || false; // When set to TRUE, the entire URI will be used when constructing the request. (i.e. GET http://www.example.com/path/to/file.html HTTP/1.0). While this is a non-standard request format, some proxy servers require it.
            var max_redirects = http_options.max_redirects || 20; // The max number of redirects to follow. Value 1 or less means that no redirects are followed.
            var protocol_version = http_options.protocol_version || 1.0; // HTTP protocol version
            var timeout = http_options.timeout || (ini.default_socket_timeout && ini.default_socket_timeout.local_value); // Read timeout in seconds, specified by a float
            var ignore_errors = http_options.ignore_errors || false; // Fetch the content even on failure status codes.
            */
        }

        if (flagNames & OPTS.FILE_TEXT) { // Overrides how encoding is treated (regardless of what is returned from the server)
            var content_type = 'text/html';
            if (http_options && http_options['phpjs.override']) { // Fix: Could allow for non-HTTP as well
                content_type = http_options['phpjs.override']; // We use this, e.g., in gettext-related functions if character set
                                                                                                        //   overridden earlier by bind_textdomain_codeset()
            }
            else {
                var encoding = (ini['unicode.stream_encoding'] && ini['unicode.stream_encoding'].local_value) || 'UTF-8';
                if (http_options && http_options.header && (/^content-type:/im).test(http_options.header)) { // We'll assume a content-type expects its own specified encoding if present
                    content_type = http_options.header.match(/^content-type:\s*(.*)$/im)[1]; // We let any header encoding stand
                }
                if (!(/;\s*charset=/).test(content_type)) { // If no encoding
                    content_type += '; charset='+encoding;
                }
            }
            req.overrideMimeType(content_type);
        }
        // Default is FILE_BINARY, but for binary, we apparently deviate from PHP in requiring the flag, since many if not
        //     most people will also want a way to have it be auto-converted into native JavaScript text instead
        else if (flagNames & OPTS.FILE_BINARY) { // Trick at https://developer.mozilla.org/En/Using_XMLHttpRequest to get binary
            req.overrideMimeType('text/plain; charset=x-user-defined');
            // Getting an individual byte then requires:
            // responseText.charCodeAt(x) & 0xFF; // throw away high-order byte (f7) where x is 0 to responseText.length-1 (see notes in our substr())
        }

        if (http_options && http_options['phpjs.sendAsBinary']) { // For content sent in a POST or PUT request (use with file_put_contents()?)
            req.sendAsBinary(content); // In Firefox, only available FF3+
        }
        else {
            req.send(content);
        }

        tmp = req.getAllResponseHeaders();
        if (tmp) {
            tmp = tmp.split('\n');
            for (k=0; k < tmp.length; k++) {
                if (func(tmp[k])) {
                    newTmp.push(tmp[k]);
                }
            }
            tmp = newTmp;
            for (i=0; i < tmp.length; i++) {
                headers[i] = tmp[i];
            }
            this.$http_response_header = headers; // see http://php.net/manual/en/reserved.variables.httpresponseheader.php
        }

        if (offset || maxLen) {
            if (maxLen) {
                return req.responseText.substr(offset || 0, maxLen);
            }
            return req.responseText.substr(offset);
        }
        return req.responseText;
    }
    return false;
};
TOOLBOX.getFormValues = function(form, config)
{
    config = TOOLBOX.mergeConfig(config,{ getEmptyVals : true, getVisibleOnly : false } );
    var formValues = {};
    // helper func
    var _validEle = function(ele)
    {
                      // valid <input elements
        var success =  ( ele.tagName.toLowerCase()=="input" &&
                         (ele.type=="text") ||
                         (ele.type=="hidden") ||
                         (ele.type=="checkbox" && ele.checked) ||
                         (ele.type=="radio" && ele.checked) )
                    // select element
                    || (ele.tagName.toLowerCase()=="select")
                    // textarea
                    || (ele.tagName.toLowerCase()=="textarea");
        return success;
    };
    // loop through elements and build formValues
    var _matches,_collectionName,_collectionValueKey;
    for (var i=0; i<form.elements.length; i++) {
        if ((!config.getVisibleOnly) || DOM_Editor.isElementVisible(form.elements[i])) {
            if ((_matches = form.elements[i].name.match(/\[(.*)\]$/))) {
                // collection
                if (_validEle(form.elements[i])) {
                    _collectionName = form.elements[i].name.replace(_matches[0],'');
                    _collectionValueKey = _matches[1];
                    if (form.elements[i].value || config.getEmptyVals) {
                        if (typeof formValues[_collectionName]=="undefined") {
                            formValues[_collectionName] = {};
                        }
                        formValues[_collectionName][_collectionValueKey] = form.elements[i].value;
                    }
                }
            }
            else if (_validEle(form.elements[i])) {
                if (form.elements[i].name) {
                    if (form.elements[i].value || config.getEmptyVals) {
                        formValues[form.elements[i].name] = form.elements[i].value;
                    }
                }
            }
        }
    }
    return formValues;
};
TOOLBOX.getNextHighestZIndex = function(obj) {
    var highestIndex = 0;
    var currentIndex = 0;
    var elArray = Array();
    if (obj) {
        elArray = obj.getElementsByTagName('*');
    }
    else {
        elArray = document.getElementsByTagName('*');
    }
    for (var i = 0; i < elArray.length; i++) {
        if (elArray[i].currentStyle) {
            currentIndex = parseFloat(elArray[i].currentStyle['zIndex']);
        }
        else if (window.getComputedStyle) {
            currentIndex = parseFloat(document.defaultView.getComputedStyle(elArray[i], null).getPropertyValue('z-index'));
        }
        if (!isNaN(currentIndex) && currentIndex > highestIndex) {
            highestIndex = currentIndex;
        }
    }
    return highestIndex + 1;
};
TOOLBOX.isObject = function(mixed_var){
    if (mixed_var instanceof Array) {
        return false;
    } else {
        return (mixed_var !== null) && (typeof( mixed_var ) == 'object');
    }
};
TOOLBOX.isString = function(mixed_var){
    return (typeof( mixed_var ) == 'string');
}
TOOLBOX.numberFormat = function(number, decimals, dec_point, thousands_sep) {
    var n = !isFinite(+number) ? 0 : +number,
        prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
        sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep,
        dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
        s = '',
        toFixedFix = function (n, prec) {
            var k = Math.pow(10, prec);
            return '' + Math.round(n * k) / k;
        };
    // Fix for IE parseFloat(0.55).toFixed(0) = 0;
    s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');
    if (s[0].length > 3) {
        s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
    }
    if ((s[1] || '').length < prec) {
        s[1] = s[1] || '';
        s[1] += new Array(prec - s[1].length + 1).join('0');
    }
    return s.join(dec);
};

TOOLBOX.toggleVisibility = function(elementId)
{
    var element = document.getElementById(elementId);
    if (element != null && element.style.display == "none") {
        element.style.display = "";
    }
    else if (element != null && element.style.display == "") {
        element.style.display = "none";
    }
}

function helpbox(subject,helptext)
{
	if (typeof helptext=='undefined')
	{
		helptext = subject;
		subject = 'Help';
	}
	if (document.getElementById('helpbox')!=null && typeof document.getElementById('helpbox') != 'undefined')
	{
		if (typeof default_helptext=='undefined')
		{
			default_helpheading = document.getElementById('helpbox_heading').innerHTML;
			default_helptext = document.getElementById('helpbox').innerHTML;
		}
		document.getElementById('helpbox_heading').innerHTML = subject;
		document.getElementById('helpbox').innerHTML = helptext;
	}
}

function nohelpbox()
{
	if (document.getElementById('helpbox')!=null && typeof document.getElementById('helpbox') != 'undefined')
	{
		if (typeof default_helptext=='undefined')
		{
			default_helpheading = 'Help';
			default_helptext = 'Hover your mouse over an area to learn more';
		}
		document.getElementById('helpbox_heading').innerHTML = default_helpheading;
		document.getElementById('helpbox').innerHTML = default_helptext;
	}
}

function text_select_change(show_select, select_field, text_field, change_butt){
	if (show_select){
		select_field.style.display='';
		text_field.style.display='none';
		change_butt.style.display='none';
		select_field.disabled=false;
		text_field.disabled=true;
	} else {
		select_field.style.display='none';
		text_field.style.display='';
		change_butt.style.display='';
		select_field.disabled=true;
		text_field.disabled=false;
	}
}

function get_checked_radioObj_value(radioObj){
	if(!radioObj)
		return "";
	var radioLength = radioObj.length;
	if(radioLength == undefined)
		if(radioObj.checked)
			return radioObj.value;
		else
			return "";
	for(var i = 0; i < radioLength; i++) {
		if(radioObj[i].checked) {
			return radioObj[i].value;
		}
	}
	return "";
}

function set_radioObj_value(radioObj,value)
{
	if(!radioObj)
		return "";
	var radioLength = radioObj.length;
	if(radioLength == undefined)
	{
		radioObj = [radioObj];
		radioLength = 1;
	}
	for(var i = 0; i < radioLength; i++) {
		(radioObj[i].value==value);
		radioObj[i].checked = (radioObj[i].value==value);
	}
	return "";
}

function multiple_select_replace(obj)
{
    var ms_div = DOM_Editor.createElement({'type':'div',
                                                     'attr':{'class':'MultipleSelect'},
                                                     'style':{'display':'none'}
                                          });
    var ms_ul = DOM_Editor.createElement({type:'ul'})
    ms_div.appendChild(ms_ul);
    var obj_options = obj.getElementsByTagName('*');
    for (var i=0; i<obj_options.length; i++) {
        if (obj_options[i].tagName.toLowerCase()=='optgroup') {
            // opt group - heading
            var li = DOM_Editor.createElement({type:'li',
                                               attr:{'class':'optgroup',
                                                     'innerHTML':obj_options[i].label}
                                                });
            ms_ul.appendChild(li);
        }
        else {
            if(obj_options[i].text!='') {
                var li = DOM_Editor.createElement({type:'li',
                                          children:[
                                              {'type':'input',
                                               attr:{type:'checkbox',
                                                     name:obj.name,
                                                     id:obj.name+'_MS_'+i,
                                                     value:obj_options[i].value,
                                                     checked:obj_options[i].selected}
                                              },
                                              {'type':'label',
                                               attr:{'for':obj.name+'_MS_'+i,
                                                     innerHTML:obj_options[i].text}
                                              }
                                          ]
                                        });
                if (obj_options[i].selected) {
                    DOM_Editor.addClass(li,'checked');
                    // for IE, which deserves to burn in hell
                    li.childNodes[0].checked = true;
                }
                // add on onclick to the checkbox
                YAHOO.util.Event.addListener(li.childNodes[0],'click',function(){
                    if (this.checked) {
                        DOM_Editor.addClass(this.parentNode,'checked');
                    }
                    else {
                        DOM_Editor.removeClass(this.parentNode,'checked');
                    }
                });
                ms_ul.appendChild(li);
            }
        }
    }
    // replace obj with the new object
    obj.parentNode.insertBefore(ms_div,obj);
    obj.parentNode.removeChild(obj);
    ms_div.style.display = '';
    return obj;
}

DOM_Editor = function() {}; // a static object
DOM_Editor.createElement = function (ele)
{
    var created_ele;
    if (typeof ele.type == 'undefined') {
        created_ele = false;
    }
    else if (ele.type=='__ELEMENT__') {
        created_ele = this._create_missing_element(ele.id);
    }
    else {
        var created_ele = document.createElement(ele.type);
        if (typeof ele.attr == 'object') {
            for (var i in ele.attr) {
                if (i=='innerHTML') {
                    created_ele.innerHTML = ele.attr[i];
                }
                else if (i=='checked') {
                    created_ele.checked = ele.checked;
                }
                else if (i=='class') {
                    created_ele.setAttribute('class',ele.attr[i]);
                    created_ele.setAttribute('className',ele.attr[i]);
                }
                else if (i=='for') {
                    created_ele.htmlFor = ele.attr[i];
                }
                else {
                    created_ele.setAttribute(i,ele.attr[i]);
                }
            }
        }
        if (typeof ele.style == 'object') {
            for (var i in ele.style) {
                created_ele.style[i]= ele.style[i];
            }
        }
        if (typeof ele.children == 'object') {
            for (var j=0; j<ele.children.length; j++) {
                var new_child = DOM_Editor.createElement(ele.children[j]);
                created_ele.appendChild(new_child);
            }
        }
    }
    return created_ele;
};

DOM_Editor.addClass = function(ele,className) {
    YAHOO.util.Dom.addClass(ele,className);
};

DOM_Editor.removeClass = function(ele,className) {
    YAHOO.util.Dom.removeClass(ele,className);
};

DOM_Editor.addCSSRule = function(selector, declaration) {
    // test for IE
    var ua = navigator.userAgent.toLowerCase();
    var isIE = (/msie/.test(ua)) && !(/opera/.test(ua)) && (/win/.test(ua));

    // create the style node for all browsers
    var style_node = document.createElement("style");
    style_node.setAttribute("type", "text/css");
    style_node.setAttribute("media", "screen");

    // append a rule for good browsers
    if (!isIE) {
        style_node.appendChild(document.createTextNode(selector + " {" + declaration + "}"));
    }

    // append the style node
    document.getElementsByTagName("head")[0].appendChild(style_node);

    // use alternative methods for IE
    if (isIE && document.styleSheets && document.styleSheets.length > 0) {
            var last_style_node = document.styleSheets[document.styleSheets.length - 1];
            if (typeof(last_style_node.addRule) == "object") last_style_node.addRule(selector, declaration);
    }
};

DOM_Editor.uniqid = function(prefix) {
    var newDate = new Date();
    var new_id = null;
    var count = 0;
    do
    {
        new_id = prefix + newDate.getTime() + count;
        count ++;
    } while (document.getElementById(new_id) != null);
    return new_id;
};

DOM_Editor.getFormFields = function(frm) {
    var fields = [];
    for (var i=0; i<frm.elements.length; i++) {
        if (-1===fields.inArray(frm.elements[i].name)) {
            fields.push(frm.elements[i].name);
        }
    }
    return fields;
};

DOM_Editor.getFormElement = function(ele_name,frm) {
    if (typeof frm[ele_name] != 'undefined') {
        return frm[ele_name];
    }
    else {
        // probably IE7...
        var elements = [];
        for (var i=0; i<frm.elements.length; i++) {
            if (frm.elements[i].name == ele_name) {
                elements.push(frm.elements[i]);
            }
        }
        if (elements.length==0) { // not found
            return false;
        }
        else if (elements.length==1) {
            return elements[0]; // just one
        }
        else {
            return elements; // multiple
        }
    }
    return false;
};

DOM_Editor.createSelectBox = function(name,options,selected,config)
{
    if (typeof config=='undefined') {
        config = {};
    }
    config = TOOLBOX.mergeConfig(config,{'class':'formDrop'});
    var selectBox = DOM_Editor.createElement({'type':'select',
                                              'attr':{'name':name,
                                                      'class':config['class']}});
    var selectedIndex=false,o;
    for (var i=0; i<options.length; i++) {
        o = new Option(options[i].text,options[i].value,false,false);
		o.value = options[i].value;
        o.selected = (options[i].value==selected);
        o.defaultSelected = false;
        selectedIndex = i+1;
        selectBox.options[selectBox.options.length] = (o);
    }
	selectBox.setAttribute('selectedIndex', selectedIndex);
    return selectBox;
};
DOM_Editor.isElementVisible = function(ele)
{
    if (ele==null || typeof ele.style == "undefined") { return true; }
    return ele.style.display!="none" && ele.style.visibility!="hidden"
           && (!ele.parentNode || DOM_Editor.isElementVisible(ele.parentNode));
};

function urlencode(str) {
    str = escape(str);
    str = str.replace('+', '%2B');
    str = str.replace('%20', '+');
    str = str.replace('*', '%2A');
    str = str.replace('/', '%2F');
    str = str.replace('@', '%40');
    str = str.replace('&', '%26');
    str = str.replace('=', '%3D');
    str = str.replace('[', '%5B');
    str = str.replace(']', '%5D');
    return str;
}
function urldecode (str) {
    return decodeURIComponent(str.replace(/\+/g, '%20'));
}

function stripTags(str, allowed_tags)
{
    var key = '', allowed = false;
    var matches = [];
    var allowed_array = [];
    var allowed_tag = '';
    var i = 0;
    var k = '';
    var html = '';
    var replacer = function(search, replace, str) {
        return str.split(search).join(replace);
    };
    if (allowed_tags) {
        allowed_array = allowed_tags.match(/([a-zA-Z]+)/gi);
    }
    str += '';
    matches = str.match(/(<\/?[\S][^>]*>)/gi);
    for (key in matches) {
        if (isNaN(key)) { continue; } // IE7 Hack
        html = matches[key].toString();
        allowed = false;
        for (k in allowed_array) {
            allowed_tag = allowed_array[k];
            i = -1;
            if (i != 0) { i = html.toLowerCase().indexOf('<'+allowed_tag+'>');}
            if (i != 0) { i = html.toLowerCase().indexOf('<'+allowed_tag+' ');}
            if (i != 0) { i = html.toLowerCase().indexOf('</'+allowed_tag)   ;}
            if (i == 0) {
                allowed = true;
                break;
            }
        }
        if (!allowed) {
            str = replacer(html, "", str); // Custom replace. No regexing
        }
    }
    return str;
};

// sprintf
eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('u={N:O(){m(K C=="P"){q w}m(C.r<1){q w}m(K C[0]!="Y"){q w}m(K Q=="P"){q w}n a=C[0];n b=H Q(/(%([%]|(\\-)?(\\+|\\Z)?(0)?(\\d+)?(\\.(\\d)?)?([10])))/g);n c=H L();n d=H L();n e=0;n f=0;n g=0;n h=0;n j=\'\';n k=w;11(k=b.12(a)){m(k[9]){e+=1}f=h;g=b.R-k[0].r;d[d.r]=a.M(f,g);h=b.R;c[c.r]={S:k[0],T:k[3]?F:U,y:k[4]||\'\',I:k[5]||\' \',V:k[6]||0,G:k[8],v:k[9]||\'%\',W:B(C[e])<0?F:U,7:z(C[e])}}d[d.r]=a.M(h);m(c.r==0){q a}m((C.r-1)<e){q w}n l=w;n k=w;n i=w;13(i=0;i<c.r;i++){m(c[i].v==\'%\'){t=\'%\'}p m(c[i].v==\'b\'){c[i].7=z(D.E(B(c[i].7)).J(2));t=u.A(c[i],F)}p m(c[i].v==\'c\'){c[i].7=z(z.14(B(D.E(B(c[i].7)))));t=u.A(c[i],F)}p m(c[i].v==\'d\'){c[i].7=z(D.E(B(c[i].7)));t=u.A(c[i])}p m(c[i].v==\'f\'){c[i].7=z(D.E(15(c[i].7)).17(c[i].G?c[i].G:6));t=u.A(c[i])}p m(c[i].v==\'o\'){c[i].7=z(D.E(B(c[i].7)).J(8));t=u.A(c[i])}p m(c[i].v==\'s\'){c[i].7=c[i].7.M(0,c[i].G?c[i].G:c[i].7.r);t=u.A(c[i],F)}p m(c[i].v==\'x\'){c[i].7=z(D.E(B(c[i].7)).J(16));t=u.A(c[i])}p m(c[i].v==\'X\'){c[i].7=z(D.E(B(c[i].7)).J(16));t=u.A(c[i]).18()}p{t=c[i].S}j+=d[i];j+=t}j+=d[i];q j},A:O(a,b){m(b){a.y=\'\'}p{a.y=a.W?\'-\':a.y}n l=a.V-a.7.r+1-a.y.r;n c=H L(l<0?0:l).19(a.I);m(!a.T){m(a.I=="0"||b){q a.y+c+a.7}p{q c+a.y+a.7}}p{m(a.I=="0"||b){q a.y+a.7+c.1a(/0/g,\' \')}p{q a.y+a.7+c}}}};1b=u.N;',62,74,'|||||||argument|||||||||||||||if|var||else|return|length||substitution|sprintfWrapper|code|null||sign|String|convert|parseInt|arguments|Math|abs|true|precision|new|pad|toString|typeof|Array|substring|init|function|undefined|RegExp|lastIndex|match|left|false|min|negative||string|x20|bcdfosxX|while|exec|for|fromCharCode|parseFloat||toFixed|toUpperCase|join|replace|sprintf'.split('|'),0,{}))

// extend String
String.prototype.camelCaseToArray = function() {
    // Preceed Uppercase (or sets of) with commas then remove any leading comma
    var Delimed = this.replace(/([A-Z]+)/g, ",$1").replace(/^,/, "");
    // Split the string on commas and return the array
    return Delimed.split(",");
};

String.prototype.camelCaseToString = function() {
    return this.camelCaseToArray().join(' ');
};

String.prototype.ucfirst = function() {
    return (this+'').replace(/^(.)|\s(.)/g, function ( $1 ) {return $1.toUpperCase( );} );
};

String.prototype.strrpos = function(needle, offset) {
    var i = (this+'').lastIndexOf( needle, offset ); // returns -1
    return i >= 0 ? i : false;
};

String.prototype.parseUrl = function(component) {
    var  o   = {
        strictMode: false,
        key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
        q:   {
            name:   "queryKey",
            parser: /(?:^|&)([^&=]*)=?([^&]*)/g
        },
        parser: {
            strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
            loose:  /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/\/?)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ // Added one optional slash to post-protocol to catch file:/// (should restrict this)
        }
    };

    var m   = o.parser[o.strictMode ? "strict" : "loose"].exec(this),
    uri = {},
    i   = 14;
    while (i--) {uri[o.key[i]] = m[i] || "";}
    // Uncomment the following to use the original more detailed (non-PHP) script
    /*
        uri[o.q.name] = {};
        uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
        if ($1) uri[o.q.name][$1] = $2;
        });
        return uri;
    */

    switch (component) {
        case 'PHP_URL_SCHEME':
            return uri.protocol;
        case 'PHP_URL_HOST':
            return uri.host;
        case 'PHP_URL_PORT':
            return uri.port;
        case 'PHP_URL_USER':
            return uri.user;
        case 'PHP_URL_PASS':
            return uri.password;
        case 'PHP_URL_PATH':
            return uri.path;
        case 'PHP_URL_QUERY':
            return uri.query;
        case 'PHP_URL_FRAGMENT':
            return uri.anchor;
        default:
            var retArr = {};
            if (uri.protocol !== '') {retArr.scheme=uri.protocol;}
            if (uri.host !== '') {retArr.host=uri.host;}
            if (uri.port !== '') {retArr.port=uri.port;}
            if (uri.user !== '') {retArr.user=uri.user;}
            if (uri.password !== '') {retArr.pass=uri.password;}
            if (uri.path !== '') {retArr.path=uri.path;}
            if (uri.query !== '') {retArr.query=uri.query;}
            if (uri.anchor !== '') {retArr.fragment=uri.anchor;}
            return retArr;
    }
};

String.prototype.parseStr = function (){
    var array = {};

    var glue1 = '=', glue2 = '&', array2 = String(this).split(glue2),
    i, j, chr, tmp, key, value, bracket, keys, evalStr,
    fixStr = function (str) {
        return str.urldecode().replace(/([\\"'])/g, '\\$1').replace(/\n/g, '\\n').replace(/\r/g, '\\r');
    };

    for (i = 0; i < array2.length; i++) {
        if (!array2[i].match(/^\s*$/)) {
            tmp = array2[i].split(glue1);
            if (tmp.length < 2) {
                tmp = [tmp, ''];
            }
            key   = fixStr(tmp[0]);
            value = fixStr(tmp[1]);

            while (key.charAt(0) === ' ') {
                key = key.substr(1);
            }
            if (key.indexOf('\0') !== -1) {
                key = key.substr(0, key.indexOf('\0'));
            }
            if (key && key.charAt(0) !== '[') {
                keys    = [];
                bracket = 0;
                for (j = 0; j < key.length; j++) {
                    if (key.charAt(j) === '[' && !bracket) {
                        bracket = j + 1;
                    }
                    else if (key.charAt(j) === ']') {
                        if (bracket) {
                            if (!keys.length) {
                                keys.push(key.substr(0, bracket - 1));
                            }
                            keys.push(key.substr(bracket, j - bracket));
                            bracket = 0;
                            if (key.charAt(j + 1) !== '[') {
                                break;
                            }
                        }
                    }
                }
                if (!keys.length) {
                    keys = [key];
                }
                for (j = 0; j < keys[0].length; j++) {
                    chr = keys[0].charAt(j);
                    if (chr === ' ' || chr === '.' || chr === '[') {
                        keys[0] = keys[0].substr(0, j) + '_' + keys[0].substr(j + 1);
                    }
                    if (chr === '[') {
                        break;
                    }
                }
                evalStr = 'array';
                for (j = 0; j < keys.length; j++) {
                    key = keys[j];
                    if ((key !== '' && key !== ' ') || j === 0) {
                        key = "'" + key + "'";
                    }
                    else {
                        key = eval(evalStr + '.push([]);') - 1;
                    }
                    evalStr += '[' + key + ']';
                    if (j !== keys.length - 1 && eval('typeof ' + evalStr) === 'undefined') {
                        eval(evalStr + ' = [];');
                    }
                }
                evalStr += " = '" + value + "';\n";
                eval(evalStr);
            }
        }
    }
    return array;
};

String.prototype.urldecode = function() {
    return urldecode(this);
};

String.prototype.repeat = function (multiplier)
{
    return new Array(multiplier + 1).join(this.toString());
}

Array.prototype.httpBuildQuery = function( numeric_prefix, key ) {
    var is_int = function (n) {return n.toString().match(/^[0-9]+$/);};
    var is_array = function(v) {return (v.constructor.toString().indexOf("Array") >= 0)};
    var is_object = function(v) {return (typeof(v)=="object");};
    var formdata = this;
	numeric_prefix = (typeof numeric_prefix =="undefined") ? null : numeric_prefix;
	key = (typeof(key)=="undefined") ? null : key;
	var res = new Array();
    var add_to_res;
	for (var k in formdata) {
		var v = formdata[k];
		if (typeof(v)=='function') continue; // skip this, it's not what we want
		var tmp_key = encodeURI( is_int(k) ? new Number(numeric_prefix)+new Number(k) : k);
		if (key) tmp_key = key+'['+tmp_key+']';
		add_to_res  = ( ( is_array(v) || is_object(v) ) ? http_build_query(v, key, tmp_key) : tmp_key+"="+escape(v) );
		res.push(add_to_res);
	}
	var separator = '&';
	return res.join(separator);
};

function http_build_query (formdata, numeric_prefix, arg_separator) {
    var value, key, tmp = [];
    var urlencode = function(str) {
        str = (str+'').toString();
        return encodeURIComponent(str).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28')
                                    .replace(/\)/g, '%29').replace(/\*/g, '%2A').replace(/%20/g, '+');
    }
    var _http_build_query_helper = function (key, val, arg_separator) {
        var k, tmp = [];
        if (val === true) {
            val = "1";
        } else if (val === false) {
            val = "0";
        }
        if (val !== null && typeof(val) === "object") {
            for (k in val) {
                if (val[k] !== null) {
                    var valPush = _http_build_query_helper(key + "[" + k + "]", val[k], arg_separator);
                    if (valPush) {
                        tmp.push(valPush);
                    }
                }
            }
            return tmp.join(arg_separator);
        } else if (typeof(val) !== "function") {
            return urlencode(key) + "=" + urlencode(val);
        } else {
            // throw new Error('There was an error processing for http_build_query().');
            return false;
        }
    };

    if (!arg_separator) {
        arg_separator = "&";
    }
    for (key in formdata) {
        value = formdata[key];
        if (numeric_prefix && !isNaN(key)) {
            key = String(numeric_prefix) + key;
        }
        var valPush = _http_build_query_helper(key, value, arg_separator);
        if (valPush) {
            tmp.push(valPush);
        }
    }

    return tmp.join(arg_separator);
}

Array.prototype.inArray = function(val) {
    for (var i in this) {if (this[i] === val) return i;}
    return -1;
};

Array.prototype.remove=function(s) {
	for (i=0; i < this.length; i++) {
		if (s == this[i]) {
            this.splice(i, 1);
        }
	}
};

Array.prototype.in_array = Array.prototype.inArray;

Date.prototype.formatDate = function(format) {
    var timestamp = this.getTime()/1000;
    var that = this;
    var jsdate=(
        (typeof(timestamp) == 'undefined') ? new Date() : // Not provided
        (typeof(timestamp) == 'number') ? new Date(timestamp*1000) : // UNIX timestamp
        new Date(timestamp) // Javascript Date()
    ); // , tal=[]
    var pad = function (n, c){
        if ( (n = n + "").length < c ) {
            return new Array(++c - n.length).join("0") + n;
        } else {
            return n;
        }
    };
    var _dst = function (t) {
        // Calculate Daylight Saving Time (derived from gettimeofday() code)
        var dst=0;
        var jan1 = new Date(t.getFullYear(), 0, 1, 0, 0, 0, 0);  // jan 1st
        var june1 = new Date(t.getFullYear(), 6, 1, 0, 0, 0, 0); // june 1st
        var temp = jan1.toUTCString();
        var jan2 = new Date(temp.slice(0, temp.lastIndexOf(' ')-1));
        temp = june1.toUTCString();
        var june2 = new Date(temp.slice(0, temp.lastIndexOf(' ')-1));
        var std_time_offset = (jan1 - jan2) / (1000 * 60 * 60);
        var daylight_time_offset = (june1 - june2) / (1000 * 60 * 60);

        if (std_time_offset === daylight_time_offset) {
            dst = 0; // daylight savings time is NOT observed
        } else {
            // positive is southern, negative is northern hemisphere
            var hemisphere = std_time_offset - daylight_time_offset;
            if (hemisphere >= 0) {
                std_time_offset = daylight_time_offset;
            }
            dst = 1; // daylight savings time is observed
        }
        return dst;
    };
    var ret = '';
    var txt_weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday",
        "Thursday", "Friday", "Saturday"];
    var txt_ordin = {1: "st", 2: "nd", 3: "rd", 21: "st", 22: "nd", 23: "rd", 31: "st"};
    var txt_months =  ["", "January", "February", "March", "April",
        "May", "June", "July", "August", "September", "October", "November",
        "December"];

    var f = {
        // Day
            d: function (){
                return pad(f.j(), 2);
            },
            D: function (){
                var t = f.l();
                return t.substr(0,3);
            },
            j: function (){
                return jsdate.getDate();
            },
            l: function (){
                return txt_weekdays[f.w()];
            },
            N: function (){
                //return f.w() + 1;
                return f.w() ? f.w() : 7;
            },
            S: function (){
                return txt_ordin[f.j()] ? txt_ordin[f.j()] : 'th';
            },
            w: function (){
                return jsdate.getDay();
            },
            z: function (){
                return (jsdate - new Date(jsdate.getFullYear() + "/1/1")) / 864e5 >> 0;
            },

        // Week
            W: function (){

                var a = f.z(), b = 364 + f.L() - a;
                var nd2, nd = (new Date(jsdate.getFullYear() + "/1/1").getDay() || 7) - 1;

                if (b <= 2 && ((jsdate.getDay() || 7) - 1) <= 2 - b){
                    return 1;
                }
                if (a <= 2 && nd >= 4 && a >= (6 - nd)){
                    nd2 = new Date(jsdate.getFullYear() - 1 + "/12/31");
                    return that.date("W", Math.round(nd2.getTime()/1000));
                }

                var w = (1 + (nd <= 3 ? ((a + nd) / 7) : (a - (7 - nd)) / 7) >> 0);

                return (w ? w : 53);
            },

        // Month
            F: function (){
                return txt_months[f.n()];
            },
            m: function (){
                return pad(f.n(), 2);
            },
            M: function (){
                var t = f.F();
                return t.substr(0,3);
            },
            n: function (){
                return jsdate.getMonth() + 1;
            },
            t: function (){
                var n;
                if ( (n = jsdate.getMonth() + 1) == 2 ){
                    return 28 + f.L();
                }
                if ( n & 1 && n < 8 || !(n & 1) && n > 7 ){
                    return 31;
                }
                return 30;
            },

        // Year
            L: function (){
                var y = f.Y();
                return (!(y & 3) && (y % 1e2 || !(y % 4e2))) ? 1 : 0;
            },
            o: function (){
                if (f.n() === 12 && f.W() === 1) {
                    return jsdate.getFullYear()+1;
                }
                if (f.n() === 1 && f.W() >= 52) {
                    return jsdate.getFullYear()-1;
                }
                return jsdate.getFullYear();
            },
            Y: function (){
                return jsdate.getFullYear();
            },
            y: function (){
                return (jsdate.getFullYear() + "").slice(2);
            },

        // Time
            a: function (){
                return jsdate.getHours() > 11 ? "pm" : "am";
            },
            A: function (){
                return f.a().toUpperCase();
            },
            B: function (){
                // peter paul koch:
                var off = (jsdate.getTimezoneOffset() + 60)*60;
                var theSeconds = (jsdate.getHours() * 3600) +
                                 (jsdate.getMinutes() * 60) +
                                  jsdate.getSeconds() + off;
                var beat = Math.floor(theSeconds/86.4);
                if (beat > 1000) {
                    beat -= 1000;
                }
                if (beat < 0) {
                    beat += 1000;
                }
                if ((String(beat)).length == 1) {
                    beat = "00"+beat;
                }
                if ((String(beat)).length == 2) {
                    beat = "0"+beat;
                }
                return beat;
            },
            g: function (){
                return jsdate.getHours() % 12 || 12;
            },
            G: function (){
                return jsdate.getHours();
            },
            h: function (){
                return pad(f.g(), 2);
            },
            H: function (){
                return pad(jsdate.getHours(), 2);
            },
            i: function (){
                return pad(jsdate.getMinutes(), 2);
            },
            s: function (){
                return pad(jsdate.getSeconds(), 2);
            },
            u: function (){
                return pad(jsdate.getMilliseconds()*1000, 6);
            },

        // Timezone
            e: function () {
                return 'UTC';
            },
            I: function (){
                return _dst(jsdate);
            },
            O: function (){
               var t = pad(Math.abs(jsdate.getTimezoneOffset()/60*100), 4);
               t = (jsdate.getTimezoneOffset() > 0) ? "-"+t : "+"+t;
               return t;
            },
            P: function (){
                var O = f.O();
                return (O.substr(0, 3) + ":" + O.substr(3, 2));
            },
            T: function () {
                return 'UTC';
            },
            Z: function (){
               return -jsdate.getTimezoneOffset()*60;
            },

        // Full Date/Time
            c: function (){
                return f.Y() + "-" + f.m() + "-" + f.d() + "T" + f.h() + ":" + f.i() + ":" + f.s() + f.P();
            },
            r: function (){
                return f.D()+', '+f.d()+' '+f.M()+' '+f.Y()+' '+f.H()+':'+f.i()+':'+f.s()+' '+f.O();
            },
            U: function (){
                return Math.round(jsdate.getTime()/1000);
            }
    };

    return format.replace(/[\\]?([a-zA-Z])/g, function (t, s){
        if ( t!=s ){
            // escaped
            ret = s;
        } else if (f[s]){
            // a date function exists
            ret = f[s]();
        } else {
            // nothing special
            ret = s;
        }
        return ret;
    });
};

function get_html_translation_table(table, quote_style)
{
    var entities = {}, hash_map = {}, decimal = 0, symbol = '';
    var constMappingTable = {}, constMappingQuoteStyle = {};
    var useTable = {}, useQuoteStyle = {};

    // Translate arguments
    constMappingTable[0]      = 'HTML_SPECIALCHARS';
    constMappingTable[1]      = 'HTML_ENTITIES';
    constMappingQuoteStyle[0] = 'ENT_NOQUOTES';
    constMappingQuoteStyle[2] = 'ENT_COMPAT';
    constMappingQuoteStyle[3] = 'ENT_QUOTES';

    useTable       = !isNaN(table) ? constMappingTable[table] : table ? table.toUpperCase() : 'HTML_SPECIALCHARS';
    useQuoteStyle = !isNaN(quote_style) ? constMappingQuoteStyle[quote_style] : quote_style ? quote_style.toUpperCase() : 'ENT_COMPAT';

    if (useTable !== 'HTML_SPECIALCHARS' && useTable !== 'HTML_ENTITIES') {
        throw new Error("Table: "+useTable+' not supported');
        // return false;
    }

    entities['38'] = '&amp;';
    if (useTable === 'HTML_ENTITIES') {
        entities['160'] = '&nbsp;';
        entities['161'] = '&iexcl;';
        entities['162'] = '&cent;';
        entities['163'] = '&pound;';
        entities['164'] = '&curren;';
        entities['165'] = '&yen;';
        entities['166'] = '&brvbar;';
        entities['167'] = '&sect;';
        entities['168'] = '&uml;';
        entities['169'] = '&copy;';
        entities['170'] = '&ordf;';
        entities['171'] = '&laquo;';
        entities['172'] = '&not;';
        entities['173'] = '&shy;';
        entities['174'] = '&reg;';
        entities['175'] = '&macr;';
        entities['176'] = '&deg;';
        entities['177'] = '&plusmn;';
        entities['178'] = '&sup2;';
        entities['179'] = '&sup3;';
        entities['180'] = '&acute;';
        entities['181'] = '&micro;';
        entities['182'] = '&para;';
        entities['183'] = '&middot;';
        entities['184'] = '&cedil;';
        entities['185'] = '&sup1;';
        entities['186'] = '&ordm;';
        entities['187'] = '&raquo;';
        entities['188'] = '&frac14;';
        entities['189'] = '&frac12;';
        entities['190'] = '&frac34;';
        entities['191'] = '&iquest;';
        entities['192'] = '&Agrave;';
        entities['193'] = '&Aacute;';
        entities['194'] = '&Acirc;';
        entities['195'] = '&Atilde;';
        entities['196'] = '&Auml;';
        entities['197'] = '&Aring;';
        entities['198'] = '&AElig;';
        entities['199'] = '&Ccedil;';
        entities['200'] = '&Egrave;';
        entities['201'] = '&Eacute;';
        entities['202'] = '&Ecirc;';
        entities['203'] = '&Euml;';
        entities['204'] = '&Igrave;';
        entities['205'] = '&Iacute;';
        entities['206'] = '&Icirc;';
        entities['207'] = '&Iuml;';
        entities['208'] = '&ETH;';
        entities['209'] = '&Ntilde;';
        entities['210'] = '&Ograve;';
        entities['211'] = '&Oacute;';
        entities['212'] = '&Ocirc;';
        entities['213'] = '&Otilde;';
        entities['214'] = '&Ouml;';
        entities['215'] = '&times;';
        entities['216'] = '&Oslash;';
        entities['217'] = '&Ugrave;';
        entities['218'] = '&Uacute;';
        entities['219'] = '&Ucirc;';
        entities['220'] = '&Uuml;';
        entities['221'] = '&Yacute;';
        entities['222'] = '&THORN;';
        entities['223'] = '&szlig;';
        entities['224'] = '&agrave;';
        entities['225'] = '&aacute;';
        entities['226'] = '&acirc;';
        entities['227'] = '&atilde;';
        entities['228'] = '&auml;';
        entities['229'] = '&aring;';
        entities['230'] = '&aelig;';
        entities['231'] = '&ccedil;';
        entities['232'] = '&egrave;';
        entities['233'] = '&eacute;';
        entities['234'] = '&ecirc;';
        entities['235'] = '&euml;';
        entities['236'] = '&igrave;';
        entities['237'] = '&iacute;';
        entities['238'] = '&icirc;';
        entities['239'] = '&iuml;';
        entities['240'] = '&eth;';
        entities['241'] = '&ntilde;';
        entities['242'] = '&ograve;';
        entities['243'] = '&oacute;';
        entities['244'] = '&ocirc;';
        entities['245'] = '&otilde;';
        entities['246'] = '&ouml;';
        entities['247'] = '&divide;';
        entities['248'] = '&oslash;';
        entities['249'] = '&ugrave;';
        entities['250'] = '&uacute;';
        entities['251'] = '&ucirc;';
        entities['252'] = '&uuml;';
        entities['253'] = '&yacute;';
        entities['254'] = '&thorn;';
        entities['255'] = '&yuml;';
    }

    if (useQuoteStyle !== 'ENT_NOQUOTES') {
        entities['34'] = '&quot;';
    }
    if (useQuoteStyle === 'ENT_QUOTES') {
        entities['39'] = '&#39;';
    }
    entities['60'] = '&lt;';
    entities['62'] = '&gt;';

    // ascii decimals to real symbols
    for (decimal in entities) {
        symbol = String.fromCharCode(decimal);
        hash_map[symbol] = entities[decimal];
    }

    return hash_map;
}

function htmlentities(string, quote_style)
{
    var hash_map = {}, symbol = '', tmp_str = '', entity = '';
    tmp_str = string.toString();

    if (false === (hash_map = get_html_translation_table('HTML_ENTITIES', quote_style))) {
        return false;
    }
    hash_map["'"] = '&#039;';
    for (symbol in hash_map) {
        entity = hash_map[symbol];
        tmp_str = tmp_str.split(symbol).join(entity);
    }

    return tmp_str;
}

function md5(str)
{
    var xl;

    var rotateLeft = function (lValue, iShiftBits) {
        return (lValue<<iShiftBits) | (lValue>>>(32-iShiftBits));
    };

    var addUnsigned = function (lX,lY) {
        var lX4,lY4,lX8,lY8,lResult;
        lX8 = (lX & 0x80000000);
        lY8 = (lY & 0x80000000);
        lX4 = (lX & 0x40000000);
        lY4 = (lY & 0x40000000);
        lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
        if (lX4 & lY4) {
            return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
        }
        if (lX4 | lY4) {
            if (lResult & 0x40000000) {
                return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
            } else {
                return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
            }
        } else {
            return (lResult ^ lX8 ^ lY8);
        }
    };

    var _F = function (x,y,z) {return (x & y) | ((~x) & z);};
    var _G = function (x,y,z) {return (x & z) | (y & (~z));};
    var _H = function (x,y,z) {return (x ^ y ^ z);};
    var _I = function (x,y,z) {return (y ^ (x | (~z)));};

    var _FF = function (a,b,c,d,x,s,ac) {
        a = addUnsigned(a, addUnsigned(addUnsigned(_F(b, c, d), x), ac));
        return addUnsigned(rotateLeft(a, s), b);
    };

    var _GG = function (a,b,c,d,x,s,ac) {
        a = addUnsigned(a, addUnsigned(addUnsigned(_G(b, c, d), x), ac));
        return addUnsigned(rotateLeft(a, s), b);
    };

    var _HH = function (a,b,c,d,x,s,ac) {
        a = addUnsigned(a, addUnsigned(addUnsigned(_H(b, c, d), x), ac));
        return addUnsigned(rotateLeft(a, s), b);
    };

    var _II = function (a,b,c,d,x,s,ac) {
        a = addUnsigned(a, addUnsigned(addUnsigned(_I(b, c, d), x), ac));
        return addUnsigned(rotateLeft(a, s), b);
    };

    var convertToWordArray = function (str) {
        var lWordCount;
        var lMessageLength = str.length;
        var lNumberOfWords_temp1=lMessageLength + 8;
        var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64;
        var lNumberOfWords = (lNumberOfWords_temp2+1)*16;
        var lWordArray=new Array(lNumberOfWords-1);
        var lBytePosition = 0;
        var lByteCount = 0;
        while ( lByteCount < lMessageLength ) {
            lWordCount = (lByteCount-(lByteCount % 4))/4;
            lBytePosition = (lByteCount % 4)*8;
            lWordArray[lWordCount] = (lWordArray[lWordCount] | (str.charCodeAt(lByteCount)<<lBytePosition));
            lByteCount++;
        }
        lWordCount = (lByteCount-(lByteCount % 4))/4;
        lBytePosition = (lByteCount % 4)*8;
        lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80<<lBytePosition);
        lWordArray[lNumberOfWords-2] = lMessageLength<<3;
        lWordArray[lNumberOfWords-1] = lMessageLength>>>29;
        return lWordArray;
    };

    var wordToHex = function (lValue) {
        var wordToHexValue="",wordToHexValue_temp="",lByte,lCount;
        for (lCount = 0;lCount<=3;lCount++) {
            lByte = (lValue>>>(lCount*8)) & 255;
            wordToHexValue_temp = "0" + lByte.toString(16);
            wordToHexValue = wordToHexValue + wordToHexValue_temp.substr(wordToHexValue_temp.length-2,2);
        }
        return wordToHexValue;
    };

    var x=[],
        k,AA,BB,CC,DD,a,b,c,d,
        S11=7, S12=12, S13=17, S14=22,
        S21=5, S22=9 , S23=14, S24=20,
        S31=4, S32=11, S33=16, S34=23,
        S41=6, S42=10, S43=15, S44=21;

    str = utf8_encode(str);
    x = convertToWordArray(str);
    a = 0x67452301;b = 0xEFCDAB89;c = 0x98BADCFE;d = 0x10325476;

    xl = x.length;
    for (k=0;k<xl;k+=16) {
        AA=a;BB=b;CC=c;DD=d;
        a=_FF(a,b,c,d,x[k+0], S11,0xD76AA478);
        d=_FF(d,a,b,c,x[k+1], S12,0xE8C7B756);
        c=_FF(c,d,a,b,x[k+2], S13,0x242070DB);
        b=_FF(b,c,d,a,x[k+3], S14,0xC1BDCEEE);
        a=_FF(a,b,c,d,x[k+4], S11,0xF57C0FAF);
        d=_FF(d,a,b,c,x[k+5], S12,0x4787C62A);
        c=_FF(c,d,a,b,x[k+6], S13,0xA8304613);
        b=_FF(b,c,d,a,x[k+7], S14,0xFD469501);
        a=_FF(a,b,c,d,x[k+8], S11,0x698098D8);
        d=_FF(d,a,b,c,x[k+9], S12,0x8B44F7AF);
        c=_FF(c,d,a,b,x[k+10],S13,0xFFFF5BB1);
        b=_FF(b,c,d,a,x[k+11],S14,0x895CD7BE);
        a=_FF(a,b,c,d,x[k+12],S11,0x6B901122);
        d=_FF(d,a,b,c,x[k+13],S12,0xFD987193);
        c=_FF(c,d,a,b,x[k+14],S13,0xA679438E);
        b=_FF(b,c,d,a,x[k+15],S14,0x49B40821);
        a=_GG(a,b,c,d,x[k+1], S21,0xF61E2562);
        d=_GG(d,a,b,c,x[k+6], S22,0xC040B340);
        c=_GG(c,d,a,b,x[k+11],S23,0x265E5A51);
        b=_GG(b,c,d,a,x[k+0], S24,0xE9B6C7AA);
        a=_GG(a,b,c,d,x[k+5], S21,0xD62F105D);
        d=_GG(d,a,b,c,x[k+10],S22,0x2441453);
        c=_GG(c,d,a,b,x[k+15],S23,0xD8A1E681);
        b=_GG(b,c,d,a,x[k+4], S24,0xE7D3FBC8);
        a=_GG(a,b,c,d,x[k+9], S21,0x21E1CDE6);
        d=_GG(d,a,b,c,x[k+14],S22,0xC33707D6);
        c=_GG(c,d,a,b,x[k+3], S23,0xF4D50D87);
        b=_GG(b,c,d,a,x[k+8], S24,0x455A14ED);
        a=_GG(a,b,c,d,x[k+13],S21,0xA9E3E905);
        d=_GG(d,a,b,c,x[k+2], S22,0xFCEFA3F8);
        c=_GG(c,d,a,b,x[k+7], S23,0x676F02D9);
        b=_GG(b,c,d,a,x[k+12],S24,0x8D2A4C8A);
        a=_HH(a,b,c,d,x[k+5], S31,0xFFFA3942);
        d=_HH(d,a,b,c,x[k+8], S32,0x8771F681);
        c=_HH(c,d,a,b,x[k+11],S33,0x6D9D6122);
        b=_HH(b,c,d,a,x[k+14],S34,0xFDE5380C);
        a=_HH(a,b,c,d,x[k+1], S31,0xA4BEEA44);
        d=_HH(d,a,b,c,x[k+4], S32,0x4BDECFA9);
        c=_HH(c,d,a,b,x[k+7], S33,0xF6BB4B60);
        b=_HH(b,c,d,a,x[k+10],S34,0xBEBFBC70);
        a=_HH(a,b,c,d,x[k+13],S31,0x289B7EC6);
        d=_HH(d,a,b,c,x[k+0], S32,0xEAA127FA);
        c=_HH(c,d,a,b,x[k+3], S33,0xD4EF3085);
        b=_HH(b,c,d,a,x[k+6], S34,0x4881D05);
        a=_HH(a,b,c,d,x[k+9], S31,0xD9D4D039);
        d=_HH(d,a,b,c,x[k+12],S32,0xE6DB99E5);
        c=_HH(c,d,a,b,x[k+15],S33,0x1FA27CF8);
        b=_HH(b,c,d,a,x[k+2], S34,0xC4AC5665);
        a=_II(a,b,c,d,x[k+0], S41,0xF4292244);
        d=_II(d,a,b,c,x[k+7], S42,0x432AFF97);
        c=_II(c,d,a,b,x[k+14],S43,0xAB9423A7);
        b=_II(b,c,d,a,x[k+5], S44,0xFC93A039);
        a=_II(a,b,c,d,x[k+12],S41,0x655B59C3);
        d=_II(d,a,b,c,x[k+3], S42,0x8F0CCC92);
        c=_II(c,d,a,b,x[k+10],S43,0xFFEFF47D);
        b=_II(b,c,d,a,x[k+1], S44,0x85845DD1);
        a=_II(a,b,c,d,x[k+8], S41,0x6FA87E4F);
        d=_II(d,a,b,c,x[k+15],S42,0xFE2CE6E0);
        c=_II(c,d,a,b,x[k+6], S43,0xA3014314);
        b=_II(b,c,d,a,x[k+13],S44,0x4E0811A1);
        a=_II(a,b,c,d,x[k+4], S41,0xF7537E82);
        d=_II(d,a,b,c,x[k+11],S42,0xBD3AF235);
        c=_II(c,d,a,b,x[k+2], S43,0x2AD7D2BB);
        b=_II(b,c,d,a,x[k+9], S44,0xEB86D391);
        a=addUnsigned(a,AA);
        b=addUnsigned(b,BB);
        c=addUnsigned(c,CC);
        d=addUnsigned(d,DD);
    }

    var temp = wordToHex(a)+wordToHex(b)+wordToHex(c)+wordToHex(d);

    return temp.toLowerCase();
}

function utf8_encode(argString)
{
    var string = (argString+''); // .replace(/\r\n/g, "\n").replace(/\r/g, "\n");

    var utftext = "";
    var start, end;
    var stringl = 0;

    start = end = 0;
    stringl = string.length;
    for (var n = 0; n < stringl; n++) {
        var c1 = string.charCodeAt(n);
        var enc = null;

        if (c1 < 128) {
            end++;
        } else if (c1 > 127 && c1 < 2048) {
            enc = String.fromCharCode((c1 >> 6) | 192) + String.fromCharCode((c1 & 63) | 128);
        } else {
            enc = String.fromCharCode((c1 >> 12) | 224) + String.fromCharCode(((c1 >> 6) & 63) | 128) + String.fromCharCode((c1 & 63) | 128);
        }
        if (enc !== null) {
            if (end > start) {
                utftext += string.substring(start, end);
            }
            utftext += enc;
            start = end = n+1;
        }
    }

    if (end > start) {
        utftext += string.substring(start, string.length);
    }

    return utftext;
}

// sniff resolution
(function()
{
    YAHOO.util.Event.addListener(window, 'load', function() {
        var resolution;
        if (window.orientation==90 || window.orientation==270 || window.orientation==-90 || window.orientation==-270) {
            resolution = screen.height +","+ screen.width;
        }
        else {
            resolution = screen.width +","+ screen.height;
        }
        TOOLBOX.setCookie('__resolution__', resolution);
        /*
        // animate browser warning
        if (typeof YAHOO.util.Anim != 'undefined') {
            var container = document.getElementById('browser-warning');
            if (container!=null) {
                container.style.display = 'none';
                var origPos = container.style.position;
                var origVis = container.style.visibility;
                var origDisplay = container.style.display;

                container.style.position = 'absolute';
                container.style.visbility = 'hidden';
                container.style.display = '';
                container.style.overflow = 'hidden';

                var origHeight = (YAHOO.util.Dom.getRegion(container).height);

                container.style.position = origPos;
                container.style.visibility = origVis;
                container.style.display = origDisplay;

                var showAnimation = new YAHOO.util.Anim(container,
                                                        {height: {to: origHeight-10}},
                                                        0.5);
                container.style.height = "2px";
                container.style.display = "";
                showAnimation.animate();
            }
        }
        */
    });
})();
// Listing table refresh, key listener.
(function()
{
var kl = new YAHOO.util.KeyListener(document, { shift:true, keys:82 },
                                              { fn:function()
        {
           if (typeof window.listingTables != 'undefined') {
               for (var i in window.listingTables) {
                   window.listingTables[i].fetchData();
               }
               for (var i in window.calendars) {
                   window.calendars[i].fetchData();
               }
           }
        }
    });
    if (document.location.href.match('blueweb')) {
        kl.enable();
    }
})();

TOOLBOX.use = function()
{
    // Variables
    var args = Array.prototype.slice.call(arguments);
    var resources = args.slice(0, args.length-1)
    var callback = args[args.length-1];
    var loaded= 0;
    
    // CONSTANTS
    var TOLOAD= resources.length;
    var ERROR={
        callback: 'The last argument must be a callabck function to be invoked once the resources listed have been loaded',
        unavailableName: 'The resource name has not been registered with this function',
        noNameOrSource: 'Please include either a name or a source property with your resource object',
        noNamewithVersion: 'Please include a name of the resource with your version number',
        dependenciesNotArray: 'The dependencies property must be an array of source strings',
        includesNotArray: 'The includes property must be an array of source strings'
    };
    var MAP = {
        'jquery' : 
            {
            defaultVersion : '1.6.2',
            version : {
                '1.6.2' : {
                    src: ['/baseapp/scripts/jquery/1.6.2/jquery.min.js'],
                    dependencies: [],
                    includes: []
                }
            }
        }
    }
 
    // Loop through resources and where done
    for(var i=0,l=resources.length; i<l; i++){
        var resource= normaliseResource(resources[i]);
        if (!isLoaded(resource.src)) loadResource(resource);
    }
    
    // validate and return a normalised resource object with all neccessary properties overwritten 
    function normaliseResource(resource){
        var normResource;
        // String
        if (typeof resource === 'string'){
            if (MAP[resource]) normResource = MAP[resource]['version'][MAP[resource]['defaultVersion']];
            else throw new Error(ERROR.unavailableName);
        }
        // Object
        else {
            // Object with no name or source
            if (typeof resource.name === 'undefined' && typeof resource.src === 'undefined')
                throw new Error(ERROR.noNameOrSource);
            // Object with version
            if (typeof resource.version !== 'undefined'){
                if (typeof resource.name === 'undefined') throw new Error(ERROR.noNameWithVersion);
                else normResource = MAP[resource.name]['version'][resource.version];
            }
            // Object without version
            else{
                if (typeof resource.name !== 'undefined'){
                    normResource = MAP[resource.name]['version'][ MAP[resource.name]['defaultVersion'] ];
                }
            }
        }
        // Override src, dependencies and includes
        var overWritable = ['src', 'dependencies', 'includes'];
        for (var i=0,l=overWritable.length; i<l; i++){
            var prop= overWritable[i];
            if (typeof resource[prop] !== 'undefined') {
                normResource[prop]= resource[prop];
            }
        }
        return normResource;
    }
    
    // Check DOM for exisiting source
    function isLoaded(src){
        var headElements= (document.head) ? document.head.childNodes : document.getElementsByTagName('head')[0].childNodes;
        var accept= {LINK : true, SCRIPT : true};
        for (var i=0,l=headElements.length; i<l; i++){
          if (!accept[headElements[i].tagName]) continue; // Not a LINK or SCRIPT tag, so continue
          // LINK with href attribute
          if (typeof headElements[i].href !== 'undefined') {
              if (headElements[i].href===src) {
                  return true;
              }
          }
          // SCRIPT with src attribute
          else if (typeof headElements[i].src !== 'undefined' && headElements[i].src.length) {
              if (headElements[i].src===src) {
                  return true;
              }
          }
        }
        return false;
    }
    
    // Load the resource and its dependencies and includes in order
    function loadResource(resource){
        var internalResources={
            dependencies: {loaded : 0 , toLoad : 0},
            src:          {loaded : 0 , toLoad : 1},
            includes:     {loaded : 0 , toLoad : 0}
        }
        loadType('dependencies');
        
        function loadType(type){
            switch (type){
                case 'dependencies':
                    if (typeOf(resource.dependencies)!=='array') throw new Error(Error.dependenciesNotArray);
                    // set how many dependencies need to be loaded before we continue to the source
                    internalResources.dependencies.toLoad= resource.dependencies.length;
                    if (internalResources.dependencies.toLoad) {
                        for(var i=0,l=internalResources.dependencies.toLoad; i<l; i++){
                            loadInternalResource('dependencies', resource.dependencies[i]);
                        }
                    }
                    else loadType('src');
                break;
                case 'src':
                    loadInternalResource('src', resource.src[0]);
                break;
                case 'includes':
                    if (typeOf(resource.includes)!=='array') throw new Error(Error.includesNotArray);
                    // set how many includes need to be loaded before we continue to the source 
                    internalResources.includes.toLoad= resource.includes.length;
                    if (internalResources.includes.toLoad) {
                        for(var i=0,l=internalResources.includes.toLoad; i<l; i++){
                            loadInternalResource('includes', resource.includes[i]);
                        }
                    }
                    else updateResourceLoaded();
                break;
            }    
        }
        
        function loadInternalResource(type, resource){
            var source= (typeof resource.src === 'undefined') ? resource : resource.src;           
            var elToCreate= getExtension(source)=='js' ? 'script' : 'link';
            var el= document.createElement(elToCreate), loaded = false;
            if (elToCreate==='script') {         
                el.onload = el.onreadystatechange = function () {
                  if ((el.readyState && el.readyState !== "complete" && el.readyState !== "loaded") || loaded) {
                       return;
                  }
                  updateInternalResourceLoaded(type);
                  el.onload = el.onreadystatechange = null;
                  loaded = true;
                };
                el.async = true;
                el.src= source;
            }
            else {
                el.href= source;
                el.rel = 'stylesheet';
                updateInternalResourceLoaded(type);
            }
            if (document.head) {
                document.head.appendChild(el);
            }
            else {
                document.getElementsByTagName('head')[0].appendChild(el);
            }
        }
        
        function updateInternalResourceLoaded(type){
            internalResources[type]['loaded'] +=1;
            if (internalResources[type]['loaded']>=internalResources[type]['toLoad']){
                switch(type){
                    case 'dependencies':
                        loadType('src');
                        break;
                    case 'src':
                        loadType('includes');
                        break;
                    case 'includes':
                        updateResourceLoaded();
                        break;
                }
            }
        }
  
        function getExtension(src){
            return src.match(/js$/) ? 'js' : 'css';
        }

    }
    
    function updateResourceLoaded(){
        loaded+=1;
        // Finally execute callback!
        if (loaded===TOLOAD){
            if (typeof callback !=='function') {
                throw new Error(ERROR.callback);
            }
            else {
                callback();
            }
        }
    }

    // Douglus Crockford typeOf function for arrays @see http://javascript.crockford.com/remedial.html
    function typeOf(value) {
        var s = typeof value;
        if (s === 'object') {
            if (value) {
                if (value instanceof Array) {
                    s = 'array';
                }
            } else {
                s = 'null';
            }
        }
        return s;
    }
};
