
/**
 * B2Bee
 *
 * @category   JavaScript
 * @package    B2Bee_Site_JavaScript
 * @copyright  Copyright (c) 2009 B2Bee, LLC. (http://b2bee.com)
 * @version    $Id: b2bee.js 1 2009-12-18 20:20:38Z kwilbur $
 */


/**
 * Add ECMA262-5 method binding if not supported natively
 */
if (!('bind' in Function.prototype)) {
    Function.prototype.bind= function(owner) {
        var that= this;
        if (arguments.length<=1) {
            return function() {
                return that.apply(owner, arguments);
            };
        }
        else {
            var args= Array.prototype.slice.call(arguments, 1);
            return function() {
                return that.apply(owner, arguments.length===0? args : args.concat(Array.prototype.slice.call(arguments)));
            };
        }
    };
}

/**
 * Add ECMA262-5 String trim methods if not supported natively
 */
if (!('trim' in String.prototype)) {
    String.prototype.trim= function() {
        return this.replace(/^\s+|\s+$/g,"");
    };
}
if (!('ltrim' in String.prototype)) {
    String.prototype.ltrim = function() {
        return this.replace(/^\s+/,"");
    };
}
if (!('rtrim' in String.prototype)) {
    String.prototype.rtrim = function() {
        return this.replace(/\s+$/,"");
    };
}

/**
 * Add ECMA262-5 Array methods if not supported natively
 */
if (!('indexOf' in Array.prototype)) {
    Array.prototype.indexOf= function(find, i /*opt*/) {
        if (i===undefined) i= 0;
        if (i<0) i+= this.length;
        if (i<0) i= 0;
        for (var n= this.length; i<n; i++)
            if (i in this && this[i]===find)
                return i;
        return -1;
    };
}
if (!('lastIndexOf' in Array.prototype)) {
    Array.prototype.lastIndexOf= function(find, i /*opt*/) {
        if (i===undefined) i= this.length-1;
        if (i<0) i+= this.length;
        if (i>this.length-1) i= this.length-1;
        for (i++; i-->0;) /* i++ because from-argument is sadly inclusive */
            if (i in this && this[i]===find)
                return i;
        return -1;
    };
}
if (!('forEach' in Array.prototype)) {
    Array.prototype.forEach= function(action, that /*opt*/) {
        for (var i= 0, n= this.length; i<n; i++)
            if (i in this)
                action.call(that, this[i], i, this);
    };
}
if (!('map' in Array.prototype)) {
    Array.prototype.map= function(mapper, that /*opt*/) {
        var other= new Array(this.length);
        for (var i= 0, n= this.length; i<n; i++)
            if (i in this)
                other[i]= mapper.call(that, this[i], i, this);
        return other;
    };
}
if (!('filter' in Array.prototype)) {
    Array.prototype.filter= function(filter, that /*opt*/) {
        var other= [], v;
        for (var i=0, n= this.length; i<n; i++)
            if (i in this && filter.call(that, v= this[i], i, this))
                other.push(v);
        return other;
    };
}
if (!('every' in Array.prototype)) {
    Array.prototype.every= function(tester, that /*opt*/) {
        for (var i= 0, n= this.length; i<n; i++)
            if (i in this && !tester.call(that, this[i], i, this))
                return false;
        return true;
    };
}
if (!('some' in Array.prototype)) {
    Array.prototype.some= function(tester, that /*opt*/) {
        for (var i= 0, n= this.length; i<n; i++)
            if (i in this && tester.call(that, this[i], i, this))
                return true;
        return false;
    };
}


/**
 * Add a console if none exists so that our debugging stuff doesn't cause errors.
 */
if ( !window.console || !console.firebug) {
    var methods = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
    window.console = new Object();
    for (var i = 0; i < methods.length; i++) {
        window.console[methods[i]] = function() {}
    }
}

/**
 * Add getElementsByClassName, if not exixts
 */
if (!document.getElementsByClassName) {
    if (!document.prototype) document.prototype = {};
    document.prototype.getElementsByClassName = function(className) {
        var elements = this.all;
        var retval = [];
        var regex = new RegExp(className,'g');
        for (var i = 0; i < elements.length; i++) if (regex.test(elements[i].className)) retval.push(elements[i]);
        return retval;
    }
    if (!document.getElementsByClassName) {
        document.getElementsByClassName = document.prototype.getElementsByClassName;
    }
}

/*
 * Date Format 1.2.3
 * (c) 2007-2009 Steven Levithan <stevenlevithan.com>
 * MIT license
 *
 * Includes enhancements by Scott Trenda <scott.trenda.net>
 * and Kris Kowal <cixar.com/~kris.kowal/>
 *
 * Accepts a date, a mask, or a date and a mask.
 * Returns a formatted version of the given date.
 * The date defaults to the current date/time.
 * The mask defaults to dateFormat.masks.default.
 */

var dateFormat = function () {
    var    token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,
        timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
        timezoneClip = /[^-+\dA-Z]/g,
        pad = function (val, len) {
            val = String(val);
            len = len || 2;
            while (val.length < len) val = "0" + val;
            return val;
        };

    // Regexes and supporting functions are cached through closure
    return function (date, mask, utc) {
        var dF = dateFormat;

        // You can't provide utc if you skip other args (use the "UTC:" mask prefix)
        if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) {
            mask = date;
            date = undefined;
        }
        
        // Passing date through Date applies Date.parse, if necessary
        date = date ? new Date(date) : new Date;
        if (isNaN(date)) throw SyntaxError("invalid date");
        
        mask = String(dF.masks[mask] || mask || dF.masks["default"]);
        
        // Allow setting the utc argument via the mask
        if (mask.slice(0, 4) == "UTC:") {
            mask = mask.slice(4);
            utc = true;
        }
        
        var    _ = utc ? "getUTC" : "get",
            d = date[_ + "Date"](),
            D = date[_ + "Day"](),
            m = date[_ + "Month"](),
            y = date[_ + "FullYear"](),
            H = date[_ + "Hours"](),
            M = date[_ + "Minutes"](),
            s = date[_ + "Seconds"](),
            L = date[_ + "Milliseconds"](),
            o = utc ? 0 : date.getTimezoneOffset(),
            flags = {
                d:    d,
                dd:   pad(d),
                ddd:  dF.i18n.dayNames[D],
                dddd: dF.i18n.dayNames[D + 7],
                m:    m + 1,
                mm:   pad(m + 1),
                mmm:  dF.i18n.monthNames[m],
                mmmm: dF.i18n.monthNames[m + 12],
                yy:   String(y).slice(2),
                yyyy: y,
                h:    H % 12 || 12,
                hh:   pad(H % 12 || 12),
                H:    H,
                HH:   pad(H),
                M:    M,
                MM:   pad(M),
                s:    s,
                ss:   pad(s),
                l:    pad(L, 3),
                L:    pad(L > 99 ? Math.round(L / 10) : L),
                t:    H < 12 ? "a"  : "p",
                tt:   H < 12 ? "am" : "pm",
                T:    H < 12 ? "A"  : "P",
                TT:   H < 12 ? "AM" : "PM",
                Z:    utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""),
                o:    (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
                S:    ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
            };
        
        return mask.replace(token, function ($0) {
            return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
        });
    };
}();

// Some common format strings
dateFormat.masks = {
    "default":      "ddd mmm dd yyyy HH:MM:ss",
    shortDate:      "m/d/yy",
    mediumDate:     "mmm d, yyyy",
    longDate:       "mmmm d, yyyy",
    fullDate:       "dddd, mmmm d, yyyy",
    shortTime:      "h:MM TT",
    mediumTime:     "h:MM:ss TT",
    longTime:       "h:MM:ss TT Z",
    isoDate:        "yyyy-mm-dd",
    isoTime:        "HH:MM:ss",
    isoDateTime:    "yyyy-mm-dd'T'HH:MM:ss",
    isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
};

// Internationalization strings
dateFormat.i18n = {
    dayNames: [
        "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
        "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
    ],
    monthNames: [
        "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
        "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
    ]
};

// For convenience...
Date.prototype.format = function (mask, utc) {
    return dateFormat(this, mask, utc);
};

var B2Bee = new Object({
    classes: {}
    ,objects: {}
    ,pages: {}
    ,prefs: {}
    ,widgets: {}
    ,addPrintListeners: function()
        {
            var elements = B2Bee.getElementsByAttribute('rel', 'print');
            if (typeof elements != 'undefined' && elements != null && elements.length > 0) {
                for (var i=0; i < elements.length; i++) {
                    B2Bee.util.events.addListener(elements[i], 'click', B2Bee.printScreen, B2Bee);
                    console.log(B2Bee.util.events.addListener(elements[i], 'click', B2Bee.printScreen, B2Bee));
                }
            }
        }
    ,addDeleteListeners: function()
        {
            // Gather all external links on the page
            var elements = B2Bee.getElementsByAttribute('rel', 'delete');
            
            if (typeof elements != 'undefined' && elements != null && elements.length > 0) {
                // Loop through links and add onClick listeners to open new windows and track in GA
                for (var i=0; i < elements.length; i++) {
                    YAHOO.util.Event.addListener(elements[i], 'click'
            ,function(event) {
                            B2Bee.stopEvent(event);
                
                var itemType = this.id.match(/^[^_]+/)[0];
                var itemID = this.id.match(/[0-9]+$/)[0];
                console.log('Delete: ' + itemType + ' ' + itemID);
                var doDelete = false;
                
                if ('client' == itemType)
                {
                    if (true == B2Bee.confirmClientDelete())
                    {
                        doDelete = confirm(this.title +'?');
                    }
                } else {
                    doDelete = confirm(this.title +'?');
                }
                if (true == doDelete) {
                var path = '/'+itemType+'/delete/'+itemID;
                var method = 'POST';
                var params = '';
                var callback = {
                    success:   function(o) {
                               try {
                               var response = YAHOO.lang.JSON.parse(o.responseText);
                               if (typeof response.message != "undefined") {
                                   B2Bee.document.showMessage(response.message, 'success');
                                   // TODO: need to update page item was deleted from, instead of reloading
                                   window.location.reload();
                               }
                               else if (typeof response.error != "undefined") {
                                   B2Bee.document.showMessage(response.error, 'error');
                                   console.error(response);
                               }
                               else {
                                   B2Bee.document.showMessage('Server response unreadable.', 'error');
                                   console.error(response);
                               }
                               }
                               catch (e) { console.error(e); console.info(o); }
                           }
                       ,failure:   function(o) {
                               B2Bee.document.showMessage('Delete failed. Could not contact server.', 'error');
                               console.error(o);
                           }
                       ,timeout:  5000
                       }
                B2Bee.util.callAPI(path,params,method,callback);
                }
                        }
            );
                }
            }
        }
    ,addExternalLinkListeners: function()
        {
            // Gather all external links on the page
            var elements = B2Bee.getElementsByAttribute('rel', 'external');
            
            if (typeof elements != 'undefined' && elements != null && elements.length > 0) {
                // Loop through links and add onClick listeners to open new windows and track in GA
                for (var i=0; i < elements.length; i++) {
                    B2Bee.util.events.addListener(elements[i], 'click', function(event) {
                            // Stop link form navagating away formt he site.
                            B2Bee.stopEvent(event);
                            
                            // Open a new window for the links target.
                            if (typeof this.href != 'undefined') {
                                if (typeof this.name != 'undefined') {
                                    window.open(this.href, this.name);
                                }
                                else if (typeof this.id != 'undefined' && this.id != '') {
                                    window.open(this.href, this.id);
                                }
                                else {
                                    window.open(this.href, this.href);
                                }
                            }
                            
                            // Track external click in Google Analytics
                            pageTracker._trackPageview('/external/'+this.href);
                        });
                }
            }
        }
    ,addHelperCloseListeners: function()
        {
            helpClosers = document.getElementsByClassName('helper_close');
            if (typeof helpClosers != 'undefined' && helpClosers != null && helpClosers.length > 0) {
                for (var i = 0;i < helpClosers.length; i++) {
                    B2Bee.util.events.addListener(
                                helpClosers[i]
                                ,'click'
                                ,function(event)
                                    {
                                        // find parent div and hide
                                        parentDiv = this.parentNode;
                                        parentDiv.style.display = 'none';
                                            //helpers[i].visible = false;
                                            //B2Bee.util.DOM.removeClassName(helpers[i],'flash');
                                            //B2Bee.util.DOM.removeClassName(helpers[i],'help');
                                            //B2Bee.util.DOM.addClassName(helpers[i],'hidden');
                                        
                                        // set cookie based on id
                                        if ('' == this.id)
                                        {
                                            // do nothing - not a registered message (probably should be)
                                            console.log('Non-registered helper text message');
                                        }
                                        else {
                                            // set the cookie
                                            var MsgID = this.id;
                                            document.cookie = MsgID + '=1; expires=31 Dec 2037 23:59:59 GMT';
                                        }
                                    }
                                );
                }
            }
        }
    ,callAPI: function(path,params,method,callback)
        {
            // TODO: update callees to use B2Bee.util.callAPI vs B2Bee.callAPI
            B2Bee.util.callAPI(path,params,method,callback);
        }
    ,confirmClientDelete: function()
        {
            var message = "ALL data related to this client will be deleted, INCLUDING invoices, payments, expenses, projects, and contacts.";
            //B2Bee.dialog.create(message, 'Warning');
            //B2Bee.dialog.show();
            return confirm(message);
        }
    ,dialog: 
        {
            currentDialog: null
            ,dialogs: []
            ,create: function(content, className, title, hideCloseButton)
                {
                    var dialog = new dijit.Dialog({
                        title: ""//className.substring(0,1).toUpperCase() + className.substring(1).toLowerCase()
                        ,content: content
                        ,style: "width: 300px"
                    });
                    if(className) {
                        dialog.attr("class", className);
                    }
                    console.log(dialog);
                    if (this.currentDialog) { this.dialogs.push(this.currentDialog); }
                    this.currentDialog = dialog;
                    this.show();
                    if (hideCloseButton) { this.currentDialog.closeButtonNode.style.display = "none"; }
                    return dialog;
                }
            ,destroy: function(dialog)
                {
                    // ensure that dialog was passed and is valid
                    if ( !dialog || typeof(dialog) === "undefined" ) {
                        // if not and currentDialog exists and is valid
                        if ( this.currentDialog && typeof(this.currentDialog) !== "undefined" ) {
                            // use that instead
                            dialog = this.currentDialog;
                        }
                        else {
                            // just quit
                            return;
                        }
                    }
                    dialog.hide();
                    dialog.destroy();
                    if (this.dialogs.length) {
                        this.currentDialog = this.dialogs.pop();
                        this.show();
                    }
                    else {
                        this.currentDialog = null;
                    }
                }
            ,destroyAll: function()
                {
                    while(this.currentDialog) {
                        this.hide();
                    }
                }
            ,hide: function(dialog)
                {
                    if (!dialog || typeof(dialog) === "undefined") dialog = this.currentDialog;
                    this.destroy(dialog);
                    /*
                    dialog.hide();
                    if (this.dialogs.length) {
                        this.currentDialog = this.dialogs.pop();
                        this.currentDialog.show();
                    }
                    else {
                        this.currentDialog = null;
                    }
                    */
                }
            ,show: function(dialog)
                {
                    if (!dialog || typeof(dialog) === "undefined") dialog = this.currentDialog;
                    dialog.show();
                }
        }
    ,Date: function (str)
        {
            var year = B2Bee.util.formatDate(str, "Y");
            var month = B2Bee.util.formatDate(str, "m") - 1; // months are zero indexed in Javascript
            var day = B2Bee.util.formatDate(str, "d");
            return new Date(year, month, day);
        }
    ,document:
        {
            height: null
            ,ready: false
            ,width: null
            ,clearMessages: function(container)
                {
                    //TODO: copy this to B2Bee.forms.hideMessage() for use in single form scope
                    switch (typeof container) {
                        case 'object':
                            break;
                        case 'string':
                            console.log('container: ' + container);
                            if ('undefined' == document.getElementById(container)) {
                                console.error('Message container "' + container + '" is not found.');
                                return;
                                break;
                            }
                            else {
                                container = document.getElementById(container);
                            }
                            break;
                        case 'undefined':
                        default:
                            console.log('container: ' + container);
                            container = document.getElementById('messages')
                            break;
                    }
                    console.log('container: ' + container);
                    B2Bee.util.DOM.removeChildren(container);
                    B2Bee.util.DOM.removeClassName(container, "error");
                    B2Bee.util.DOM.removeClassName(container, "success");
                    container.style.display = 'none';
                    return;
                }
            ,getCookie: function(name)
                {
                    var retval = '';
                    // Do we have cookies?
                    if ( document.cookie.length > 0 ) {
                        // Do we have *this* cookie?
                        var start = document.cookie.indexOf(name + "=");
                        if (start >= 0 ) {
                            // move 'start' to beginning of value
                            start = start + name.length + 1;
                            // find 'end' of value
                            var end = document.cookie.indexOf(";",start);
                            if ( end < 0 ) end = document.cookie.length;
                            // grab value
                            retval = unescape(document.cookie.substring(start,end));
                        }
                    }
                    return retval;
                }
            ,hideMessage: function(container)
                {
                    //TODO: copy this to B2Bee.forms.hideMessage() for use in single form scope
                    switch (typeof container) {
                        case 'object':
                            break;
                        case 'string':
                            if ('undefined' == document.getElementById(container)) {
                                console.error('Message container "' + container + '" is not found.');
                                return;
                                break;
                            }
                            else {
                                container = document.getElementById(container);
                            }
                            break;
                        case 'undefined':
                        default:
                            console.error('Invalid container "' + container + '".');
                            return;
                    }
                    container.style.display = 'none';
                }
            ,scrollTo: function(element)
                {
                    switch (typeof element) {
                        case 'object':
                            dojox.fx.smoothScroll({node:element,win:window,duration:400}).play();
                            dojox.fx.highlight({node:element,duration:800}).play();
                            break;
                        case 'string':
                            dojox.fx.smoothScroll({node:dojo.byId(element),win:window,duration:400}).play();
                            dojox.fx.highlight({node:dojo.byId(element),duration:800}).play();
                            break;
                        case 'undefined':
                            break;
                    }
                    return true;
                }
            ,showMessage: function(message, className, container)
                {
                    //TODO: copy this to B2Bee.forms.showMessage() for use in single form scope
                    switch (typeof container) {
                        case 'object':
                            break;
                        case 'string':
                            if ('undefined' == document.getElementById(container)) {
                                console.error('Message container "' + container + '" is not found.');
                                return false;
                                break;
                            }
                            else {
                                container = document.getElementById(container);
                            }
                            break;
                        case 'undefined':
                                var id = B2Bee.util.crypto.md5(message);
                                console.log('id: ' + id);
                                if ( 'undefined' == document.getElementById(id) || null == document.getElementById(id)) {
                                    console.log('ID not found...');
                                    container = document.createElement('DIV');
                                    container.id = B2Bee.util.crypto.md5(message);
                                    document.getElementById('messages').appendChild(container);
                                    document.getElementById('messages').style.display = 'block';
                                }
                                else {
                                    console.log('ID found...');
                                    container = document.getElementById(id)
                                }
                                console.log(container);
                                B2Bee.util.DOM.addClassName(container, 'flash');
                            break;
                        default:
                            console.error('Invalid container "' + container + '".');
                            return false;
                    }
                    
                    if ('undefined' != typeof className) B2Bee.util.DOM.addClassName(container, className);
                    container.innerHTML = message;container.style.display = 'block';
                    container.focus();
                    B2Bee.document.scrollTo(container);
                    return container;
                }
            ,updateSize: function()
                {
                    this.height = YAHOO.util.Dom.getDocumentHeight();
                    this.width  = YAHOO.util.Dom.getDocumentWidth();
                    B2Bee.window.updatePosition();
                }
        }
    ,event:
        {
        }
    ,getElements: null
    ,getElementsByAttribute: null
    ,getTimezoneName: function ()
        {
            summer = new Date(Dsate.UTC(2005, 6, 30, 0, 0, 0, 0));
            so = -1 * summer.getTimezoneOffset();
            winter = new Date(Date.UTC(2005, 12, 30, 0, 0, 0, 0));
            wo = -1 * winter.getTimezoneOffset();
        
            if (-660 == so && -660 == wo) return 'Pacific/Midway';
            if (-600 == so && -600 == wo) return 'Pacific/Tahiti';
            if (-570 == so && -570 == wo) return 'Pacific/Marquesas';
            if (-540 == so && -600 == wo) return 'America/Adak';
            if (-540 == so && -540 == wo) return 'Pacific/Gambier';
            if (-480 == so && -540 == wo) return 'US/Alaska';
            if (-480 == so && -480 == wo) return 'Pacific/Pitcairn';
            if (-420 == so && -480 == wo) return 'US/Pacific';
            if (-420 == so && -420 == wo) return 'US/Arizona';
            if (-360 == so && -420 == wo) return 'US/Mountain';
            if (-360 == so && -360 == wo) return 'America/Guatemala';
            if (-360 == so && -300 == wo) return 'Pacific/Easter';
            if (-300 == so && -360 == wo) return 'US/Central';
            if (-300 == so && -300 == wo) return 'America/Bogota';
            if (-240 == so && -300 == wo) return 'US/Eastern';
            if (-240 == so && -240 == wo) return 'America/Caracas';
            if (-240 == so && -180 == wo) return 'America/Santiago';
            if (-180 == so && -240 == wo) return 'Canada/Atlantic';
            if (-180 == so && -180 == wo) return 'America/Montevideo';
            if (-180 == so && -120 == wo) return 'America/Sao_Paulo';
            if (-150 == so && -210 == wo) return 'America/St_Johns';
            if (-120 == so && -180 == wo) return 'America/Godthab';
            if (-120 == so && -120 == wo) return 'America/Noronha';
            if ( -60 == so &&  -60 == wo) return 'Atlantic/Cape_Verde';
            if (   0 == so &&  -60 == wo) return 'Atlantic/Azores';
            if (   0 == so &&    0 == wo) return 'Africa/Casablanca';
            if (  60 == so &&    0 == wo) return 'Europe/London';
            if (  60 == so &&   60 == wo) return 'Africa/Algiers';
            if (  60 == so &&  120 == wo) return 'Africa/Windhoek';
            if ( 120 == so &&   60 == wo) return 'Europe/Amsterdam';
            if ( 120 == so &&  120 == wo) return 'Africa/Harare';
            if ( 180 == so &&  120 == wo) return 'Europe/Athens';
            if ( 180 == so &&  180 == wo) return 'Africa/Nairobi';
            if ( 240 == so &&  180 == wo) return 'Europe/Moscow';
            if ( 240 == so &&  240 == wo) return 'Asia/Dubai';
            if ( 270 == so &&  210 == wo) return 'Asia/Tehran';
            if ( 270 == so &&  270 == wo) return 'Asia/Kabul';
            if ( 300 == so &&  240 == wo) return 'Asia/Baku';
            if ( 300 == so &&  300 == wo) return 'Asia/Karachi';
            if ( 330 == so &&  330 == wo) return 'Asia/Calcutta';
            if ( 345 == so &&  345 == wo) return 'Asia/Katmandu';
            if ( 360 == so &&  300 == wo) return 'Asia/Yekaterinburg';
            if ( 360 == so &&  360 == wo) return 'Asia/Colombo';
            if ( 390 == so &&  390 == wo) return 'Asia/Rangoon';
            if ( 420 == so &&  360 == wo) return 'Asia/Almaty';
            if ( 420 == so &&  420 == wo) return 'Asia/Bangkok';
            if ( 480 == so &&  420 == wo) return 'Asia/Krasnoyarsk';
            if ( 480 == so &&  480 == wo) return 'Australia/Perth';
            if ( 540 == so &&  480 == wo) return 'Asia/Irkutsk';
            if ( 540 == so &&  540 == wo) return 'Asia/Tokyo';
            if ( 570 == so &&  570 == wo) return 'Australia/Darwin';
            if ( 570 == so &&  630 == wo) return 'Australia/Adelaide';
            if ( 600 == so &&  540 == wo) return 'Asia/Yakutsk';
            if ( 600 == so &&  600 == wo) return 'Australia/Brisbane';
            if ( 600 == so &&  660 == wo) return 'Australia/Sydney';
            if ( 630 == so &&  660 == wo) return 'Australia/Lord_Howe';
            if ( 660 == so &&  600 == wo) return 'Asia/Vladivostok';
            if ( 660 == so &&  660 == wo) return 'Pacific/Guadalcanal';
            if ( 690 == so &&  690 == wo) return 'Pacific/Norfolk';
            if ( 720 == so &&  660 == wo) return 'Asia/Magadan';
            if ( 720 == so &&  720 == wo) return 'Pacific/Fiji';
            if ( 720 == so &&  780 == wo) return 'Pacific/Auckland';
            if ( 765 == so &&  825 == wo) return 'Pacific/Chatham';
            if ( 780 == so &&  780 == wo) return 'Pacific/Enderbury'
            if ( 840 == so &&  840 == wo) return 'Pacific/Kiritimati';
            return 'US/Eastern';
        }
    ,getTimezoneOffset: function ()
        {
            date = new Date(Date.UTC(2005, 6, 30, 0, 0, 0, 0));
            return ( -1 * date.getTimezoneOffset() );
        }    
    ,formatCurrency: null
    ,forms:
        {
            clearErrors: function(form)
                {
                    console.log('Clear errors...');
                    
                    // make sure form actually exists
                    if (typeof form == "undefined" ) {
                        throw "B2BEE_MISSING_EXPECTED_OBJECT";
                    }
                    
                    // Clear all 'messages' containers
                    try {
                        var msgContainer = document.getElementById(form.id.replace(/_form$/, '_messages'));
                        if (typeof msgContainer == "undefined" || msgContainer == null) {
                            msgContainer = document.getElementById('messages');
                        }
                        for(var i=0; i < msgContainer.childNodes.length; i++) {
                            if ( msgContainer.childNodes[1].className && 0 <= B2Bee.util.indexOf(msgContainer.childNodes[1].className,'error') ) {
                                msgContainer.removeChild(msgContainer.childNodes[1]);
                            }
                        }
                        for(var i=0; i < form.length; i++) {
                            B2Bee.util.DOM.removeClassName(form[i], 'error');
                        }
                    }
                    catch (e) {}
                    
                    // Clear all '<formname>_error' containers
                    try {
                        var errContainer = document.getElementById(form.id.replace(/_form$/, '_error'));
                        if (typeof errContainer == "undefined" || errContainer == null) {
                            errContainer = document.getElementById('errors');
                        }
                        
                        if (errContainer && errContainer.innerHTML) { errContainer.innerHTML = ''; }
                        if (errContainer && errContainer.style) { errContainer.style.display = 'none'; }
                        
                    }
                    catch (e) {}
                    
                    // Reset all form fields.
                    for (var i=0; i < form.length; i++) {
                        B2Bee.util.DOM.removeClassName(form[i], 'error');
                    }
                    
                    return true;
                }
            ,clearMessages: function(form)
                {
                    console.log('Clear messages...');
                    
                    // make sure form actually exists
                    if (typeof form == "undefined" ) {
                        throw "B2BEE_MISSING_EXPECTED_OBJECT";
                    }
                    
                    try {
                        var msgContainer = document.getElementById(form.id.replace(/_form$/, '_messages'));
                        if (typeof msgContainer == "undefined" || msgContainer == null) {
                            msgContainer = document.getElementById('messages');
                        }
                        B2Bee.util.DOM.removeChildren(msgContainer);
                        for(var i=0; i < form.length; i++) {
                            B2Bee.util.DOM.removeClassName(form[i], 'error');
                        }
                    }
                    catch (e) {}
                    return true;
                    
                    return true;
                }
            /**
             * B2Bee.forms.dateTextbox()
             * Creates a new text input for selecting a date
             * ... or applies new features to an existing text input.
             * @param config {object} The config info for the textarea.
             *      {
             *       name: "textareaElement.id"
             *       ,value: "Textarea content"
             *       ,style: "width:200px;height:300px;..."
             *       ,className: "foo bar"
             *       }
             */
            ,dateTextbox: function(config)
                {
                    // Check input for expected values.
                    if (typeof(config) === "undefined") throw "B2BEE_MISSING_EXPECTED_CONFIG_OBJECT";
                    if (typeof(config.name) === "undefined") throw "B2BEE_MISSING_REQUIRED_CONFIG_VALUE";
                    var element = document.getElementById(config.name);
                    if (typeof(element) === "undefined") {
                        element = docuemnt.createElement("INPUT");
                        element.type = "text";
                        element.id = config.name;
                    }
                    if (typeof(config.value) === "undefined") config.value = "";
                    if (typeof(config.style) === "undefined") config.style = "";
                    if (typeof(config.className) === "undefined") config.className = "";
                    
                    var textbox = new dijit.form.DateTextBox(
                                                            {
                                                                name: config.name
                                                                ,value: config.value
                                                                ,style: config.style
                                                            }
                                                            ,config.name
                                                        );
                    textbox.attr("class", config.className);
                    return textbox;
                }
            ,getData: function(thisObject)
                {
                    console.log('Get data...');
                    
                    var data = {};
                    for(var i=0; i < thisObject.form.length; i++) {
                        var input = thisObject.form[i];
                        data[input.id] = {
                            id: input.id
                            ,name: input.name
                            ,value: input.value
                            };
                    }                
                    return data;
                }
            ,hideMessage: function(container)
                {
                    switch (typeof container) {
                        case 'object':
                            break;
                        case 'string':
                            if ('undefined' == document.getElementById(container)) {
                                console.error('Message container "' + container + '" is not found.');
                                return;
                                break;
                            }
                            else {
                                container = document.getElementById(container);
                            }
                            break;
                        case 'undefined':
                        default:
                            console.error('Invalid container "' + container + '".');
                            return;
                    }
                    container.style.display = 'none';
                }
            ,reportError: function(element,message,container)
                {
                    B2Bee.dialog.create(message, 'error');
                    B2Bee.util.DOM.addClassName(element, 'error');
                    B2Bee.dialog.show();
                    /*
                     * Truying out the dialog for form errors, if ok, delete this commented code block
                    if (typeof message == "undefined" || message == null) {
                        message = "Invalid entry";
                        if (typeof document.getElementById(element.id+"_label") != "undefined") {
                            message += " for " + document.getElementById(element.id+"_label").textContent;
                        }
                    }
                    if (typeof container == "undefined" || container == null) {
                        alert(message);
                    }
                    else {
                        this.showMessage(element.form, message, "error", container) 
                    }
                    */
                    return true;
                }
            ,resetForm: function(form)
                {
                    console.log('Reset form...');
                    
                    // make sure form actually exists, we need the HTML form element object
                    switch (typeof form ) {
                        case "object":
                            break;
                        case "string":
                            form = docuemnt.getElementById(form);
                            if ("undefined" != typeof form) break;
                        case "undefined":
                        default:
                            console.log('form is undefined');
                            throw "B2BEE_MISSING_EXPECTED_OBJECT";
                    }
                    
                    for(var i=0; i < form.length; i++) {
                        form[i].value = ''
                        if (form[i].selectedIndex) form[i].selectedIndex = 0;
                        if (form[i].checked) form[i].checked = false;
                    }
                    B2Bee.forms.clearErrors(form);
                    return true;
                }
            ,showMessage: function(form, message, className, container)
                {
                    switch (typeof container) {
                        case 'object':
                            break;
                        case 'string':
                            if ('undefined' == document.getElementById(container)) {
                                console.error('Message container "' + container + '" is not found.');
                                return false;
                                break;
                            }
                            else {
                                container = document.getElementById(container);
                            }
                            break;
                        case 'undefined':
                                var id = B2Bee.util.crypto.md5(message);
                                if ( 'undefined' == document.getElementById(id) || null == document.getElementById(id)) {
                                    container = document.createElement('DIV');
                                    container.id = B2Bee.util.crypto.md5(message);
                                    var msgContainer = document.getElementById(form.id.replace(/_form$/,'_messages'));
                                    if (typeof msgContainer == 'undefined' || msgContainer == null) {
                                        msgContainer = document.getElementById('messages');
                                    }
                                    msgContainer.appendChild(container);
                                    msgContainer.style.display = 'block';
                                }
                                else {
                                    container = document.getElementById(id)
                                }
                                B2Bee.util.DOM.addClassName(container, 'flash');
                            break;
                        default:
                            console.error('Invalid container "' + container + '".');
                            return false;
                    }
                    
                    if ('undefined' != typeof className) B2Bee.util.DOM.addClassName(container, className);
                    container.innerHTML = message;
                    container.style.display = 'block';
                    B2Bee.document.scrollTo(container);
                    return container;
                }
            /**
             * B2Bee.forms.textarea()
             * Creates a new dynamically expanding textarea input with the given attributes
             * ... or applies new features to an existing textarea
             * 
             * @param config {object} The config info for the textarea.
             *      {
             *       name: "textareaElement.id"
             *       ,value: "Textarea content"
             *       ,style: "width:200px;height:300px;..."
             *       ,className: "foo bar"
             *       }
             */
            ,textarea: function(config)
                {
                    // Check input for expected values.
                    if (typeof(config) === "undefined") throw "B2BEE_MISSING_EXPECTED_CONFIG_OBJECT";
                    if (typeof(config.id) === "undefined") throw "B2BEE_MISSING_REQUIRED_CONFIG_VALUE";
                    var element = document.getElementById(config.id);
                    if (typeof(element) === "undefined") {
                        element = docuemnt.createElement("TEXTAREA");
                        element.id = config.id;
                    }
                    if (typeof(config.value) === "undefined") config.value = "";
                    if (typeof(config.style) === "undefined") config.style = "";
                    if (typeof(config.className) === "undefined") config.className = "";
                    
                    var textarea = new dijit.form.Textarea(
                                                            {
                                                                name: config.id
                                                                ,value: config.value
                                                                ,style: config.style
                                                            }
                                                            ,config.id
                                                        );
                    textarea.attr("class", config.className);
                    return textarea;
                }
            /**
             * B2Bee.forms.textbox()
             * Creates a new text input
             * ... or applies new features to an existing text input.
             * @param config {object} The config info for the textarea.
             *      {
             *       name: "textareaElement.id"
             *       ,value: "Textarea content"
             *       ,style: "width:200px;height:300px;..."
             *       ,className: "foo bar"
             *       }
             */
            ,textbox: function(config)
                {
                    // Check input for expected values.
                    if (typeof(config) === "undefined") throw "B2BEE_MISSING_EXPECTED_CONFIG_OBJECT";
                    if (typeof(config.name) === "undefined") throw "B2BEE_MISSING_REQUIRED_CONFIG_VALUE";
                    var element = document.getElementById(config.name);
                    if (typeof(element) === "undefined") {
                        element = docuemnt.createElement("INPUT");
                        element.type = "text";
                        element.id = config.name;
                    }
                    if (typeof(config.value) === "undefined") config.value = "";
                    if (typeof(config.style) === "undefined") config.style = "";
                    if (typeof(config.className) === "undefined") config.className = "";
                    
                    var textbox = new dijit.form.TextBox(
                                                        {
                                                            name: config.name
                                                            ,value: config.value
                                                            ,style: config.style
                                                        }
                                                        ,config.name
                                                        );
                    textbox.attr("class", config.className);
                    return textbox;
                }
            ,validate: function(thisObject)
                {
                    console.log('Validate...');
                    
                    if ( typeof thisObject == "undefined") {
                        console.log('thisObject is undefined');
                        throw "B2BEE_MISSING_EXPECTED_OBJECT";
                    }
                    
                    if ( typeof thisObject.fieldValidation == "undefined" ) {
                        console.log('fieldValidation is undefined');
                        throw "B2BEE_MISSING_EXPECTED_OBJECT";
                    }
                    
                    //Reset any previous errors
                    B2Bee.forms.clearErrors(thisObject.form);
                    
                    // Get the form field name/value pairs
                    var data = B2Bee.forms.getData(thisObject);
                    
                    var msgContainer = document.getElementById(thisObject.form.id.replace(/_form$/, '_messages'));
                    if (typeof msgContainer == "undefined" || msgContainer == null) {
                        msgContainer = document.getElementById('messages');
                    }
                    
                    // loop throught all of the objets in thisObject.fieldValidation
                    var validation = thisObject.fieldValidation;
                    for (var fieldName in validation) {
                        
                        // make sure that the field expected in the fieldValidation list actually was returned from the getData call
                        if (typeof data[fieldName] != 'undefined') {
                            
                            // Trim white space
                            data[fieldName].value = data[fieldName].value.trim();
                            
                            // apply validation regex...should match if data is valid
                            var regex = new RegExp(validation[fieldName].regex, "i");
                            if (!data[fieldName].value.match(regex)) {
                                // If validation failure, report error
                                this.reportError(
                                                document.getElementById(fieldName)
                                                ,"Invalid entry for " + document.getElementById(fieldName+"_label").textContent
                                                ,msgContainer
                                                );
                                return false;
                            }
                        }
                        else {
                            console.log('data['+fieldName+'] is undefined');
                            throw "B2BEE_MISSING_EXPECTED_OBJECT";
                        }
                    }
                    return true;
                }
        }
    ,init: function()
        {
            console.log('B2Bee.init()');
            /**
             * Pull in PHP_JS library if available...
             */
            try {
                this.PHP = new PHP_JS();
            }
            catch (err) {}
            this.formatCurrency = this.util.formatCurrency;
            this.getElements = this.util.DOM.getElements;
            this.getElementsByAttribute = this.util.DOM.getElementsByAttribute;
            this.window.height = YAHOO.util.Dom.getViewportHeight();
            this.window.width  = YAHOO.util.Dom.getViewportWidth();
            this.window.XPosition = YAHOO.util.Dom.getDocumentScrollLeft();
            this.window.YPosition = YAHOO.util.Dom.getDocumentScrollTop();
            this.document.width = YAHOO.util.Dom.getDocumentWidth();
            this.document.height = YAHOO.util.Dom.getDocumentHeight();
            this.util.events.addListener(window, 'scroll', B2Bee.window.updatePosition, B2Bee.window, true);
            this.util.events.addListener(window, 'resize', B2Bee.document.updateSize, B2Bee.document, true);
            this.addPrintListeners();
            this.util.DOM.runOnReadyFuncts();
            this.addExternalLinkListeners();
            this.addDeleteListeners();
            this.addHelperCloseListeners();
            this.setTimeOffsetCookie();
            this.document.ready = true;
            console.log('DOMReady');
            
            return true;
        }
    ,lightbox:
        {
        old:
            {
                applyOverlay: function()
                    {
                        var o = document.createElement('div');
                        o.id  = "overlay";
                        document.body.appendChild(o);
                        o.width          = B2Bee.document.width;
                        o.style.width    = B2Bee.document.width + "px";
                        o.height         = B2Bee.document.height;
                        o.style.height   = B2Bee.document.height + "px";
                        o.style.textAlign  = "center";
                        this.overlay = o;
                        return o;
                    }
                ,close: function()
                    {
                        this.element.style.display = 'none';
                        var e = this.elements.pop();
                        if (e) {
                            e.style.display = 'block'
                            this.element = e;
                            this.positionContent();
                        }
                        else {
                            this.element = null;
                            this.hide();
                        }
                    }
                ,elementWidth: null
                ,elementHeight: null
                ,elements: []
                ,height: null
                ,hide: function()
                    {
                        this.overlay.style.display = "none";
                        this.visible = false;
                    }
                ,init: function(element)
                    {
                        if (this.element) {
                            var e = this.element
                            e.style.display = 'none';
                            this.elements.push(e);
                            this.element = element;
                            this.overlay.appendChild(this.element);
                        }
                        else {
                            this.element = element;
                            console.log(this.element);
                            this.applyOverlay();
                            this.height = this.overlay.height;
                            this.width = this.overlay.width;
                            this.overlay.appendChild(this.element);
                        }
                        this.show();
                        this.element.style.display    = "block";
                        this.positionContent();
                        B2Bee.util.events.addListener(window, 'resize', B2Bee.lightbox.old.resize, B2Bee.lightbox.old, true);
                    }
                ,overlay: null
                ,positionContent: function()
                    {
                        this.elementWidth        = this.element.width;
                        this.elementHeight       = this.element.height;
                        this.elementTop          = Math.round(((B2Bee.window.height - this.elementHeight) / 4) + B2Bee.window.YPosition);
                        this.elementLeft         = Math.round(((B2Bee.window.width - this.elementWidth) / 2) + B2Bee.window.XPosition);
                        this.element.style.top        = this.elementTop + "px";
                        this.element.style.left       = this.elementLeft + "px";
                        this.element.style.height     = this.elementHeight + "px";
                        this.element.style.width      = this.elementWidth + "px";
                    }
                ,resize: function()
                    {
                        B2Bee.document.updateSize();
                        B2Bee.window.updatePosition();
                        this.overlay.width          = B2Bee.document.width;
                        this.overlay.style.width    = B2Bee.document.width + "px";
                        this.overlay.height         = B2Bee.document.height;
                        this.overlay.style.height   = B2Bee.document.height + "px";
                    }
                ,show: function()
                    {
                        this.overlay.style.display = "block";
                        this.visible = true;
                    }
                ,toggle: function()
                    {
                        if (this.visible) {
                            this.hide();
                        }
                        else {
                            this.show();
                        }
                    }
                ,width: null
            },
            
            /**
             * New code implementing Dojo's DIalog widget (dijit.Dialog)
             */
            currentDialog: null
            ,dialogs: []
            ,close: function()
                {
                    this.hide();
                }
            ,destroy: function(dialog)
                {
                    if (!dialog || typeof(dialog) === "undefined") dialog = this.currentDialog;
                    dialog.hide();
                    dialog.destroy();
                    if (this.dialogs.length) {
                        this.currentDialog = this.dialogs.pop();
                        this.show();
                    }
                    else {
                        this.currentDialog = null;
                    }
                }
            ,destroyAll: function()
                {
                    while(this.currentDialog) {
                        this.hide();
                    }
                }
            ,init: function(element, title)
                {
                    console.log(element);
                    B2Bee.util.DOM.removeClassName(element, "hidden");
                    if (typeof(title) === "undefined") title = "";
                    if (this.currentDialog) {
                        this.currentDialog.hide();
                        this.dialogs.push(this.currentDialog);
                    }
                    var dialog = new dijit.Dialog({
                        title: ""//className.substring(0,1).toUpperCase() + className.substring(1).toLowerCase()
                        ,content:  element
                        ,title: title
                        ,style: "width: "+element.width+"px"
                    });
                    //B2Bee.util.DOM.addClassName(dialog.domNode, className);
                    //dialog.attr("title", title);
                    //dialog.attr("content", element.outerHTML);
                    //dialog.attr("class", className);
                    this.currentDialog = dialog;
                    this.show();
                    //this.currentDialog.onHide = function() {this.thisObject.cancel();};
                    this.currentDialog.closeButtonNode.style.display = "none";
                    //this.currentDialog.getElementsByClassName(dijitDialogCloseIcon);
                    return dialog;
                }
            ,hide: function()
                {
                    if ( this.currentDialog ) {
                        this.currentDialog.hide();
                    }
                    
                    if (this.dialogs.length) {
                        this.currentDialog = this.dialogs.pop();
                        this.currentDialog.show();
                    }
                    else {
                        this.currentDialog = null;
                    }
                }
            ,show: function()
                {
                    this.currentDialog.show();
                }
        }
    ,printScreen: function(event, thisObject)
        {
            B2Bee.stopEvent(event);
            window.print();
            return true;
        }
    ,reportFormInputError: function(element,message,container)
        {
            this.forms.reportError(element,message,container);
            return true;
        }
    ,setTimeOffsetCookie: function()
        {
            B2Bee.setCookie("TimeOffset", B2Bee.getTimezoneOffset(), 1 /* Days */);
        }
    ,setCookie: function(name,value,ttl)
        {
            var date = new Date();
            date.setDate( date.getDate() + ttl );
            document.cookie = name + "=" + escape(value) + ( (ttl==null) ? "" : ";expires=" + date.toUTCString() );
        }
    ,stopEvent: function(event)
        {
            return B2Bee.util.events.stopEvent(event);
        }
    ,util:
        {
           callAPI: function(path,params,method,callback)
                {
                    //var url = '/api/' + method + path;
                    var url = window.location.protocol + '//' + window.location.hostname;
                    switch (method) {
                        case 'GET':
                            url = path + '?' + params;
                            break;
                        case 'POST':
                            url = path;
                            break;
                        default:
                            throw "INVALID_API_METHOD_EXCEPTION";
                    }
                    //alert(method+" : "+url+"   "+params);
                    YAHOO.util.Connect.asyncRequest(method,url,callback, params);
                }
           ,crypto:
                {
                    /**
                     *
                     *  MD5 (Message-Digest Algorithm)
                     *  From PHP_JS
                     *
                     **/
                     
                    md5: function (string) {
                        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; 
                        
                        string = B2Bee.PHP.utf8_encode(string);
                        x = convertToWordArray(string);
                        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();
                        
                    }
                }
           ,Dojo: dojo
           ,DOM:
                {
                    onReadyFuncts: []
                    ,addClassName: function(node, className)
                        {
                            if (typeof(node) === 'undefined') return false;
                            else return dojo.addClass(node, className);
                        }
                    ,addOnLoadFunct: function(funct)
                        {
                            dojo.addOnLoad(funct);
                        }
                    ,addOnReadyFunct: function(funct)
                        {
                            this.onReadyFuncts.push(funct);
                        }
                    ,getElements: function(parent)
                        {
                            if (typeof parent == 'undefined' || parent == null) parent = document;
                            
                            var elements = new Array();
                            var element = null;
                            var retval = new Array();
                            
                            if (typeof parent.childNodes == 'undefined' ) { console.log(parent); }
                            if (parent.childNodes.length > 0) {
                                elements = parent.childNodes;
                                for (var i=0; i < elements.length; i++) {
                                    element = elements[i];
                                    retval.push(element);
                                    if (typeof element.childNodes == 'undefined' ) { console.log(element); }
                                    if (element.childNodes.length > 0 ) {
                                        retval = retval.concat(this.getElements(element));
                                    }
                                }
                            }
                            return retval;
                        }
                    ,focus: function (elem) {
                        elem.focus();
                        if (elem.select) elem.select();
                    }
                    ,getElementsByAttribute: function(attributeName, attributeValue, tagName, parent)
                        {
                            if (typeof attributeName == 'undefined' || attributeName == null) throw "Required arguement 'attributeName' missing in B2Bee.getElementsByAttribute";
                            
                            var elements = [];
                            var element = null;
                            var attribute = null;
                            var retval = [];
                            var elementsWithAttribute = []; // for debugging only
                            
                            if (typeof parent != "undefined" && parent != null && parent != '') {
                                if (typeof tagName) {
                                    elements = parent.getElementsByTagName(tagName);
                                }
                                else {
                                    elements = this.getElements(parent);
                                }
                            }
                            else {
                                if (typeof tagName != "undefined" && tagName != null && tagName != '' ) {
                                    elements = document.getElementsByTagName(tagName);
                                }
                                else {
                                    elements = this.getElements(document);
                                }
                            }
                            
                            /*
                             * Not all borwsers are equal.
                             * Some browsers only parse specific attributes from HTML which then become
                             * part of that elements DOM proprerties. However if they HTML attributes
                             * do not become part of the DOM objects direct properties, the HTML
                             * attributes are stored in an "attributes" array. The getAttribute()
                             * method is used to find those.
                             */
                            for (var i=0; i < elements.length; i++) {
                                element = elements[i];
                                if (element[attributeName] || ( element.getAttribute && element.getAttribute(attributeName))) elementsWithAttribute.push(element); // for debugging only
                                if (
                                    // first try to get element attribute using square bracket notation.
                                    (element[attributeName] && element[attributeName].search('(?:^|\\s)'+attributeValue+'(?:\\s|$)') >= 0 )
                                    // if that fails, try to use the getAttribute method
                                    //    - first to check that element has a getAttribute method
                                    //    - then check to see that it has that attribute
                                    //    - then check that attribute for the value
                                    || (element.getAttribute && element.getAttribute(attributeName) && element.getAttribute(attributeName).search('(?:^|\\s)'+attributeValue+'(?:\\s|$)') >= 0 )
                                    ) {
                                    retval.push(element);
                                }
                            }
                            return retval;
                        }
                    ,getElementsByClassName: function(className,parent)
                        {
                            if (typeof parent == 'undefined' || parent == null) {
                                parent = document;
                            }
                            
                            if (parent.getElementsByClassName) {
                                return parent.getElementsByClassName(className);
                            }
                            else {
                                var els = this.getElements(parent);
                                var retval = [];
                                if (els.length) {
                                    for(var i = 0; i < els.length; i++) {
                                        var el = els[i];
                                        if (this.hasClassName(el,className)) retval.push(el);
                                    }
                                }
                                return retval;
                            }
                        }
                    ,getNextSibling: function(node)
                        {
                            return YAHOO.util.Dom.getNextSibling(node);
                        }
                    ,hasClassName: function(node, name)
                        {
                            var retval = false;
                            if (typeof(node) != 'undefined' && node != null && node.className) retval = node.className.search(name) >= 0 ? true : false;
                            return retval;
                        }
                    ,removeChildren: function(node)
                        {
                            while (node.lastChild) {
                                node.removeChild(node.lastChild);
                            }
                        }
                    ,removeClassName: function(node, className)
                        {
                            if (typeof(node) === 'undefined') return false;
                            else return dojo.removeClass(node, className);
                        }
                    ,runOnReadyFuncts: function(funct)
                        {
                            for (var index in this.onReadyFuncts) {
                                this.onReadyFuncts[index]();
                            }
                        }
                }
            ,download: function(url,newWindow)
                {
                    if ( url ) {
                        if (!newWindow) {
                            /*
                             * Create an iframe and load the file to be downloaded in that iframe.
                             */
                            var ifrm = document.createElement("IFRAME"); 
                            ifrm.setAttribute("src", url); 
                            ifrm.style.width = 0+"px"; 
                            ifrm.style.height = 0+"px";
                            document.body.appendChild(ifrm);
                            return ifrm.contentWindow;
                        }
                        else {
                            /*
                             * Open a new window with the url to the file to be downloaded
                             */
                            var myWin = window.open(url,"b2bee-download");
                            return myWin;
                        }
                    }
                    return false;
                }
            ,events:
                {
                    addListener: function(elemId,event,funct,obj,scopeObj)
                        {
                            YAHOO.util.Event.addListener(elemId,event,funct,obj,scopeObj);
                        }
                    ,removeListener: function(elemId,event)
                        {
                            YAHOO.util.Event.removeListener(elemId,event);
                        }
                    ,stopEvent: function(event)
                        {
                            if (typeof event != 'undefined' && event !== null) {
                                if (typeof(event.cancelBubble) != 'undefined') {
                                    event.cancelBubble = true;
                                }
                                // handle event
                                if (typeof(event.stopPropagation) != 'undefined') {
                                    event.stopPropagation();
                                }                                
                                // handle event
                                if (typeof(event.preventBubble) != 'undefined') {
                                    event.preventBubble();
                                }                                
                                // handle event
                                if (typeof(event.preventCapture) != 'undefined') {
                                    event.preventCapture();
                                }                                
                                // handle event
                                if (typeof(event.preventDefault) != 'undefined') {
                                    event.preventDefault();
                                }                                
                                YAHOO.util.Event.stopEvent(event);
                            }
                            return true;
                        }
                }
            ,formatCurrency: function(num)
                {
                    /*try {
                        var currencySymbol = this.Company.CurrencySymbol;
                        var currencyThousandsSeparator = this.Company.CurrencyThousandsSeparator;
                        var currencyDecimalSeparator = this.Company.CurrencyDecimalSeparator;
                    }
                    catch (err) {
                    */
                        var currencySymbol = '$';
                        var currencyThousandsSeparator = ',';
                        var currencyDecimalSeparator = '.';
                    //}
                    num = num.toString().replace(/[^.0-9]/g,'');
                    if(isNaN(num)) num = "0";
                    sign = (num == (num = Math.abs(num)));
                    num = Math.floor( num * 100 + 0.50000000001 );
                    var cents = num % 100;
                    num = Math.floor( num / 100 ).toString();
                    if (cents < 10 ) cents = '0' + cents.toString();
                    for (var i = 0; i < Math.floor( ( num.length - ( 1 + i ) ) / 3 ); i++) {
                        num = num.substring( 0, num.length - ( 4 * i + 3 ) ) + currencyThousandsSeparator + num.substring( num.length - ( 4 * i + 3 ) );
                    }
                    return ( ((sign)?'':'-') + currencySymbol + num + currencyDecimalSeparator + cents );
                }
            ,formatDate: function(str, phpFormat)
                {
                    
                    //if (str === "0000-00-00 00:00:00" || str =='') return "";
                    if ( !str || str == null || str === "0000-00-00 00:00:00") str = 'now';
                    str = str.replace(/\s{2,}|^\s|\s$/g, ' '); // unecessary spaces
                    str = str.replace(/[\t\r\n]/g, ''); // unecessary chars       
                    
                    /*
                    B2BeeFormat = 'd-M-Y'; 
                    MySQLFormat = 'Ymdhis';
                    ISOFormat   = 'Y-m-d H:i:s';
                    */
                    
                    // TODO: re-write this to loop through the format param string and build a new pair of format strings, one for PHP and one for JS, from the format param
                    switch(phpFormat) {
                        case 'd':
                            jsFormat = "d";
                            break;
                        case 'd-M-Y':
                            jsFormat = "dd-mmm-yyyy";
                            break;
                        case 'isoDate':
                            phpFormat = 'Y-m-d';
                            jsFormat = "yyyy-mm-dd";
                            break;
                        case 'isoDateTime':
                            phpFormat = 'Y-m-d H:i:s';
                            jsFormat = "yyyy-mm-dd HH:MM:ss";
                            break;
                        case 'm':
                            phpFormat = 'm';
                            jsFormat = "m";
                            break;
                        case 'usDate':
                            phpFormat = 'm/d/Y';
                            jsFormat = "m/d/yy";
                            break;
                        case 'y':
                            jsFormat = "yy";
                            break;
                        case 'Y':
                            jsFormat = "yyyy";
                            break;
                        case 'Y-m-d':
                            jsFormat = "yyyy-mm-dd";
                            break;
                        case 'Y-M-d':
                            jsFormat = "yyyy-mmm-dd";
                            break;
                        case 'Y-m-d H:i:s':
                            jsFormat = "yyyy-mm-dd HH:MM:ss";
                            break;
                        case 'YmdHis':
                            jsFormat = "yyyymmddHHMMss";
                            break;
                        default:
                            phpFormat = 'Y-m-d';
                            jsFormat = "dd-mmm-yyyy";
                            break;
                    }
                    
                    // Force PHP format so that we can parse it for JS Date object.
                    phpFormat = 'Y-m-d H:i:s';
                    
                    // Match dd-mmm-yyyy format
                    var matches = str.match(/^(\d{2})[-.](\w{3})[.-](\d{4})$/i);
                    if (matches != null) {
                        var day = matches[1];
                        var month = B2Bee.util.indexOf(dateFormat.i18n.monthNames,matches[2]);
                        var year = matches[3];
                        var hour = 0;
                        var minute = 0;
                        var second = 0;
                    }
                    else {
                        var timestamp = B2Bee.PHP.strtotime(str);
                        var date = B2Bee.PHP.date(phpFormat,timestamp);
                        
                        var parts = date.split(" ");
                        var dateParts = parts[0].split("-");
                        if (typeof(parts[1]) === "undefined") parts[1] = "00:00:00";
                        var timeParts = parts[1].split(":");
                        var year = dateParts[0];
                        var month = ( isNaN(dateParts[1]) ? ( B2Bee.util.indexOf(dateFormat.i18n.monthNames,dateParts[1])) : dateParts[1] - 1 ); // JavaScript's date expects a 0 indexed month value.
                        var day = dateParts[2];
                        var hour = timeParts[0];
                        var minute = timeParts[1];
                        var second = timeParts[2];
                    }
                    
                    return new Date(year, month, day, hour, minute, second).format(jsFormat);
                    
                    return date;
                }
            ,indexOf: function(haystack,needle)
                {
                    if (haystack.indexOf) {
                        return haystack.indexOf(needle);
                    }
                    else {
                        for (var index in haystack) {
                            if (haystack[index] == needle) {
                                return index;
                            }
                        }
                    }
                    
                    return false;
                }
            ,JSON:
                {
                    decode: function(string)
                        {
                            return YAHOO.lang.JSON.parse(string);
                        }
                    ,encode: function(val)
                        {
                            return YAHOO.lang.JSON.stringify(val);
                        }
                }
        }
    ,window:
        {
            height: null
            ,print: function () { B2Bee.printScreen(); }
            ,updatePosition: function()
                {
                    this.height = YAHOO.util.Dom.getViewportHeight();
                    this.width  = YAHOO.util.Dom.getViewportWidth();
                    this.XPosition = YAHOO.util.Dom.getDocumentScrollLeft();
                    this.YPosition = YAHOO.util.Dom.getDocumentScrollTop();
                }
            ,width: null
            ,XPosition: null
            ,YPosition: null
        }
});
YAHOO.util.Event.onDOMReady(
    function()
        {
            window.domReady=true;
            B2Bee.init();
        }
    ); 

/**
 * Dojo elements used on multiple B2Bee pages.
 */
dojo.require('dojox.fx.scroll');
dojo.require('dojox.fx');
dojo.require("dijit.Dialog");
dojo.require("dijit.form.TextBox");
dojo.require("dijit.form.Textarea");
dojo.require("dijit.form.DateTextBox");
dojo.require("dojo.parser");
