function registerNamespaces() {
    for (var i = 0; i < arguments.length; i++) {
        var astrParts = arguments[i].split(".");
        var root = window;
        for (var j = 0; j < astrParts.length; j++) {
            if (!root[astrParts[j]]) {
                root[astrParts[j]] = new Object()
            }
            root = root[astrParts[j]]
        }
    }
}
registerNamespaces("Plaxo.Util");
Plaxo.Util.Timer = {
    timers: {},
    startTimer: function(id) {
        if (!this.enabled) return;
        this.timers.id = new Date().getTime()
    },
    getElapsedTime: function(id) {
        if (!this.enabled) return;
        var start = this.timers.id;
        if (!start) {
            alert('Unknown timer: ' + id)
        }
        return new Date().getTime() - start
    },
    alertElapsedTime: function(id) {
        if (!this.enabled) return;
        alert('Elapsed time for "' + id + '": ' + this.getElapsedTime(id))
    },
    enabled: true,
    setTimersEnabled: function(state) {
        this.enabled = state
    }
};
Plaxo.Util.Looper = {
    doLoop: function(list, func, doneFunc, loopSize, start) {
        if (!loopSize) loopSize = 500;
        if (!start) start = 0;
        var max = start + loopSize;
        var lastLoop = false;
        if (max > list.length) {
            max = list.length;
            lastLoop = true
        }
        for (var i = start; i < max; i++) {
            func(list, i)
        }
        if (lastLoop) {
            if (doneFunc) doneFunc()
        } else {
            setTimeout(function() {
                Plaxo.Util.Looper.doLoop(list, func, doneFunc, loopSize, max)
            },
            0)
        }
    }
};
registerNamespaces("Plaxo.Form");
Plaxo.Form = {
    getSelectValue: function(sel) {
        if (!sel) return null;
        if (!sel.options) return sel.value;
        return sel.options[sel.selectedIndex].value
    },
    focusFirstVisibleFormElem: function(f, findFirstBlankField) {
        for (var i = 0; i < f.length; i++) {
            var el = f.elements[i];
            if (el.type != 'hidden' && el.style.display != 'none' && (!findFirstBlankField || el.value.length == 0) && el.focus) {
                el.focus();
                break
            }
        }
    }
};
registerNamespaces("Plaxo.String");
Plaxo.String = {
    contains: function(whole, part) {
        return whole.indexOf(part) != -1
    },
    alnumChars: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_",
    isalnum: function(ch) {
        return this.contains(this.alnumChars, ch)
    },
    otherSafeEmailChars: ".-+=",
    findBoundary: function(s, start, forward) {
        if (forward) {
            for (var i = start; i < s.length; i++) {
                var ch = s.charAt(i);
                if (!Plaxo.String.isalnum(ch) && !this.contains(this.otherSafeEmailChars, ch)) {
                    return i - 1
                }
            }
            return s.length - 1
        } else {
            for (var i = start - 1; i >= 0; i--) {
                var ch = s.charAt(i);
                if (!Plaxo.String.isalnum(ch) && !this.contains(this.otherSafeEmailChars, ch)) {
                    return i + 1
                }
            }
            return 0
        }
    },
    removeDups: function(strs, ignoreCase) {
        var uniqueStrs = [];
        var oldStrs = {};
        for (var i = 0; i < strs.length; i++) {
            var s = strs[i];
            if (ignoreCase) s = s.toLowerCase();
            if (!oldStrs[s]) {
                uniqueStrs.push(strs[i]);
                oldStrs[s] = 1
            }
        }
        return uniqueStrs
    }
};
registerNamespaces("Plaxo.Debug");
Plaxo.Debug = {
    logLevel: 0,
    assert: function(expr, msg) {
        if (!expr) {
            if (!msg) msg = 'unk';
            throw new Error('Assertion failed: ' + msg)
        }
    },
    error: function(msg) {
        if (this.logLevel < 1) return;
        alert(msg);
        msg = this.format(msg, 1);
        if (this.dumpEnabled) dump(msg)
    },
    warning: function(msg) {
        if (this.logLevel < 2) return;
        msg = this.format(msg, 2);
        if (this.dumpEnabled) dump(msg);
        else alert(msg)
    },
    trace: function(msg) {
        if (this.logLevel < 3) return;
        msg = this.format(msg, 3);
        if (this.dumpEnabled) dump(msg);
        else window.status = msg
    },
    format: function(msg, level) {
        var d = new Date();
        return level + '|' + d.toLocaleTimeString() + '.' + d.getMilliseconds() + '|' + msg + '\n'
    },
    dumpEnabled: false,
    initialize: function() {
        var PREFS_CID = "@mozilla.org/preferences;1";
        var PREFS_I_PREF = "nsIPref";
        var PREF_STRING = "browser.dom.window.dump.enabled";
        try {
            var Pref = new Components.Constructor(PREFS_CID, PREFS_I_PREF);
            var pref = new Pref();
            pref.SetBoolPref(PREF_STRING, true);
            this.dumpEnabled = true
        } catch(e) {
            if (typeof(dump) != 'undefined') {
                this.dumpEnabled = true
            }
        }
    }
};
Plaxo.Debug.initialize();
function Array_push() {
    var A_p = 0;
    for (A_p = 0; A_p < arguments.length; A_p++) {
        this[this.length] = arguments[A_p]
    }
    return this.length
};
function Array_pop() {
    var response = this[this.length - 1];
    this.length--;
    return response
};
function Array_unshift() {
    this.reverse();
    for (var i = arguments.length - 1; i >= 0; i--) this[this.length] = arguments[i];
    this.reverse();
    return this.length
}
if (typeof(Array.prototype.unshift) == "undefined") {
    Array.prototype.unshift = Array_unshift
}
if (typeof(Array.prototype.pop) == "undefined") {
    Array.prototype.pop = Array_pop
}
if (typeof Array.prototype.push == "undefined") {
    Array.prototype.push = Array_push
};
function isWhitespace(c) {
    return c == ' ' || c == '\t' || c == '\r' || c == '\n'
};
function String_trim(trimset) {
    if (this.length == 0) return this;
    if (!trimset) trimset = " \t\r\n";
    var start = 0;
    while (start < this.length && trimset.indexOf(this.charAt(start)) != -1) start++;
    var end = this.length - 1;
    while (end > start && trimset.indexOf(this.charAt(end)) != -1) end--;
    if (start > 0 || end < this.length - 1) {
        return this.substring(start, end + 1)
    } else return this
}
if (typeof String.prototype.trim == "undefined") {
    String.prototype.trim = String_trim
};
function String_endsWith(s) {
    if (!s) return true;
    if (s.length > this.length) return false;
    var start = this.length - s.length;
    for (var i = 0; i < s.length; i++) {
        if (s.charAt(i) != this.charAt(start + i)) {
            return false
        }
    }
    return true
}
if (typeof String.prototype.endsWith == "undefined") {
    String.prototype.endsWith = String_endsWith
}


/* ******************* */
function inherits(child, parent) {
    if (typeof parent.prototype == 'function') {
        inherits(child, parent.prototype)
    }
    for (var method in parent.prototype) {
        if (method == 'prototype') {
            continue
        }
        child[method] = parent.prototype[method]
    }
};
function sprintf() {
    if (!arguments || arguments.length < 1 || !RegExp) {
        return
    }
    var str = arguments[0];
    var re = /([^%]*)%('.|0|\x20)?(-)?(\d+)?(\.\d+)?(%|b|c|d|u|f|o|s|x|X)(.*)/; //'
    var a = b = [],
    numSubstitutions = 0,
    numMatches = 0;
    while (a = re.exec(str)) {
        var leftpart = a[1],
        pPad = a[2],
        pJustify = a[3],
        pMinLength = a[4];
        var pPrecision = a[5],
        pType = a[6],
        rightPart = a[7];
        numMatches++;
        if (pType == '%') {
            subst = '%';
        } else {
            numSubstitutions++;
            if (numSubstitutions >= arguments.length) {
                alert('Error! Not enough function arguments (' + (arguments.length - 1) + ', excluding the string)\nfor the number of substitution parameters in string (' + numSubstitutions + ' so far).');
            }
            var param = arguments[numSubstitutions];
            var pad = '';
            if (pPad && pPad.substr(0, 1) == "'") pad = leftpart.substr(1, 1);
            else if (pPad) pad = pPad;
            var justifyRight = true;
            if (pJustify && pJustify === "-") justifyRight = false;
            var minLength = -1;
            if (pMinLength) minLength = parseInt(pMinLength);
            var precision = -1;
            if (pPrecision && pType == 'f') precision = parseInt(pPrecision.substring(1));
            var subst = param;
            if (pType == 'b') subst = parseInt(param).toString(2);
            else if (pType == 'c') subst = String.fromCharCode(parseInt(param));
            else if (pType == 'd') subst = parseInt(param) ? parseInt(param) : 0;
            else if (pType == 'u') subst = Math.abs(param);
            else if (pType == 'f') subst = (precision > -1) ? Math.round(parseFloat(param) * Math.pow(10, precision)) / Math.pow(10, precision) : parseFloat(param);
            else if (pType == 'o') subst = parseInt(param).toString(8);
            else if (pType == 's') subst = param;
            else if (pType == 'x') subst = ('' + parseInt(param).toString(16)).toLowerCase();
            else if (pType == 'X') subst = ('' + parseInt(param).toString(16)).toUpperCase()
        }
        str = leftpart + subst + rightPart
    }
    return str
};
function popup(url, title, width, height) {
    var numArgs = arguments.length;
    var ht;
    var windowObj;
    var windowParams = (numArgs > 4) ? arguments[4] : 'statusbar=no,menubar=no,toolbar=no,scrollbars=yes,resizable=yes,top=0';
    var isOffset = (numArgs > 7) ? arguments[7] : false;
    var offset;
    if (numArgs > 5) {
        if (isOffset) {
            offset = (window.screenY) ? window.screenY: self.screenTop;
            offset = (offset) ? offset: 0
        } else {
            offset = 0
        }
        offset += arguments[5];
        windowParams += (windowParams) ? ',': '';
        windowParams += 'top=' + offset + ',screenY=' + offset
    } else {
        windowParams += 'top=0,screenY=0'
    }
    if (numArgs > 6) {
        if (isOffset) {
            offset = (window.screenX) ? window.screenX: self.screenLeft;
            offset = (offset) ? offset: 0
        } else {
            offset = 0
        }
        offset += arguments[6];
        windowParams += ',left=' + offset + ',screenX=' + offset
    }
    if (screen.height) {
        ht = screen.height
    } else if (window.document.body.clientHeight) {
        ht = window.document.body.clientHeight
    } else if (window.innerHeight) {
        ht = window.innerHeight
    } else if (document.documentElement.clientHeight) {
        ht = document.documentElement.clientHeight
    } else {
        ht = 580
    }
    if ((height != 0) && (height > ht)) {
        height = ht
    }
    if (height != 0 && width != 0) {
        windowParams += ',height=' + height + ',width=' + width
    } else if (width != 0) {
        windowParams += ',width=' + width
    }
    windowObj = window.open(url, title, windowParams, false);
    if (windowObj) {
        windowObj.focus()
    }
    return windowObj
};
function plx_Browser() {
    var d = document;
    this.agt = navigator.userAgent.toLowerCase();
    this.major = parseInt(navigator.appVersion);
    this.dom = (d.getElementById) ? 1 : 0;
    this.ns = (d.layers);
    this.ns4up = (this.ns && this.major >= 4);
    this.ns4 = ((navigator.appName == "Netscape") && (parseInt(navigator.appVersion) == 4));
    this.ns6 = (this.dom && navigator.appName == "Netscape");
    this.op = this.agt.indexOf('opera') != -1;
    this.ie = (d.all);
    this.ie4 = (d.all && !this.dom) ? 1 : 0;
    this.ie4up = (this.ie && this.major >= 4);
    this.ie5 = (d.all && this.dom);
    this.win = ((this.agt.indexOf("win") != -1) || (this.agt.indexOf("16bit") != -1));
    this.mac = (this.agt.indexOf("mac") != -1);
    this.gecko = (this.agt.indexOf("gecko") != -1);
    this.safari = (this.agt.indexOf("safari") != -1);
    this.sp2 = (this.agt.indexOf('sv1') != -1)
}
var brz = new plx_Browser();

/* ************************************ */
registerNamespaces("Plaxo");
Plaxo.Util.Timer.setTimersEnabled(false);
Plaxo.byId = function(elem) {
    if (typeof elem == 'string') {
        elem = document.getElementById(elem)
    }
    return elem
};
Plaxo.Class = {
    create: function() {
        return function() {
            this.initialize.apply(this, arguments)
        }
    }
};
Plaxo.ABLauncher = Plaxo.Class.create();
Plaxo.ABLauncher.prototype = {
    initialize: function() {
        Plaxo.Debug.trace('initializing');
        this.name = "Plaxo.ABLauncher 1.0";
        this.abWin = null;
        this.textArea = null;
        this.currentEmails = {}
    },
    dialogWidth: 460,
    dialogHeight: 480,
    toQueryString: function(options) {
        var queryComponents = [];
        for (key in options) {
            if (typeof options[key] == 'function') continue;
            var queryComponent = encodeURIComponent(key) + '=' + encodeURIComponent(options[key]);
            queryComponents.push(queryComponent)
        }
        return queryComponents.join('&')
    },
    showABChooser: function(textArea, plaxoHost, callbackPage, extraOptions) {
        this.textArea = Plaxo.byId(textArea);
        if (!this.textArea) {
            Plaxo.Debug.error("can't find text area -> aborting");
            return
        }
        this.currentEmails = {};
        this.extractEmails(this.textArea.value);
        if (!this.abWin || this.abWin.closed) {
            if (callbackPage.length > 0 && callbackPage.charAt(0) != '/') {
                callbackPage = '/' + callbackPage
            }
            var cb = location.protocol + '//' + location.host + callbackPage;
            extraOptions.cb = cb;
            extraOptions.host = location.href;
            extraOptions.ts = new Date().getTime();
            var qs = this.toQueryString(extraOptions);
            var url = 'https://' + plaxoHost + '/ab_chooser?' + qs;
            if (extraOptions.plaxoMembersOnly) {
                url += '&direct=1'
            } else {
                var emails = this.getCurrentEmailList().join(',');
                url += '&t=import&emails=' + escape(emails)
            }
            this.abWin = popup(url, "PlaxoABC", this.dialogWidth, this.dialogHeight, 'resizable=no,scrollbars=no')
        }
        if (this.abWin) {
            this.abWin.focus()
        }
    },
    getCurrentEmailList: function() {
        var emails = [];
        for (email in this.currentEmails) {
            emails.push(email)
        }
        return emails
    },
    extractEmails: function(str) {
        var index = 0;
        while (true) {
            index = str.indexOf('@', index);
            if (index == -1) break;
            var start = Plaxo.String.findBoundary(str, index - 1, false);
            var end = Plaxo.String.findBoundary(str, index + 1, true);
            var email = str.substring(start, end + 1).toLowerCase();
            this.currentEmails[email] = 1;
            index++
        }
    },
    hasCurrentEmail: function(email) {
        return this.currentEmails[email.toLowerCase()]
    },
    addCheckedRecipients: function(text) {
        if (!text) return false;
        if (!this.textArea) {
            Plaxo.Debug.error('no text area to add recipients to');
            return false
        }
        var curText = this.textArea.value;
        if (curText && !curText.trim().endsWith(',')) curText += ', ';
        curText += text;
        this.setTextAreaValue(curText);
        return true
    },
    setTextAreaValue: function(str) {
        this.textArea.value = str
    }
};
Plaxo.abl = null;
function showPlaxoABChooser(textArea, callbackPage, plaxoHost, extraOptions) {
    if (!Plaxo.abl) Plaxo.abl = new Plaxo.ABLauncher();
    if (!plaxoHost) plaxoHost = 'www.plaxo.com';
    if (!extraOptions) extraOptions = {};
    Plaxo.abl.showABChooser(textArea, plaxoHost, callbackPage, extraOptions)
}