var datePickerController = (function datePickerController() {
    var debug = false,
        isOpera = Object.prototype.toString.call(window.opera) === "[object Opera]",
        isMoz = /mozilla/.test(navigator.userAgent.toLowerCase()) && !/(compatible|webkit)/.test(navigator.userAgent.toLowerCase()),
        languageInfo = parseUILanguage(),
        datePickers = {},
        uniqueId = 0,
        weeksInYearCache = {},
        localeImport = false,
        nbsp = String.fromCharCode(160),
        describedBy = "",
        nodrag = false,
        buttonTabIndex = true,
        returnLocaleDate = false,
        mouseWheel = true,
        cellFormat = "d-sp-F-sp-Y",
        titleFormat = "F-sp-d-cc-sp-Y",
        formatParts = isOpera ? ["placeholder"] : ["placeholder", "sp-F-sp-Y"],
        dividors = ["dt", "sl", "ds", "cc", "sp"],
        dvParts = "dt|sl|ds|cc|sp",
        dParts = "d|j",
        mParts = "m|n|M|F",
        yParts = "Y|y",
        kbEvent = false,
        bespokeTitles = {},
        finalOpacity = 100,
        validFmtRegExp = /^((sp|dt|sl|ds|cc)|([d|D|l|j|N|w|S|W|M|F|m|n|t|Y|y]))(-((sp|dt|sl|ds|cc)|([d|D|l|j|N|w|S|W|M|F|m|n|t|Y|y])))*$/,
        rangeRegExp = /^((\d\d\d\d)(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01]))$/,
        wcDateRegExp = /^(((\d\d\d\d)|(\*\*\*\*))((0[1-9]|1[012])|(\*\*))(0[1-9]|[12][0-9]|3[01]))$/;
    (function () {
        var scriptFiles = document.getElementsByTagName('script'),
            scriptInner = String(scriptFiles[scriptFiles.length - 1].innerHTML).replace(/[\n\r\s\t]+/g, " ").replace(/^\s+/, "").replace(/\s+$/, ""),
            json = parseJSON(scriptInner);
        if (typeof json === "object" && !("err" in json)) {
            affectJSON(json)
        };
        if (typeof (fdLocale) != "object") {
            var head = document.getElementsByTagName("head")[0] || document.documentElement,
                loc = scriptFiles[scriptFiles.length - 1].src.substr(0, scriptFiles[scriptFiles.length - 1].src.lastIndexOf("/")) + "/lang/",
                script;
            for (var i = 0; i < languageInfo.length; i++) {
                script = document.createElement('script');
                script.type = "text/javascript";
                script.src = loc + languageInfo[i] + ".js";
                script.charSet = "utf-8"; /*@cc_on/*@if(@_win32)var bases=document.getElementsByTagName('base');if(bases.length&&bases[0].childNodes.length){bases[0].appendChild(script)}else{document.getElementsByTagName('head')[0].appendChild(script)};bases=null;@else@*/
                head.appendChild(script); /*@end@*/
            };
            script = null
        } else {
            returnLocaleDate = true
        }
    })();

    function parseUILanguage() {
        var languageTag = document.getElementsByTagName('html')[0].getAttribute('lang') || document.getElementsByTagName('html')[0].getAttribute('xml:lang');
        if (!languageTag) {
            languageTag = "en"
        } else {
            languageTag = languageTag.toLowerCase()
        };
        return languageTag.search(/^([a-z]{2,3})-([a-z]{2})$/) != -1 ? [languageTag.match(/^([a-z]{2,3})-([a-z]{2})$/)[1], languageTag] : [languageTag]
    };

    function affectJSON(json) {
        if (typeof json !== "object") {
            return
        };
        for (key in json) {
            value = json[key];
            switch (key.toLowerCase()) {
                case "lang":
                    if (value.search(/^[a-z]{2,3}(-([a-z]{2}))?$/i) != -1) {
                        languageInfo = [value.toLowerCase()];
                        returnLocaleDate = true
                    };
                    break;
                case "nodrag":
                    nodrag = !!value;
                    break;
                case "buttontabindex":
                    buttonTabIndex = !!value;
                    break;
                case "mousewheel":
                    mouseWheel = !!value;
                    break;
                case "cellformat":
                    if (typeof value == "string" && value.match(validFmtRegExp)) {
                        parseCellFormat(value)
                    };
                    break;
                case "titleformat":
                    if (typeof value == "string" && value.match(validFmtRegExp)) {
                        titleFormat = value
                    };
                    break;
                case "describedby":
                    if (typeof value == "string") {
                        describedBy = value
                    };
                    break;
                case "finalopacity":
                    if (typeof value == 'number' && (+value > 20 && +value <= 100)) {
                        finalOpacity = parseInt(value, 10)
                    };
                    break;
                case "bespoketitles":
                    bespokeTitles = {};
                    for (var dt in value) {
                        bespokeTitles[dt] = value[dt]
                    }
            }
        }
    };

    function parseCellFormat(value) {
        if (isOpera) {
            formatParts = ["placeholder"];
            cellFormat = "j-sp-F-sp-Y";
            return
        };
        var parts = value.split("-"),
            fullParts = [],
            tmpParts = [],
            part;
        for (var pt = 0; pt < parts.length; pt++) {
            part = parts[pt];
            if (part == "j" || part == "d") {
                if (tmpParts.length) {
                    fullParts.push(tmpParts.join("-"));
                    tmpParts = []
                };
                fullParts.push("placeholder")
            } else {
                tmpParts.push(part)
            }
        };
        if (tmpParts.length) {
            fullParts.push(tmpParts.join("-"))
        };
        if (!fullParts.length || fullParts.length > 3) {
            formatParts = ["placeholder", "sp-F-sp-Y"];
            cellFormat = "j-sp-F-sp-Y";
            return
        };
        formatParts = fullParts;
        cellFormat = value
    };

    function pad(value, length) {
        length = length || 2;
        return "0000".substr(0, length - Math.min(String(value).length, length)) + value
    };

    function addEvent(obj, type, fn) {
        try {
            if (obj.attachEvent) {
                obj["e" + type + fn] = fn;
                obj[type + fn] = function () {
                    obj["e" + type + fn](window.event)
                };
                obj.attachEvent("on" + type, obj[type + fn])
            } else {
                obj.addEventListener(type, fn, true)
            }
        } catch (err) {}
    };

    function removeEvent(obj, type, fn) {
        try {
            if (obj.detachEvent) {
                obj.detachEvent("on" + type, obj[type + fn]);
                obj[type + fn] = null
            } else {
                obj.removeEventListener(type, fn, true)
            }
        } catch (err) {}
    };

    function stopEvent(e) {
        e = e || document.parentWindow.event;
        if (e.stopPropagation) {
            e.stopPropagation();
            e.preventDefault()
        }; /*@cc_on@if(@_win32)e.cancelBubble=true;e.returnValue=false;@end@*/
        return false
    };

    function parseJSON(str) {
        if (typeof str !== 'string' || str == "") {
            return {}
        };
        try {
            if (typeof JSON === "object" && JSON.parse) {
                return window.JSON.parse(str)
            } else if (/lang|buttontabindex|mousewheel|cellformat|titleformat|nodrag|describedby/.test(str.toLowerCase())) {
                var f = Function(['var document,top,self,window,parent,Number,Date,Object,Function,', 'Array,String,Math,RegExp,Image,ActiveXObject;', 'return (', str.replace(/<\!--.+-->/gim, '').replace(/\bfunction\b/g, 'function­'), ');'].join(''));
                return f()
            }
        } catch (e) {};
        if (debug) {
            throw "Could not parse the JSON object";
        };
        return {
            "err": "Could not parse the JSON object"
        }
    };

    function setARIARole(element, role) {
        if (element && element.tagName) {
            element.setAttribute("role", role)
        }
    };

    function setARIAProperty(element, property, value) {
        if (element && element.tagName) {
            element.setAttribute("aria-" + property, value)
        }
    };

    function datePicker(options) {
        this.dateSet = null;
        this.timerSet = false;
        this.visible = false;
        this.fadeTimer = null;
        this.timer = null;
        this.yearInc = 0;
        this.monthInc = 0;
        this.dayInc = 0;
        this.mx = 0;
        this.my = 0;
        this.x = 0;
        this.y = 0;
        this.created = false;
        this.disabled = false;
        this.opacity = 0;
        this.opacityTo = 99;
        this.inUpdate = false;
        this.kbEventsAdded = false;
        this.fullCreate = false;
        this.selectedTD = null;
        this.cursorTD = null;
        this.cursorDate = options.cursorDate ? options.cursorDate : "", this.date = options.cursorDate ? new Date(+options.cursorDate.substr(0, 4), +options.cursorDate.substr(4, 2) - 1, +options.cursorDate.substr(6, 2)) : new Date();
        this.defaults = {};
        this.dynDisabledDates = {};
        this.firstDayOfWeek = localeImport.firstDayOfWeek;
        this.interval = new Date();
        this.clickActivated = false;
        this.noFocus = true;
        this.kbEvent = false;
        this.disabledDates = false;
        this.enabledDates = false;
        this.delayedUpdate = false;
        this.bespokeTitles = {};
        for (var thing in options) {
            if (thing.search(/callbacks|formElements|formatMasks/) != -1) continue;
            this[thing] = options[thing]
        }; /*@cc_on@if(@_win32)this.iePopUp=null;this.isIE7=false;@end@*/ /*@cc_on@if(@_jscript_version<=5.7)this.isIE7=document.documentElement&&typeof document.documentElement.style.maxHeight!="undefined";@end@*/
        for (var i = 0, prop; prop = ["callbacks", "formElements", "formatMasks"][i]; i++) {
            this[prop] = {};
            for (var thing in options[prop]) {
                this[prop][thing] = options[prop][thing]
            }
        };
        this.date.setHours(5);
        this.changeHandler = function () {
            o.setDateFromInput();
            o.callback("dateset", o.createCbArgObj())
        };
        this.createCbArgObj = function () {
            return this.dateSet ? {
                "id": this.id,
                "date": this.dateSet,
                "dd": pad(this.date.getDate()),
                "mm": pad(this.date.getMonth() + 1),
                "yyyy": this.date.getFullYear()
            } : {
                "id": this.id,
                "date": null,
                "dd": null,
                "mm": null,
                "yyyy": null
            }
        };
        this.getScrollOffsets = function () {
            if (typeof (window.pageYOffset) == 'number') {
                return [window.pageXOffset, window.pageYOffset]
            } else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
                return [document.body.scrollLeft, document.body.scrollTop]
            } else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
                return [document.documentElement.scrollLeft, document.documentElement.scrollTop]
            };
            return [0, 0]
        };
        this.reposition = function () {
            if (!o.created || o.staticPos) {
                return
            };
            o.div.style.visibility = "hidden";
            o.div.style.left = o.div.style.top = "0px";
            o.div.style.display = "block";
            var osh = o.div.offsetHeight,
                osw = o.div.offsetWidth,
                elem = document.getElementById('fd-but-' + o.id),
                pos = o.truePosition(elem),
                trueBody = (document.compatMode && document.compatMode != "BackCompat") ? document.documentElement : document.body,
                sOffsets = o.getScrollOffsets(),
                scrollTop = sOffsets[1],
                scrollLeft = sOffsets[0],
                fitsBottom = parseInt(trueBody.clientHeight + scrollTop) > parseInt(osh + pos[1] + elem.offsetHeight + 2),
                fitsTop = parseInt(pos[1] - (osh + elem.offsetHeight + 2)) > parseInt(scrollTop);
            o.div.style.visibility = "visible";
            o.div.style.left = Number(parseInt(trueBody.clientWidth + scrollLeft) < parseInt(osw + pos[0]) ? Math.abs(parseInt((trueBody.clientWidth + scrollLeft) - osw)) : pos[0]) + "px";
            o.div.style.top = (fitsBottom || !fitsTop) ? Math.abs(parseInt(pos[1] + elem.offsetHeight + 2)) + "px" : Math.abs(parseInt(pos[1] - (osh + 2))) + "px"; /*@cc_on@if(@_jscript_version<=5.7)if(o.isIE7)return;o.iePopUp.style.top=o.div.style.top;o.iePopUp.style.left=o.div.style.left;o.iePopUp.style.width=osw+"px";o.iePopUp.style.height=(osh-2)+"px";@end@*/
        };
        this.removeOldFocus = function () {
            var td = document.getElementById(o.id + "-date-picker-hover");
            if (td) {
                try {
                    td.setAttribute(! /*@cc_on!@*/ false ? "tabIndex" : "tabindex", "-1");
                    td.tabIndex = -1;
                    td.className = td.className.replace(/date-picker-hover/, "");
                    td.id = "";
                    td.onblur = null;
                    td.onfocus = null
                } catch (err) {}
            }
        };
        this.addAccessibleDate = function () {
            var td = document.getElementById(o.id + "-date-picker-hover");
            if (td && !(td.getElementsByTagName("span").length)) {
                var ymd = td.className.match(/cd-([\d]{4})([\d]{2})([\d]{2})/),
                    noS = (td.className.search(/date-picker-unused|out-of-range|day-disabled|no-selection|not-selectable/) != -1),
                    spn = document.createElement('span'),
                    spnC;
                spn.className = "fd-screen-reader";
                while (td.firstChild) td.removeChild(td.firstChild);
                if (noS) {
                    spnC = spn.cloneNode(false);
                    spnC.appendChild(document.createTextNode(getTitleTranslation(13)));
                    td.appendChild(spnC)
                };
                for (var pt = 0, part; part = formatParts[pt]; pt++) {
                    if (part == "placeholder") {
                        td.appendChild(document.createTextNode(+ymd[3]))
                    } else {
                        spnC = spn.cloneNode(false);
                        spnC.appendChild(document.createTextNode(printFormattedDate(new Date(ymd[1], +ymd[2] - 1, ymd[3]), part, true)));
                        td.appendChild(spnC)
                    }
                }
            }
        };
        this.setNewFocus = function () {
            var td = document.getElementById(o.id + "-date-picker-hover");
            if (td) {
                try {
                    td.setAttribute(! /*@cc_on!@*/ false ? "tabIndex" : "tabindex", "0");
                    td.tabIndex = 0;
                    td.className = td.className.replace(/date-picker-hover/, "") + " date-picker-hover";
                    if (!this.clickActivated) {
                        td.onblur = o.onblur;
                        td.onfocus = o.onfocus
                    };
                    if (!isOpera && !this.clickActivated) o.addAccessibleDate();
                    if (!this.noFocus && !this.clickActivated) {
                        setTimeout(function () {
                            try {
                                td.focus()
                            } catch (err) {}
                        }, 0)
                    }
                } catch (err) {}
            }
        };
        this.setCursorDate = function (yyyymmdd) {
            if (String(yyyymmdd).search(/^([0-9]{8})$/) != -1) {
                this.date = new Date(+yyyymmdd.substr(0, 4), +yyyymmdd.substr(4, 2) - 1, +yyyymmdd.substr(6, 2));
                this.cursorDate = yyyymmdd;
                if (this.staticPos) {
                    this.updateTable()
                }
            }
        };
        this.updateTable = function (noCallback) {
            if (!o || o.inUpdate || !o.created) return;
            o.inUpdate = true;
            o.removeOldFocus();
            if (o.timerSet && !o.delayedUpdate) {
                if (o.monthInc) {
                    var n = o.date.getDate(),
                        d = new Date(o.date);
                    d.setDate(2);
                    d.setMonth(d.getMonth() + o.monthInc * 1);
                    d.setDate(Math.min(n, daysInMonth(d.getMonth(), d.getFullYear())));
                    o.date = new Date(d)
                } else {
                    o.date.setDate(Math.min(o.date.getDate() + o.dayInc, daysInMonth(o.date.getMonth() + o.monthInc, o.date.getFullYear() + o.yearInc)));
                    o.date.setMonth(o.date.getMonth() + o.monthInc);
                    o.date.setFullYear(o.date.getFullYear() + o.yearInc)
                }
            };
            o.outOfRange();
            if (!o.noToday) {
                o.disableTodayButton()
            };
            o.showHideButtons(o.date);
            var cd = o.date.getDate(),
                cm = o.date.getMonth(),
                cy = o.date.getFullYear(),
                cursorDate = (String(cy) + pad(cm + 1) + pad(cd)),
                tmpDate = new Date(cy, cm, 1);
            tmpDate.setHours(5);
            var dt, cName, td, i, currentDate, cellAdded, col, currentStub, abbr, bespokeRenderClass, spnC, dateSetD, weekDayC = (tmpDate.getDay() + 6) % 7,
                firstColIndex = (((weekDayC - o.firstDayOfWeek) + 7) % 7) - 1,
                dpm = daysInMonth(cm, cy),
                today = new Date(),
                stub = String(tmpDate.getFullYear()) + pad(tmpDate.getMonth() + 1),
                cellAdded = [4, 4, 4, 4, 4, 4],
                lm = new Date(cy, cm - 1, 1),
                nm = new Date(cy, cm + 1, 1),
                daySub = daysInMonth(lm.getMonth(), lm.getFullYear()),
                stubN = String(nm.getFullYear()) + pad(nm.getMonth() + 1),
                stubP = String(lm.getFullYear()) + pad(lm.getMonth() + 1),
                weekDayN = (nm.getDay() + 6) % 7,
                weekDayP = (lm.getDay() + 6) % 7,
                today = today.getFullYear() + pad(today.getMonth() + 1) + pad(today.getDate()),
                spn = document.createElement('span');
            o.firstDateShown = !o.constrainSelection && o.fillGrid && (0 - firstColIndex < 1) ? String(stubP) + (daySub + (0 - firstColIndex)) : stub + "01";
            o.lastDateShown = !o.constrainSelection && o.fillGrid ? stubN + pad(41 - firstColIndex - dpm) : stub + String(dpm);
            o.currentYYYYMM = stub;
            bespokeRenderClass = o.callback("redraw", {
                id: o.id,
                dd: pad(cd),
                mm: pad(cm + 1),
                yyyy: cy,
                firstDateDisplayed: o.firstDateShown,
                lastDateDisplayed: o.lastDateShown
            }) || {};
            dts = o.getDates(cy, cm + 1);
            o.checkSelectedDate();
            dateSetD = (o.dateSet != null) ? o.dateSet.getFullYear() + pad(o.dateSet.getMonth() + 1) + pad(o.dateSet.getDate()) : false;
            spn.className = "fd-screen-reader";
            if (this.selectedTD != null) {
                setARIAProperty(this.selectedTD, "selected", false);
                this.selectedTD = null
            };
            for (var curr = 0; curr < 42; curr++) {
                row = Math.floor(curr / 7);
                td = o.tds[curr];
                spnC = spn.cloneNode(false);
                while (td.firstChild) td.removeChild(td.firstChild);
                if ((curr > firstColIndex && curr <= (firstColIndex + dpm)) || o.fillGrid) {
                    currentStub = stub;
                    weekDay = weekDayC;
                    dt = curr - firstColIndex;
                    cName = [];
                    selectable = true;
                    if (dt < 1) {
                        dt = daySub + dt;
                        currentStub = stubP;
                        weekDay = weekDayP;
                        selectable = !o.constrainSelection;
                        cName.push("month-out")
                    } else if (dt > dpm) {
                        dt -= dpm;
                        currentStub = stubN;
                        weekDay = weekDayN;
                        selectable = !o.constrainSelection;
                        cName.push("month-out")
                    };
                    weekDay = (weekDay + dt + 6) % 7;
                    cName.push("day-" + localeDefaults.dayAbbrs[weekDay].toLowerCase());
                    currentDate = currentStub + String(dt < 10 ? "0" : "") + dt;
                    if (o.rangeLow && +currentDate < +o.rangeLow || o.rangeHigh && +currentDate > +o.rangeHigh) {
                        td.className = "out-of-range";
                        td.title = "";
                        td.appendChild(document.createTextNode(dt));
                        if (o.showWeeks) {
                            cellAdded[row] = Math.min(cellAdded[row], 2)
                        }
                    } else {
                        if (selectable) {
                            td.title = titleFormat ? printFormattedDate(new Date(+String(currentStub).substr(0, 4), +String(currentStub).substr(4, 2) - 1, +dt), titleFormat, true) : "";
                            cName.push("cd-" + currentDate + " yyyymm-" + currentStub + " mmdd-" + currentStub.substr(4, 2) + pad(dt))
                        } else {
                            td.title = titleFormat ? getTitleTranslation(13) + " " + printFormattedDate(new Date(+String(currentStub).substr(0, 4), +String(currentStub).substr(4, 2) - 1, +dt), titleFormat, true) : "";
                            cName.push("yyyymm-" + currentStub + " mmdd-" + currentStub.substr(4, 2) + pad(dt) + " not-selectable")
                        }; if (currentDate == today) {
                            cName.push("date-picker-today")
                        };
                        if (dateSetD == currentDate) {
                            cName.push("date-picker-selected-date");
                            setARIAProperty(td, "selected", "true");
                            this.selectedTD = td
                        };
                        if (o.disabledDays[weekDay] || dts[currentDate] == 0) {
                            cName.push("day-disabled");
                            if (titleFormat && selectable) {
                                td.title = getTitleTranslation(13) + " " + td.title
                            }
                        }
                        if (currentDate in bespokeRenderClass) {
                            cName.push(bespokeRenderClass[currentDate])
                        }
                        if (o.highlightDays[weekDay]) {
                            cName.push("date-picker-highlight")
                        };
                        if (cursorDate == currentDate) {
                            td.id = o.id + "-date-picker-hover"
                        };
                        td.appendChild(document.createTextNode(dt));
                        td.className = cName.join(" ");
                        if (o.showWeeks) {
                            cellAdded[row] = Math.min(cName[0] == "month-out" ? 3 : 1, cellAdded[row])
                        }
                    }
                } else {
                    td.className = "date-picker-unused";
                    td.appendChild(document.createTextNode(nbsp));
                    td.title = ""
                }; if (o.showWeeks && curr - (row * 7) == 6) {
                    while (o.wkThs[row].firstChild) o.wkThs[row].removeChild(o.wkThs[row].firstChild);
                    o.wkThs[row].appendChild(document.createTextNode(cellAdded[row] == 4 && !o.fillGrid ? nbsp : getWeekNumber(cy, cm, curr - firstColIndex - 6)));
                    o.wkThs[row].className = "date-picker-week-header" + (["", "", " out-of-range", " month-out", ""][cellAdded[row]])
                }
            };
            var span = o.titleBar.getElementsByTagName("span");
            while (span[0].firstChild) span[0].removeChild(span[0].firstChild);
            while (span[1].firstChild) span[1].removeChild(span[1].firstChild);
            span[0].appendChild(document.createTextNode(getMonthTranslation(cm, false) + nbsp));
            span[1].appendChild(document.createTextNode(cy));
            if (o.timerSet) {
                o.timerInc = 50 + Math.round(((o.timerInc - 50) / 1.8));
                o.timer = window.setTimeout(o.updateTable, o.timerInc)
            };
            o.inUpdate = o.delayedUpdate = false;
            o.setNewFocus()
        };
        this.destroy = function () {
            if (document.getElementById("fd-but-" + this.id)) {
                document.getElementById("fd-but-" + this.id).parentNode.removeChild(document.getElementById("fd-but-" + this.id))
            };
            if (!this.created) {
                return
            };
            removeEvent(this.table, "mousedown", o.onmousedown);
            removeEvent(this.table, "mouseover", o.onmouseover);
            removeEvent(this.table, "mouseout", o.onmouseout);
            removeEvent(document, "mousedown", o.onmousedown);
            removeEvent(document, "mouseup", o.clearTimer);
            if (window.addEventListener && !window.devicePixelRatio) {
                try {
                    window.removeEventListener('DOMMouseScroll', this.onmousewheel, false)
                } catch (err) {}
            } else {
                removeEvent(document, "mousewheel", this.onmousewheel);
                removeEvent(window, "mousewheel", this.onmousewheel)
            };
            o.removeOnFocusEvents();
            clearTimeout(o.fadeTimer);
            clearTimeout(o.timer); /*@cc_on@if(@_jscript_version<=5.7)if(!o.staticPos&&!o.isIE7){try{o.iePopUp.parentNode.removeChild(o.iePopUp);o.iePopUp=null}catch(err){}};@end@*/
            if (this.div && this.div.parentNode) {
                this.div.parentNode.removeChild(this.div)
            };
            o = null
        };
        this.resizeInlineDiv = function () {
            o.div.style.width = o.table.offsetWidth + "px";
            o.div.style.height = o.table.offsetHeight + "px"
        };
        this.create = function () {
            if (document.getElementById("fd-" + this.id)) return;
            this.noFocus = true;

            function createTH(details) {
                var th = document.createElement('th');
                if (details.thClassName) th.className = details.thClassName;
                if (details.colspan) { /*@cc_on/*@if(@_win32)th.setAttribute('colSpan',details.colspan);@else@*/
                    th.setAttribute('colspan', details.colspan); /*@end@*/
                }; /*@cc_on/*@if(@_win32)th.unselectable="on";/*@end@*/
                return th
            };

            function createThAndButton(tr, obj) {
                for (var i = 0, details; details = obj[i]; i++) {
                    var th = createTH(details);
                    tr.appendChild(th);
                    var but = document.createElement('span');
                    but.className = details.className;
                    but.id = o.id + details.id;
                    but.appendChild(document.createTextNode(details.text || o.nbsp));
                    but.title = details.title || ""; /*@cc_on/*@if(@_win32)th.unselectable=but.unselectable="on";/*@end@*/
                    th.appendChild(but)
                }
            };
            this.div = document.createElement('div');
            this.div.id = "fd-" + this.id;
            this.div.className = "datePicker";
            this.div.style.visibility = "hidden";
            this.div.style.display = "none";
            if (this.describedBy && document.getElementById(this.describedBy)) {
                setARIAProperty(this.div, "describedby", this.describedBy)
            };
            if (this.labelledBy) {
                setARIAProperty(this.div, "labelledby", this.labelledBy.id)
            };
            var tr, row, col, tableHead, tableBody, tableFoot;
            this.table = document.createElement('table');
            this.table.className = "datePickerTable";
            this.table.onmouseover = this.onmouseover;
            this.table.onmouseout = this.onmouseout;
            this.table.onclick = this.onclick;
            if (this.staticPos) {
                this.table.onmousedown = this.onmousedown
            };
            this.div.appendChild(this.table);
            var dragEnabledCN = !this.dragDisabled ? " drag-enabled" : "";
            if (!this.staticPos) {
                this.div.style.visibility = "hidden";
                this.div.className += dragEnabledCN;
                document.getElementsByTagName('body')[0].appendChild(this.div); /*@cc_on@if(@_jscript_version<=5.7)if(!this.isIE7){this.iePopUp=document.createElement('iframe');this.iePopUp.src="javascript:'<html></html>';";this.iePopUp.setAttribute('className','iehack');this.iePopUp.setAttribute("tabIndex",-1);setARIARole(this.iePopUp,"presentation");setARIAProperty(this.iePopUp,"hidden","true");this.iePopUp.scrolling="no";this.iePopUp.frameBorder="0";this.iePopUp.name=this.iePopUp.id=this.id+"-iePopUpHack";document.body.appendChild(this.iePopUp)};@end@*/
                setARIAProperty(this.div, "hidden", "true")
            } else {
                elem = document.getElementById(this.positioned ? this.positioned : this.id);
                if (!elem) {
                    this.div = null;
                    if (debug) throw this.positioned ? "Could not locate a datePickers associated parent element with an id:" + this.positioned : "Could not locate a datePickers associated input with an id:" + this.id;
                    return
                };
                this.div.className += " static-datepicker";
                if (this.positioned) {
                    elem.appendChild(this.div)
                } else {
                    elem.parentNode.insertBefore(this.div, elem.nextSibling)
                }; if (this.hideInput) {
                    for (var elemID in this.formElements) {
                        elem = document.getElementById(elemID);
                        if (elem) {
                            elem.className += " fd-hidden-input"
                        }
                    }
                };
                setTimeout(this.resizeInlineDiv, 300)
            };
            setARIARole(this.div, "grid");
            if (this.statusFormat) {
                tableFoot = document.createElement('tfoot');
                this.table.appendChild(tableFoot);
                tr = document.createElement('tr');
                tr.className = "date-picker-tfoot";
                tableFoot.appendChild(tr);
                this.statusBar = createTH({
                    thClassName: "date-picker-statusbar" + dragEnabledCN,
                    colspan: this.showWeeks ? 8 : 7
                });
                tr.appendChild(this.statusBar);
                this.updateStatus()
            };
            tableHead = document.createElement('thead');
            this.table.appendChild(tableHead);
            tr = document.createElement('tr');
            setARIARole(tr, "presentation");
            tableHead.appendChild(tr);
            this.titleBar = createTH({
                thClassName: "date-picker-title" + dragEnabledCN,
                colspan: this.showWeeks ? 8 : 7
            });
            tr.appendChild(this.titleBar);
            tr = null;
            var span = document.createElement('span');
            span.appendChild(document.createTextNode(nbsp));
            span.className = "month-display" + dragEnabledCN;
            this.titleBar.appendChild(span);
            span = document.createElement('span');
            span.appendChild(document.createTextNode(nbsp));
            span.className = "year-display" + dragEnabledCN;
            this.titleBar.appendChild(span);
            span = null;
            tr = document.createElement('tr');
            setARIARole(tr, "presentation");
            tableHead.appendChild(tr);
            createThAndButton(tr, [{
                className: "prev-but prev-year",
                id: "-prev-year-but",
                text: "\u00AB",
                title: getTitleTranslation(2)
            }, {
                className: "prev-but prev-month",
                id: "-prev-month-but",
                text: "\u2039",
                title: getTitleTranslation(0)
            }, {
                colspan: this.showWeeks ? 4 : 3,
                className: "today-but",
                id: "-today-but",
                text: getTitleTranslation(4)
            }, {
                className: "next-but next-month",
                id: "-next-month-but",
                text: "\u203A",
                title: getTitleTranslation(1)
            }, {
                className: "next-but next-year",
                id: "-next-year-but",
                text: "\u00BB",
                title: getTitleTranslation(3)
            }]);
            tableBody = document.createElement('tbody');
            this.table.appendChild(tableBody);
            var colspanTotal = this.showWeeks ? 8 : 7,
                colOffset = this.showWeeks ? 0 : -1,
                but, abbr;
            for (var rows = 0; rows < 7; rows++) {
                row = document.createElement('tr');
                if (rows != 0) {
                    setARIARole(row, "row");
                    tableBody.appendChild(row)
                } else {
                    tableHead.appendChild(row)
                };
                for (var cols = 0; cols < colspanTotal; cols++) {
                    if (rows === 0 || (this.showWeeks && cols === 0)) {
                        col = document.createElement('th')
                    } else {
                        col = document.createElement('td');
                        setARIAProperty(col, "describedby", this.id + "-col-" + cols + (this.showWeeks ? " " + this.id + "-row-" + rows : ""));
                        setARIAProperty(col, "selected", "false")
                    }; /*@cc_on@*/ /*@if(@_win32)col.unselectable="on";/*@end@*/
                    row.appendChild(col);
                    if ((this.showWeeks && cols > 0 && rows > 0) || (!this.showWeeks && rows > 0)) {
                        setARIARole(col, "gridcell")
                    } else {
                        if (rows === 0 && cols > colOffset) {
                            col.className = "date-picker-day-header";
                            col.scope = "col";
                            setARIARole(col, "columnheader");
                            col.id = this.id + "-col-" + cols
                        } else {
                            col.className = "date-picker-week-header";
                            col.scope = "row";
                            setARIARole(col, "rowheader");
                            col.id = this.id + "-row-" + rows
                        }
                    }
                }
            };
            col = row = null;
            this.ths = this.table.getElementsByTagName('thead')[0].getElementsByTagName('tr')[2].getElementsByTagName('th');
            for (var y = 0; y < colspanTotal; y++) {
                if (y == 0 && this.showWeeks) {
                    this.ths[y].appendChild(document.createTextNode(getTitleTranslation(6)));
                    this.ths[y].title = getTitleTranslation(8);
                    continue
                };
                if (y > (this.showWeeks ? 0 : -1)) {
                    but = document.createElement("span");
                    but.className = "fd-day-header"; /*@cc_on@*/ /*@if(@_win32)but.unselectable="on";/*@end@*/
                    this.ths[y].appendChild(but)
                }
            };
            but = null;
            this.trs = this.table.getElementsByTagName('tbody')[0].getElementsByTagName('tr');
            this.tds = this.table.getElementsByTagName('tbody')[0].getElementsByTagName('td');
            this.butPrevYear = document.getElementById(this.id + "-prev-year-but");
            this.butPrevMonth = document.getElementById(this.id + "-prev-month-but");
            this.butToday = document.getElementById(this.id + "-today-but");
            this.butNextYear = document.getElementById(this.id + "-next-year-but");
            this.butNextMonth = document.getElementById(this.id + "-next-month-but");
            if (this.noToday) {
                this.butToday.style.display = "none"
            };
            if (this.showWeeks) {
                this.wkThs = this.table.getElementsByTagName('tbody')[0].getElementsByTagName('th');
                this.div.className += " weeks-displayed"
            };
            tableBody = tableHead = tr = createThAndButton = createTH = null;
            if (this.rangeLow && this.rangeHigh && (this.rangeHigh - this.rangeLow < 7)) {
                this.equaliseDates()
            };
            this.updateTableHeaders();
            this.created = true;
            this.updateTable();
            if (this.staticPos) {
                this.visible = true;
                this.opacity = this.opacityTo = this.finalOpacity;
                this.div.style.visibility = "visible";
                this.div.style.display = "block";
                this.noFocus = true;
                this.fade()
            } else {
                this.reposition();
                this.div.style.visibility = "visible";
                this.fade();
                this.noFocus = true
            };
            this.callback("domcreate", {
                "id": this.id
            })
        };
        this.fade = function () {
            window.clearTimeout(o.fadeTimer);
            o.fadeTimer = null;
            var diff = Math.round(o.opacity + ((o.opacityTo - o.opacity) / 4));
            o.setOpacity(diff);
            if (Math.abs(o.opacityTo - diff) > 3 && !o.noFadeEffect) {
                o.fadeTimer = window.setTimeout(o.fade, 50)
            } else {
                o.setOpacity(o.opacityTo);
                if (o.opacityTo == 0) {
                    o.div.style.display = "none";
                    o.div.style.visibility = "hidden";
                    setARIAProperty(o.div, "hidden", "true");
                    o.visible = false
                } else {
                    setARIAProperty(o.div, "hidden", "false");
                    o.visible = true
                }
            }
        };
        this.trackDrag = function (e) {
            e = e || window.event;
            var diffx = (e.pageX ? e.pageX : e.clientX ? e.clientX : e.x) - o.mx;
            var diffy = (e.pageY ? e.pageY : e.clientY ? e.clientY : e.Y) - o.my;
            o.div.style.left = Math.round(o.x + diffx) > 0 ? Math.round(o.x + diffx) + 'px' : "0px";
            o.div.style.top = Math.round(o.y + diffy) > 0 ? Math.round(o.y + diffy) + 'px' : "0px"; /*@cc_on@if(@_jscript_version<=5.7)if(o.staticPos||o.isIE7)return;o.iePopUp.style.top=o.div.style.top;o.iePopUp.style.left=o.div.style.left;@end@*/
        };
        this.stopDrag = function (e) {
            var b = document.getElementsByTagName("body")[0];
            b.className = b.className.replace(/fd-drag-active/g, "");
            removeEvent(document, 'mousemove', o.trackDrag, false);
            removeEvent(document, 'mouseup', o.stopDrag, false);
            o.div.style.zIndex = 9999
        };
        this.onmousedown = function (e) {
            e = e || document.parentWindow.event;
            var el = e.target != null ? e.target : e.srcElement,
                origEl = el,
                hideDP = true,
                reg = new RegExp("^fd-(but-)?" + o.id + "$");
            o.mouseDownElem = null;
            while (el) {
                if (el.id && el.id.length && el.id.search(reg) != -1) {
                    hideDP = false;
                    break
                };
                try {
                    el = el.parentNode
                } catch (err) {
                    break
                }
            };
            if (hideDP) {
                hideAll();
                return true
            };
            if ((o.div.className + origEl.className).search('fd-disabled') != -1) {
                return true
            };
            if (origEl.id.search(new RegExp("^" + o.id + "(-prev-year-but|-prev-month-but|-next-month-but|-next-year-but)$")) != -1) {
                o.mouseDownElem = origEl;
                addEvent(document, "mouseup", o.clearTimer);
                addEvent(origEl, "mouseout", o.clearTimer);
                var incs = {
                        "-prev-year-but": [0, -1, 0],
                        "-prev-month-but": [0, 0, -1],
                        "-next-year-but": [0, 1, 0],
                        "-next-month-but": [0, 0, 1]
                    },
                    check = origEl.id.replace(o.id, ""),
                    dateYYYYMM = Number(o.date.getFullYear() + pad(o.date.getMonth() + 1));
                o.timerInc = 800;
                o.timerSet = true;
                o.dayInc = incs[check][0];
                o.yearInc = incs[check][1];
                o.monthInc = incs[check][2];
                o.accellerator = 1;
                if (!(o.currentYYYYMM == dateYYYYMM)) {
                    if ((o.currentYYYYMM < dateYYYYMM && (o.yearInc == -1 || o.monthInc == -1)) || (o.currentYYYYMM > dateYYYYMM && (o.yearInc == 1 || o.monthInc == 1))) {
                        o.delayedUpdate = false;
                        o.timerInc = 1200
                    } else {
                        o.delayedUpdate = true;
                        o.timerInc = 800
                    }
                };
                o.updateTable();
                return stopEvent(e)
            } else if (el.className.search("drag-enabled") != -1) {
                o.mx = e.pageX ? e.pageX : e.clientX ? e.clientX : e.x;
                o.my = e.pageY ? e.pageY : e.clientY ? e.clientY : e.Y;
                o.x = parseInt(o.div.style.left);
                o.y = parseInt(o.div.style.top);
                addEvent(document, 'mousemove', o.trackDrag, false);
                addEvent(document, 'mouseup', o.stopDrag, false);
                var b = document.getElementsByTagName("body")[0];
                b.className = b.className.replace(/fd-drag-active/g, "") + " fd-drag-active";
                o.div.style.zIndex = 10000;
                return stopEvent(e)
            };
            return true
        };
        this.onclick = function (e) {
            if (o.opacity != o.opacityTo || o.disabled) return stopEvent(e);
            e = e || document.parentWindow.event;
            var el = e.target != null ? e.target : e.srcElement;
            while (el.parentNode) {
                if (el.tagName && el.tagName.toLowerCase() == "td") {
                    if (el.className.search(/cd-([0-9]{8})/) == -1 || el.className.search(/date-picker-unused|out-of-range|day-disabled|no-selection|not-selectable/) != -1) return stopEvent(e);
                    var cellDate = el.className.match(/cd-([0-9]{8})/)[1];
                    o.date = new Date(cellDate.substr(0, 4), cellDate.substr(4, 2) - 1, cellDate.substr(6, 2));
                    o.dateSet = new Date(o.date);
                    o.noFocus = true;
                    o.callback("dateset", {
                        "id": o.id,
                        "date": o.dateSet,
                        "dd": o.dateSet.getDate(),
                        "mm": o.dateSet.getMonth() + 1,
                        "yyyy": o.dateSet.getFullYear()
                    });
                    o.returnFormattedDate();
                    o.hide();
                    o.stopTimer();
                    break
                } else if (el.id && el.id == o.id + "-today-but") {
                    o.date = new Date();
                    o.updateTable();
                    o.stopTimer();
                    break
                } else if (el.className.search(/date-picker-day-header/) != -1) {
                    var cnt = o.showWeeks ? -1 : 0,
                        elem = el;
                    while (elem.previousSibling) {
                        elem = elem.previousSibling;
                        if (elem.tagName && elem.tagName.toLowerCase() == "th") cnt++
                    };
                    o.firstDayOfWeek = (o.firstDayOfWeek + cnt) % 7;
                    o.updateTableHeaders();
                    break
                };
                try {
                    el = el.parentNode
                } catch (err) {
                    break
                }
            };
            return stopEvent(e)
        };
        this.show = function (autoFocus) {
            if (this.staticPos) {
                return
            };
            var elem, elemID;
            for (elemID in this.formElements) {
                elem = document.getElementById(this.id);
                if (!elem || (elem && elem.disabled)) {
                    return
                }
            };
            this.noFocus = true;
            if (!this.created || !document.getElementById('fd-' + this.id)) {
                this.created = false;
                this.fullCreate = false;
                this.create();
                this.fullCreate = true
            } else {
                this.setDateFromInput();
                this.reposition()
            };
            this.noFocus = !!!autoFocus;
            if (this.noFocus) {
                this.clickActivated = true;
                addEvent(document, "mousedown", this.onmousedown);
                if (mouseWheel) {
                    if (window.addEventListener && !window.devicePixelRatio) window.addEventListener('DOMMouseScroll', this.onmousewheel, false);
                    else {
                        addEvent(document, "mousewheel", this.onmousewheel);
                        addEvent(window, "mousewheel", this.onmousewheel)
                    }
                }
            } else {
                this.clickActivated = false
            };
            this.opacityTo = this.finalOpacity;
            this.div.style.display = "block"; /*@cc_on@if(@_jscript_version<=5.7)if(!o.isIE7){this.iePopUp.style.width=this.div.offsetWidth+"px";this.iePopUp.style.height=this.div.offsetHeight+"px";this.iePopUp.style.display="block"};@end@*/
            this.setNewFocus();
            this.fade();
            var butt = document.getElementById('fd-but-' + this.id);
            if (butt) {
                butt.className = butt.className.replace("dp-button-active", "") + " dp-button-active"
            }
        };
        this.hide = function () {
            if (!this.visible || !this.created || !document.getElementById('fd-' + this.id)) return;
            this.kbEvent = false;
            o.div.className = o.div.className.replace("datepicker-focus", "");
            this.stopTimer();
            this.removeOnFocusEvents();
            this.clickActivated = false;
            if (this.statusBar) {
                this.updateStatus(getTitleTranslation(9))
            };
            this.noFocus = true;
            this.setNewFocus();
            if (this.staticPos) {
                return
            };
            var butt = document.getElementById('fd-but-' + this.id);
            if (butt) butt.className = butt.className.replace("dp-button-active", "");
            removeEvent(document, "mousedown", this.onmousedown);
            if (mouseWheel) {
                if (window.addEventListener && !window.devicePixelRatio) {
                    try {
                        window.removeEventListener('DOMMouseScroll', this.onmousewheel, false)
                    } catch (err) {}
                } else {
                    removeEvent(document, "mousewheel", this.onmousewheel);
                    removeEvent(window, "mousewheel", this.onmousewheel)
                }
            }; /*@cc_on@if(@_jscript_version<=5.7)if(!this.isIE7){this.iePopUp.style.display="none"};@end@*/
            this.opacityTo = 0;
            this.fade()
        };
        this.onblur = function (e) {
            o.hide()
        };
        this.onfocus = function (e) {
            o.noFocus = false;
            o.div.className = o.div.className.replace("datepicker-focus", "") + " datepicker-focus";
            o.addOnFocusEvents()
        };
        this.onmousewheel = function (e) {
            e = e || document.parentWindow.event;
            var delta = 0;
            if (e.wheelDelta) {
                delta = e.wheelDelta / 120;
                if (isOpera && window.opera.version() < 9.2) delta = -delta
            } else if (e.detail) {
                delta = -e.detail / 3
            };
            var n = o.date.getDate(),
                d = new Date(o.date),
                inc = delta > 0 ? 1 : -1;
            d.setDate(2);
            d.setMonth(d.getMonth() + inc * 1);
            d.setDate(Math.min(n, daysInMonth(d.getMonth(), d.getFullYear())));
            if (o.outOfRange(d)) {
                return stopEvent(e)
            };
            o.date = new Date(d);
            o.updateTable();
            if (o.statusBar) {
                o.updateStatus(printFormattedDate(o.date, o.statusFormat, true))
            };
            return stopEvent(e)
        };
        this.onkeydown = function (e) {
            o.stopTimer();
            if (!o.visible) return false;
            e = e || document.parentWindow.event;
            var kc = e.keyCode ? e.keyCode : e.charCode;
            if (kc == 13) {
                var td = document.getElementById(o.id + "-date-picker-hover");
                if (!td || td.className.search(/cd-([0-9]{8})/) == -1 || td.className.search(/no-selection|out-of-range|day-disabled/) != -1) {
                    return stopEvent(e)
                };
                o.dateSet = new Date(o.date);
                o.callback("dateset", o.createCbArgObj());
                o.returnFormattedDate();
                o.hide();
                return stopEvent(e)
            } else if (kc == 27) {
                if (!o.staticPos) {
                    o.hide();
                    return stopEvent(e)
                };
                return true
            } else if (kc == 32 || kc == 0) {
                o.date = new Date();
                o.updateTable();
                return stopEvent(e)
            } else if (kc == 9) {
                if (!o.staticPos) {
                    return stopEvent(e)
                };
                return true
            }; /*@cc_on@if(@_win32)if(new Date().getTime()-o.interval.getTime()<50){return stopEvent(e)};o.interval=new Date();@end@*/
            if (isMoz) {
                if (new Date().getTime() - o.interval.getTime() < 50) {
                    return stopEvent(e)
                };
                o.interval = new Date()
            };
            if ((kc > 49 && kc < 56) || (kc > 97 && kc < 104)) {
                if (kc > 96) kc -= (96 - 48);
                kc -= 49;
                o.firstDayOfWeek = (o.firstDayOfWeek + kc) % 7;
                o.updateTableHeaders();
                return stopEvent(e)
            };
            if (kc < 33 || kc > 40) return true;
            var d = new Date(o.date),
                tmp, cursorYYYYMM = o.date.getFullYear() + pad(o.date.getMonth() + 1);
            if (kc == 36) {
                d.setDate(1)
            } else if (kc == 35) {
                d.setDate(daysInMonth(d.getMonth(), d.getFullYear()))
            } else if (kc == 33 || kc == 34) {
                var inc = (kc == 34) ? 1 : -1;
                if (e.ctrlKey) {
                    d.setFullYear(d.getFullYear() + inc * 1)
                } else {
                    var n = o.date.getDate();
                    d.setDate(2);
                    d.setMonth(d.getMonth() + inc * 1);
                    d.setDate(Math.min(n, daysInMonth(d.getMonth(), d.getFullYear())))
                }
            } else if (kc == 37) {
                d = new Date(o.date.getFullYear(), o.date.getMonth(), o.date.getDate() - 1)
            } else if (kc == 39 || kc == 34) {
                d = new Date(o.date.getFullYear(), o.date.getMonth(), o.date.getDate() + 1)
            } else if (kc == 38) {
                d = new Date(o.date.getFullYear(), o.date.getMonth(), o.date.getDate() - 7)
            } else if (kc == 40) {
                d = new Date(o.date.getFullYear(), o.date.getMonth(), o.date.getDate() + 7)
            };
            if (o.outOfRange(d)) {
                return stopEvent(e)
            };
            o.date = d;
            if (o.statusBar) {
                o.updateStatus(o.getBespokeTitle(o.date.getFullYear(), o.date.getMonth() + 1, o.date.getDate()) || printFormattedDate(o.date, o.statusFormat, true))
            };
            var t = String(o.date.getFullYear()) + pad(o.date.getMonth() + 1) + pad(o.date.getDate());
            if (e.ctrlKey || (kc == 33 || kc == 34) || t < o.firstDateShown || t > o.lastDateShown) {
                o.updateTable(); /*@cc_on@if(@_win32)o.interval=new Date();@end@*/
            } else {
                if (!o.noToday) {
                    o.disableTodayButton()
                };
                o.removeOldFocus();
                for (var i = 0, td; td = o.tds[i]; i++) {
                    if (td.className.search("cd-" + t) == -1) {
                        continue
                    };
                    o.showHideButtons(o.date);
                    td.id = o.id + "-date-picker-hover";
                    o.setNewFocus();
                    break
                }
            };
            return stopEvent(e)
        };
        this.onmouseout = function (e) {
            e = e || document.parentWindow.event;
            var p = e.toElement || e.relatedTarget;
            while (p && p != this) try {
                p = p.parentNode
            } catch (e) {
                p = this
            };
            if (p == this) return false;
            if (o.currentTR) {
                o.currentTR.className = "";
                o.currentTR = null
            };
            if (o.statusBar) {
                o.updateStatus(o.getBespokeTitle(o.date.getFullYear(), o.date.getMonth() + 1, o.date.getDate()) || printFormattedDate(o.date, o.statusFormat, true))
            }
        };
        this.onmouseover = function (e) {
            e = e || document.parentWindow.event;
            var el = e.target != null ? e.target : e.srcElement;
            while (el.nodeType != 1) {
                el = el.parentNode
            };
            if (!el || !el.tagName) {
                return
            };
            var statusText = getTitleTranslation(9);
            switch (el.tagName.toLowerCase()) {
                case "td":
                    if (el.className.search(/date-picker-unused|out-of-range/) != -1) {
                        statusText = getTitleTranslation(9)
                    }
                    if (el.className.search(/cd-([0-9]{8})/) != -1) {
                        o.stopTimer();
                        var cellDate = el.className.match(/cd-([0-9]{8})/)[1];
                        o.removeOldFocus();
                        el.id = o.id + "-date-picker-hover";
                        o.setNewFocus();
                        o.date = new Date(+cellDate.substr(0, 4), +cellDate.substr(4, 2) - 1, +cellDate.substr(6, 2));
                        if (!o.noToday) {
                            o.disableTodayButton()
                        };
                        statusText = o.getBespokeTitle(+cellDate.substr(0, 4), +cellDate.substr(4, 2), +cellDate.substr(6, 2)) || printFormattedDate(o.date, o.statusFormat, true)
                    };
                    break;
                case "th":
                    if (!o.statusBar) {
                        break
                    };
                    if (el.className.search(/drag-enabled/) != -1) {
                        statusText = getTitleTranslation(10)
                    } else if (el.className.search(/date-picker-week-header/) != -1) {
                        var txt = el.firstChild ? el.firstChild.nodeValue : "";
                        statusText = txt.search(/^(\d+)$/) != -1 ? getTitleTranslation(7, [txt, txt < 3 && o.date.getMonth() == 11 ? getWeeksInYear(o.date.getFullYear()) + 1 : getWeeksInYear(o.date.getFullYear())]) : getTitleTranslation(9)
                    };
                    break;
                case "span":
                    if (!o.statusBar) {
                        break
                    };
                    if (el.className.search(/drag-enabled/) != -1) {
                        statusText = getTitleTranslation(10)
                    } else if (el.className.search(/day-([0-6])/) != -1) {
                        var day = el.className.match(/day-([0-6])/)[1];
                        statusText = getTitleTranslation(11, [getDayTranslation(day, false)])
                    } else if (el.className.search(/prev-year/) != -1) {
                        statusText = getTitleTranslation(2)
                    } else if (el.className.search(/prev-month/) != -1) {
                        statusText = getTitleTranslation(0)
                    } else if (el.className.search(/next-year/) != -1) {
                        statusText = getTitleTranslation(3)
                    } else if (el.className.search(/next-month/) != -1) {
                        statusText = getTitleTranslation(1)
                    } else if (el.className.search(/today-but/) != -1 && el.className.search(/disabled/) == -1) {
                        statusText = getTitleTranslation(12)
                    };
                    break;
                default:
                    statusText = ""
            };
            while (el.parentNode) {
                el = el.parentNode;
                if (el.nodeType == 1 && el.tagName.toLowerCase() == "tr") {
                    if (o.currentTR) {
                        if (el == o.currentTR) break;
                        o.currentTR.className = ""
                    };
                    el.className = "dp-row-highlight";
                    o.currentTR = el;
                    break
                }
            };
            if (o.statusBar && statusText) {
                o.updateStatus(statusText)
            }
        };
        this.clearTimer = function () {
            o.stopTimer();
            o.timerInc = 800;
            o.yearInc = 0;
            o.monthInc = 0;
            o.dayInc = 0;
            removeEvent(document, "mouseup", o.clearTimer);
            if (o.mouseDownElem != null) {
                removeEvent(o.mouseDownElem, "mouseout", o.clearTimer)
            };
            o.mouseDownElem = null
        };
        var o = this;
        this.setDateFromInput();
        if (this.staticPos) {
            this.create()
        } else {
            this.createButton()
        };
        (function () {
            var elemID, elem;
            for (elemID in o.formElements) {
                elem = document.getElementById(elemID);
                if (elem && elem.tagName && elem.tagName.search(/select|input/i) != -1) {
                    addEvent(elem, "change", o.changeHandler)
                };
                if (!elem || elem.disabled == true) {
                    o.disableDatePicker()
                }
            }
        })();
        this.fullCreate = true
    };
    datePicker.prototype.addButtonEvents = function (but) {
        function buttonEvent(e) {
            e = e || window.event;
            var inpId = this.id.replace('fd-but-', ''),
                dpVisible = isVisible(inpId),
                autoFocus = false,
                kbEvent = datePickers[inpId].kbEvent;
            if (kbEvent) {
                datePickers[inpId].kbEvent = false;
                return
            };
            if (e.type == "keydown") {
                datePickers[inpId].kbEvent = true;
                var kc = e.keyCode != null ? e.keyCode : e.charCode;
                if (kc != 13) return true;
                if (dpVisible) {
                    this.className = this.className.replace("dp-button-active", "");
                    hideAll();
                    return stopEvent(e)
                };
                autoFocus = true
            } else {
                datePickers[inpId].kbEvent = false
            };
            this.className = this.className.replace("dp-button-active", "");
            if (!dpVisible) {
                this.className += " dp-button-active";
                hideAll(inpId);
                showDatePicker(inpId, autoFocus)
            } else {
                hideAll()
            };
            return stopEvent(e)
        };
        but.onkeydown = buttonEvent;
        but.onclick = buttonEvent;
        if (!buttonTabIndex || this.bespokeTabIndex === false) {
            but.setAttribute(! /*@cc_on!@*/ false ? "tabIndex" : "tabindex", "-1");
            but.tabIndex = -1;
            but.onkeydown = null;
            removeEvent(but, "keydown", buttonEvent)
        } else {
            but.setAttribute(! /*@cc_on!@*/ false ? "tabIndex" : "tabindex", this.bespokeTabIndex);
            but.tabIndex = this.bespokeTabIndex
        }
    };
    datePicker.prototype.createButton = function () {
        if (this.staticPos || document.getElementById("fd-but-" + this.id)) {
            return
        };
        var inp = document.getElementById(this.id),
            span = document.createElement('span'),
            but = document.createElement('a');
        but.href = "#" + this.id;
        but.className = "date-picker-control";
        but.title = getTitleTranslation(5);
        but.id = "fd-but-" + this.id;
        span.appendChild(document.createTextNode(nbsp));
        but.appendChild(span);
        span = document.createElement('span');
        span.className = "fd-screen-reader";
        span.appendChild(document.createTextNode(but.title));
        but.appendChild(span);
        setARIARole(but, "button");
        setARIAProperty(but, "haspopup", true);
        if (this.positioned && document.getElementById(this.positioned)) {
            document.getElementById(this.positioned).appendChild(but)
        } else {
            inp.parentNode.insertBefore(but, inp.nextSibling)
        };
        this.addButtonEvents(but);
        but = null;
        this.callback("dombuttoncreate", {
            id: this.id
        })
    };
    datePicker.prototype.setBespokeTitles = function (titles) {
        this.bespokeTitles = titles
    };
    datePicker.prototype.addBespokeTitles = function (titles) {
        for (var dt in titles) {
            this.bespokeTitles[dt] = titles[dt]
        }
    };
    datePicker.prototype.getBespokeTitle = function (y, m, d) {
        var dt, dtFull, yyyymmdd = y + String(pad(m)) + pad(d);
        for (dt in this.bespokeTitles) {
            dtFull = dt.replace(/^(\*\*\*\*)/, y).replace(/^(\d\d\d\d)(\*\*)/, "$1" + pad(m));
            if (dtFull == yyyymmdd) return this.bespokeTitles[dt]
        };
        for (dt in bespokeTitles) {
            dtFull = dt.replace(/^(\*\*\*\*)/, y).replace(/^(\d\d\d\d)(\*\*)/, "$1" + pad(m));
            if (dtFull == yyyymmdd) return bespokeTitles[dt]
        };
        return false
    };
    datePicker.prototype.returnSelectedDate = function () {
        return this.dateSet
    };
    datePicker.prototype.setRangeLow = function (range) {
        this.rangeLow = (String(range).search(/^(\d\d\d\d)(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])$/) == -1) ? false : range;
        if (!this.inUpdate) this.setDateFromInput()
    };
    datePicker.prototype.setRangeHigh = function (range) {
        this.rangeHigh = (String(range).search(/^(\d\d\d\d)(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])$/) == -1) ? false : range;
        if (!this.inUpdate) this.setDateFromInput()
    };
    datePicker.prototype.setDisabledDays = function (dayArray) {
        if (!dayArray.length || dayArray.length != 7 || dayArray.join("").search(/^([0|1]{7})$/) == -1) {
            if (debug) {
                throw "Invalid values located when attempting to call setDisabledDays";
            };
            return false
        };
        this.disabledDays = dayArray;
        if (!this.inUpdate) this.setDateFromInput()
    };
    datePicker.prototype.setDisabledDates = function (dateObj) {
        this.disabledDates = {};
        this.addDisabledDates(dateObj)
    };
    datePicker.prototype.setEnabledDates = function (dateObj) {
        this.enabledDates = {};
        this.addEnabledDates(dateObj)
    };
    datePicker.prototype.addDisabledDates = function (dateObj) {
        this.enabledDates = false;
        this.disabledDates = this.disabledDates || {};
        var startD;
        for (startD in dateObj) {
            if ((String(startD).search(wcDateRegExp) != -1 && dateObj[startD] == 1) || (String(startD).search(rangeRegExp) != -1 && String(dateObj[startD]).search(rangeRegExp) != -1)) {
                this.disabledDates[startD] = dateObj[startD]
            }
        };
        if (!this.inUpdate) this.setDateFromInput()
    };
    datePicker.prototype.addEnabledDates = function (dateObj) {
        this.disabledDates = false;
        this.enabledDates = this.enabledDates || {};
        var startD;
        for (startD in dateObj) {
            if ((String(startD).search(wcDateRegExp) != -1 && dateObj[startD] == 1) || (String(startD).search(rangeRegExp) != -1 && String(dateObj[startD]).search(rangeRegExp) != -1)) {
                this.enabledDates[startD] = dateObj[startD]
            }
        };
        if (!this.inUpdate) this.setDateFromInput()
    };
    datePicker.prototype.setSelectedDate = function (yyyymmdd) {
        if (String(yyyymmdd).search(wcDateRegExp) == -1) {
            return false
        };
        var match = yyyymmdd.match(rangeRegExp),
            dt = new Date(+match[2], +match[3] - 1, +match[4]);
        if (!dt || isNaN(dt) || !this.canDateBeSelected(dt)) {
            return false
        };
        this.dateSet = new Date(dt);
        if (!this.inUpdate) this.updateTable();
        this.callback("dateset", this.createCbArgObj());
        this.returnFormattedDate()
    };
    datePicker.prototype.checkSelectedDate = function () {
        if (this.dateSet && !this.canDateBeSelected(this.dateSet)) {
            this.dateSet = null
        };
        if (!this.inUpdate) this.updateTable()
    };
    datePicker.prototype.addOnFocusEvents = function () {
        if (this.kbEventsAdded || this.noFocus) {
            return
        };
        addEvent(document, "keypress", this.onkeydown);
        addEvent(document, "mousedown", this.onmousedown); /*@cc_on@if(@_win32)removeEvent(document,"keypress",this.onkeydown);addEvent(document,"keydown",this.onkeydown);@end@*/
        if (window.devicePixelRatio) {
            removeEvent(document, "keypress", this.onkeydown);
            addEvent(document, "keydown", this.onkeydown)
        };
        this.noFocus = false;
        this.kbEventsAdded = true
    };
    datePicker.prototype.removeOnFocusEvents = function () {
        if (!this.kbEventsAdded) {
            return
        };
        removeEvent(document, "keypress", this.onkeydown);
        removeEvent(document, "keydown", this.onkeydown);
        removeEvent(document, "mousedown", this.onmousedown);
        this.kbEventsAdded = false
    };
    datePicker.prototype.stopTimer = function () {
        this.timerSet = false;
        window.clearTimeout(this.timer)
    };
    datePicker.prototype.setOpacity = function (op) {
        this.div.style.opacity = op / 100;
        this.div.style.filter = 'alpha(opacity=' + op + ')';
        this.opacity = op
    };
    datePicker.prototype.getDates = function (y, m) {
        var dpm = daysInMonth(m - 1, y),
            obj = {},
            dds = this.getGenericDates(y, m, false),
            eds = this.getGenericDates(y, m, true),
            dts = y + pad(m);
        for (var i = 1; i <= dpm; i++) {
            dt = dts + "" + pad(i);
            if (dds) {
                obj[dt] = (dt in dds) ? 0 : 1
            } else if (eds) {
                obj[dt] = (dt in eds) ? 1 : 0
            } else {
                obj[dt] = 1
            }
        };
        return obj
    };
    datePicker.prototype.getGenericDates = function (y, m, enabled) {
        var deDates = enabled ? this.enabledDates : this.disabledDates;
        if (!deDates) {
            return false
        };
        m = pad(m);
        var obj = {},
            lower = this.firstDateShown,
            upper = this.lastDateShown,
            dt1, dt2, rngLower, rngUpper;
        if (!upper || !lower) {
            lower = this.firstDateShown = y + pad(m) + "01";
            upper = this.lastDateShown = y + pad(m) + pad(daysInMonth(m, y))
        };
        for (dt in deDates) {
            dt1 = dt.replace(/^(\*\*\*\*)/, y).replace(/^(\d\d\d\d)(\*\*)/, "$1" + m);
            dt2 = deDates[dt];
            if (dt2 == 1) {
                if (Number(dt1.substr(0, 6)) >= +String(this.firstDateShown).substr(0, 6) && Number(dt1.substr(0, 6)) <= +String(this.lastDateShown).substr(0, 6)) {
                    obj[dt1] = 1
                };
                continue
            };
            if (+String(this.firstDateShown).substr(0, 6) >= Number(dt1.substr(0, 6)) && +String(this.lastDateShown).substr(0, 6) <= Number(dt2.substr(0, 6))) {
                if (Number(dt1.substr(0, 6)) == Number(dt2.substr(0, 6))) {
                    for (var i = dt1; i <= dt2; i++) {
                        obj[i] = 1
                    };
                    continue
                };
                rngLower = Number(dt1.substr(0, 6)) == +String(this.firstDateShown).substr(0, 6) ? dt1 : lower;
                rngUpper = Number(dt2.substr(0, 6)) == +String(this.lastDateShown).substr(0, 6) ? dt2 : upper;
                for (var i = +rngLower; i <= +rngUpper; i++) {
                    obj[i] = 1
                }
            }
        };
        return obj
    };
    datePicker.prototype.truePosition = function (element) {
        var pos = this.cumulativeOffset(element);
        if (isOpera) {
            return pos
        };
        var iebody = (document.compatMode && document.compatMode != "BackCompat") ? document.documentElement : document.body,
            dsocleft = document.all ? iebody.scrollLeft : window.pageXOffset,
            dsoctop = document.all ? iebody.scrollTop : window.pageYOffset,
            posReal = this.realOffset(element);
        return [pos[0] - posReal[0] + dsocleft, pos[1] - posReal[1] + dsoctop]
    };
    datePicker.prototype.realOffset = function (element) {
        var t = 0,
            l = 0;
        do {
            t += element.scrollTop || 0;
            l += element.scrollLeft || 0;
            element = element.parentNode
        } while (element);
        return [l, t]
    };
    datePicker.prototype.cumulativeOffset = function (element) {
        var t = 0,
            l = 0;
        do {
            t += element.offsetTop || 0;
            l += element.offsetLeft || 0;
            element = element.offsetParent
        } while (element);
        return [l, t]
    };
    datePicker.prototype.equaliseDates = function () {
        var clearDayFound = false,
            tmpDate;
        for (var i = this.rangeLow; i <= this.rangeHigh; i++) {
            tmpDate = String(i);
            if (!this.disabledDays[new Date(tmpDate.substr(0, 4), tmpDate.substr(6, 2), tmpDate.substr(4, 2)).getDay() - 1]) {
                clearDayFound = true;
                break
            }
        };
        if (!clearDayFound) {
            this.disabledDays = [0, 0, 0, 0, 0, 0, 0]
        }
    };
    datePicker.prototype.outOfRange = function (tmpDate) {
        if (!this.rangeLow && !this.rangeHigh) {
            return false
        };
        var level = false;
        if (!tmpDate) {
            level = true;
            tmpDate = this.date
        };
        var d = pad(tmpDate.getDate()),
            m = pad(tmpDate.getMonth() + 1),
            y = tmpDate.getFullYear(),
            dt = String(y) + String(m) + String(d);
        if (this.rangeLow && +dt < +this.rangeLow) {
            if (!level) {
                return true
            };
            this.date = new Date(this.rangeLow.substr(0, 4), this.rangeLow.substr(4, 2) - 1, this.rangeLow.substr(6, 2), 5, 0, 0);
            return false
        };
        if (this.rangeHigh && +dt > +this.rangeHigh) {
            if (!level) {
                return true
            };
            this.date = new Date(this.rangeHigh.substr(0, 4), this.rangeHigh.substr(4, 2) - 1, this.rangeHigh.substr(6, 2), 5, 0, 0)
        };
        return false
    };
    datePicker.prototype.canDateBeSelected = function (tmpDate) {
        if (!tmpDate) return false;
        var d = pad(tmpDate.getDate()),
            m = pad(tmpDate.getMonth() + 1),
            y = tmpDate.getFullYear(),
            dt = String(y) + String(m) + String(d),
            dd = this.getDates(y, m),
            wd = tmpDate.getDay() == 0 ? 7 : tmpDate.getDay();
        if ((this.rangeLow && +dt < +this.rangeLow) || (this.rangeHigh && +dt > +this.rangeHigh) || (dd[dt] == 0) || this.disabledDays[wd - 1]) {
            return false
        };
        return true
    };
    datePicker.prototype.updateStatus = function (msg) {
        while (this.statusBar.firstChild) {
            this.statusBar.removeChild(this.statusBar.firstChild)
        };
        if (msg && this.statusFormat.search(/-S|S-/) != -1 && msg.search(/([0-9]{1,2})(st|nd|rd|th)/) != -1) {
            msg = msg.replace(/([0-9]{1,2})(st|nd|rd|th)/, "$1<sup>$2</sup>").split(/<sup>|<\/sup>/);
            var dc = document.createDocumentFragment();
            for (var i = 0, nd; nd = msg[i]; i++) {
                if (/^(st|nd|rd|th)$/.test(nd)) {
                    var sup = document.createElement("sup");
                    sup.appendChild(document.createTextNode(nd));
                    dc.appendChild(sup)
                } else {
                    dc.appendChild(document.createTextNode(nd))
                }
            };
            this.statusBar.appendChild(dc)
        } else {
            this.statusBar.appendChild(document.createTextNode(msg ? msg : getTitleTranslation(9)))
        }
    };
    datePicker.prototype.setDateFromInput = function () {
        var origDateSet = this.dateSet,
            m = false,
            dt, elemID, elem, elemFmt, d, y, elemVal;
        this.dateSet = null;
        for (elemID in this.formElements) {
            elem = document.getElementById(elemID);
            if (!elem) {
                return
            };
            elemVal = String(elem.value);
            elemFmt = this.formElements[elemID];
            dt = false;
            if (!(elemVal == "")) {
                for (var i = 0, fmt; fmt = this.formatMasks[elemID][i]; i++) {
                    dt = parseDateString(elemVal, fmt);
                    if (dt) {
                        break
                    }
                }
            };
            if (dt) {
                if (elemFmt.search(new RegExp('[' + dParts + ']')) != -1) {
                    d = dt.getDate()
                };
                if (elemFmt.search(new RegExp('[' + mParts + ']')) != -1) {
                    m = dt.getMonth()
                };
                if (elemFmt.search(new RegExp('[' + yParts + ']')) != -1) {
                    y = dt.getFullYear()
                }
            }
        };
        dt = false;
        if (d && !(m === false) && y) {
            if (+d > daysInMonth(+m, +y)) {
                d = daysInMonth(+m, +y);
                dt = false
            } else {
                dt = new Date(+y, +m, +d)
            }
        };
        if (!dt || isNaN(dt)) {
            var newDate = new Date(y || new Date().getFullYear(), !(m === false) ? m : new Date().getMonth(), 1);
            this.date = this.cursorDate ? new Date(+this.cursorDate.substr(0, 4), +this.cursorDate.substr(4, 2) - 1, +this.cursorDate.substr(6, 2)) : new Date(newDate.getFullYear(), newDate.getMonth(), Math.min(+d || new Date().getDate(), daysInMonth(newDate.getMonth(), newDate.getFullYear())));
            this.date.setHours(5);
            this.outOfRange();
            this.updateTable();
            return
        };
        dt.setHours(5);
        this.date = new Date(dt);
        this.outOfRange();
        if (dt.getTime() == this.date.getTime() && this.canDateBeSelected(this.date)) {
            this.dateSet = new Date(this.date)
        };
        if (this.fullCreate) this.updateTable();
        this.returnFormattedDate(true)
    };
    datePicker.prototype.setSelectIndex = function (elem, indx) {
        for (var opt = elem.options.length - 1; opt >= 0; opt--) {
            if (elem.options[opt].value == indx) {
                elem.selectedIndex = opt;
                return
            }
        }
    };
    datePicker.prototype.returnFormattedDate = function (noFocus) {
        if (!this.dateSet) {
            return
        };
        var d = pad(this.dateSet.getDate()),
            m = pad(this.dateSet.getMonth() + 1),
            y = this.dateSet.getFullYear(),
            el = false,
            elemID, elem, elemFmt, fmtDate;
        noFocus = !!noFocus;
        for (elemID in this.formElements) {
            elem = document.getElementById(elemID);
            if (!elem) return;
            if (!el) el = elem;
            elemFmt = this.formElements[elemID];
            fmtDate = printFormattedDate(this.dateSet, elemFmt, returnLocaleDate);
            if (elem.tagName.toLowerCase() == "input") {
                elem.value = fmtDate
            } else {
                this.setSelectIndex(elem, fmtDate)
            }
        };
        if (this.staticPos) {
            this.noFocus = true;
            this.updateTable();
            this.noFocus = false
        };
        if (this.fullCreate) {
            if (el.type && el.type != "hidden" && !noFocus) {
                el.focus()
            }
        }
    };
    datePicker.prototype.disableDatePicker = function () {
        if (this.disabled) return;
        if (this.staticPos) {
            this.removeOnFocusEvents();
            this.removeOldFocus();
            this.noFocus = true;
            this.div.className = this.div.className.replace(/dp-disabled/, "") + " dp-disabled";
            this.table.onmouseover = this.table.onclick = this.table.onmouseout = this.table.onmousedown = null;
            removeEvent(document, "mousedown", this.onmousedown);
            removeEvent(document, "mouseup", this.clearTimer)
        } else {
            if (this.visible) this.hide();
            var but = document.getElementById("fd-but-" + this.id);
            if (but) {
                but.className = but.className.replace(/dp-disabled/, "") + " dp-disabled";
                setARIAProperty(but, "disabled", true);
                but.onkeydown = but.onclick = function () {
                    return false
                };
                but.setAttribute(! /*@cc_on!@*/ false ? "tabIndex" : "tabindex", "-1");
                but.tabIndex = -1
            }
        };
        clearTimeout(this.timer);
        this.disabled = true
    };
    datePicker.prototype.enableDatePicker = function () {
        if (!this.disabled) return;
        if (this.staticPos) {
            this.removeOldFocus();
            this.noFocus = true;
            this.updateTable();
            this.div.className = this.div.className.replace(/dp-disabled/, "");
            this.disabled = false;
            this.table.onmouseover = this.onmouseover;
            this.table.onmouseout = this.onmouseout;
            this.table.onclick = this.onclick;
            this.table.ontouchend = this.onclick;
            this.table.onmousedown = this.onmousedown
        } else {
            var but = document.getElementById("fd-but-" + this.id);
            if (but) {
                but.className = but.className.replace(/dp-disabled/, "");
                setARIAProperty(but, "disabled", false);
                this.addButtonEvents(but)
            }
        };
        this.disabled = false
    };
    datePicker.prototype.disableTodayButton = function () {
        var today = new Date();
        this.butToday.className = this.butToday.className.replace("fd-disabled", "");
        if (this.outOfRange(today) || (this.date.getDate() == today.getDate() && this.date.getMonth() == today.getMonth() && this.date.getFullYear() == today.getFullYear())) {
            this.butToday.className += " fd-disabled"
        }
    };
    datePicker.prototype.updateTableHeaders = function () {
        var colspanTotal = this.showWeeks ? 8 : 7,
            colOffset = this.showWeeks ? 1 : 0,
            d, but;
        for (var col = colOffset; col < colspanTotal; col++) {
            d = (this.firstDayOfWeek + (col - colOffset)) % 7;
            this.ths[col].title = getDayTranslation(d, false);
            if (col > colOffset) {
                but = this.ths[col].getElementsByTagName("span")[0];
                while (but.firstChild) {
                    but.removeChild(but.firstChild)
                };
                but.appendChild(document.createTextNode(getDayTranslation(d, true)));
                but.title = this.ths[col].title;
                but.className = but.className.replace(/day-([0-6])/, "") + " day-" + d;
                but = null
            } else {
                while (this.ths[col].firstChild) {
                    this.ths[col].removeChild(this.ths[col].firstChild)
                };
                this.ths[col].appendChild(document.createTextNode(getDayTranslation(d, true)))
            };
            this.ths[col].className = this.ths[col].className.replace(/date-picker-highlight/g, "");
            if (this.highlightDays[d]) {
                this.ths[col].className += " date-picker-highlight"
            }
        };
        if (this.created) {
            this.updateTable()
        }
    };
    datePicker.prototype.callback = function (type, args) {
        if (!type || !(type in this.callbacks)) {
            return false
        };
        var ret = false;
        for (var func = 0; func < this.callbacks[type].length; func++) {
            ret = this.callbacks[type][func](args || this.id)
        };
        return ret
    };
    datePicker.prototype.showHideButtons = function (tmpDate) {
        if (!this.butPrevYear) {
            return
        };
        var tdm = tmpDate.getMonth(),
            tdy = tmpDate.getFullYear();
        if (this.outOfRange(new Date((tdy - 1), tdm, daysInMonth(+tdm, tdy - 1)))) {
            if (this.butPrevYear.className.search(/fd-disabled/) == -1) {
                this.butPrevYear.className += " fd-disabled"
            };
            if (this.yearInc == -1) this.stopTimer()
        } else {
            this.butPrevYear.className = this.butPrevYear.className.replace(/fd-disabled/g, "")
        }; if (this.outOfRange(new Date(tdy, (+tdm - 1), daysInMonth(+tdm - 1, tdy)))) {
            if (this.butPrevMonth.className.search(/fd-disabled/) == -1) {
                this.butPrevMonth.className += " fd-disabled"
            };
            if (this.monthInc == -1) this.stopTimer()
        } else {
            this.butPrevMonth.className = this.butPrevMonth.className.replace(/fd-disabled/g, "")
        }; if (this.outOfRange(new Date((tdy + 1), +tdm, 1))) {
            if (this.butNextYear.className.search(/fd-disabled/) == -1) {
                this.butNextYear.className += " fd-disabled"
            };
            if (this.yearInc == 1) this.stopTimer()
        } else {
            this.butNextYear.className = this.butNextYear.className.replace(/fd-disabled/g, "")
        }; if (this.outOfRange(new Date(tdy, +tdm + 1, 1))) {
            if (this.butNextMonth.className.search(/fd-disabled/) == -1) {
                this.butNextMonth.className += " fd-disabled"
            };
            if (this.monthInc == 1) this.stopTimer()
        } else {
            this.butNextMonth.className = this.butNextMonth.className.replace(/fd-disabled/g, "")
        }
    };
    var localeDefaults = {
        fullMonths: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
        monthAbbrs: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
        fullDays: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
        dayAbbrs: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
        titles: ["Previous month", "Next month", "Previous year", "Next year", "Today", "Show Calendar", "wk", "Week [[%0%]] of [[%1%]]", "Week", "Select a date", "Click \u0026 Drag to move", "Display \u201C[[%0%]]\u201D first", "Go to Today\u2019s date", "Disabled date :"],
        firstDayOfWeek: 0,
        imported: false
    };
    var joinNodeLists = function () {
        if (!arguments.length) {
            return []
        }
        var nodeList = [];
        for (var i = 0; i < arguments.length; i++) {
            for (var j = 0, item; item = arguments[i][j]; j++) {
                nodeList[nodeList.length] = item
            }
        };
        return nodeList
    };
    var cleanUp = function () {
        var dp, fe;
        for (dp in datePickers) {
            for (fe in datePickers[dp].formElements) {
                if (!document.getElementById(fe)) {
                    datePickers[dp].destroy();
                    datePickers[dp] = null;
                    delete datePickers[dp];
                    break
                }
            }
        }
    };
    var hideAll = function (exception) {
        var dp;
        for (dp in datePickers) {
            if (!datePickers[dp].created || (exception && exception == datePickers[dp].id)) continue;
            datePickers[dp].hide()
        }
    };
    var hideDatePicker = function (inpID) {
        if (inpID in datePickers) {
            if (!datePickers[inpID].created || datePickers[inpID].staticPos) return;
            datePickers[inpID].hide()
        }
    };
    var showDatePicker = function (inpID, autoFocus) {
        if (!(inpID in datePickers)) return false;
        datePickers[inpID].clickActivated = !!!autoFocus;
        datePickers[inpID].show(autoFocus);
        return true
    };
    var destroy = function (e) {
        e = e || window.event;
        if (e.persisted) {
            return
        };
        for (dp in datePickers) {
            datePickers[dp].destroy();
            datePickers[dp] = null;
            delete datePickers[dp]
        };
        datePickers = null;
        removeEvent(window, 'unload', datePickerController.destroy)
    };
    var destroySingleDatePicker = function (id) {
        if (id && (id in datePickers)) {
            datePickers[id].destroy();
            datePickers[id] = null;
            delete datePickers[id]
        }
    };
    var getTitleTranslation = function (num, replacements) {
        replacements = replacements || [];
        if (localeImport.titles.length > num) {
            var txt = localeImport.titles[num];
            if (replacements && replacements.length) {
                for (var i = 0; i < replacements.length; i++) {
                    txt = txt.replace("[[%" + i + "%]]", replacements[i])
                }
            };
            return txt.replace(/[[%(\d)%]]/g, "")
        };
        return ""
    };
    var getDayTranslation = function (day, abbreviation) {
        var titles = localeImport[abbreviation ? "dayAbbrs" : "fullDays"];
        return titles.length && titles.length > day ? titles[day] : ""
    };
    var getMonthTranslation = function (month, abbreviation) {
        var titles = localeImport[abbreviation ? "monthAbbrs" : "fullMonths"];
        return titles.length && titles.length > month ? titles[month] : ""
    };
    var daysInMonth = function (nMonth, nYear) {
        nMonth = (nMonth + 12) % 12;
        return (((0 == (nYear % 4)) && ((0 != (nYear % 100)) || (0 == (nYear % 400)))) && nMonth == 1) ? 29 : [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][nMonth]
    };
    var getWeeksInYear = function (Y) {
        if (Y in weeksInYearCache) {
            return weeksInYearCache[Y]
        };
        var X1, X2, NW;
        with(X1 = new Date(Y, 0, 4)) {
            setDate(getDate() - (6 + getDay()) % 7)
        };
        with(X2 = new Date(Y, 11, 28)) {
            setDate(getDate() + (7 - getDay()) % 7)
        };
        weeksInYearCache[Y] = Math.round((X2 - X1) / 604800000);
        return weeksInYearCache[Y]
    };
    var getWeekNumber = function (y, m, d) {
        var d = new Date(y, m, d, 0, 0, 0);
        var DoW = d.getDay();
        d.setDate(d.getDate() - (DoW + 6) % 7 + 3);
        var ms = d.valueOf();
        d.setMonth(0);
        d.setDate(4);
        return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1
    };
    var printFormattedDate = function (date, fmt, useImportedLocale) {
        if (!date || isNaN(date)) {
            return ""
        };
        var parts = fmt.split("-"),
            str = [],
            d = date.getDate(),
            D = date.getDay(),
            m = date.getMonth(),
            y = date.getFullYear(),
            flags = {
                "sp": " ",
                "dt": ".",
                "sl": "/",
                "ds": "-",
                "cc": ",",
                "d": pad(d),
                "D": useImportedLocale ? localeImport.dayAbbrs[D == 0 ? 6 : D - 1] : localeDefaults.dayAbbrs[D == 0 ? 6 : D - 1],
                "l": useImportedLocale ? localeImport.fullDays[D == 0 ? 6 : D - 1] : localeDefaults.fullDays[D == 0 ? 6 : D - 1],
                "j": d,
                "N": D == 0 ? 7 : D,
                "w": D,
                "W": getWeekNumber(y, m, d),
                "M": useImportedLocale ? localeImport.monthAbbrs[m] : localeDefaults.monthAbbrs[m],
                "F": useImportedLocale ? localeImport.fullMonths[m] : localeDefaults.fullMonths[m],
                "m": pad(m + 1),
                "n": m + 1,
                "t": daysInMonth(m, y),
                "y": String(y).substr(2, 2),
                "Y": y,
                "S": ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
            };
        for (var pt = 0, part; part = parts[pt]; pt++) {
            str.push(!(part in flags) ? "" : flags[part])
        };
        return str.join("")
    };
    var parseDateString = function (str, fmt) {
        var d = false,
            m = false,
            y = false,
            now = new Date(),
            parts = fmt.replace(/-sp(-sp)+/g, "-sp").split("-"),
            divds = {
                "dt": ".",
                "sl": "/",
                "ds": "-",
                "cc": ","
            },
            str = "" + str;
        loopLabel: for (var pt = 0, part; part = parts[pt]; pt++) {
            if (str.length == 0) {
                return false
            };
            switch (part) {
                case "sp":
                case "dt":
                case "sl":
                case "ds":
                case "cc":
                    str = str.replace(/^(\s|\.|\/|,|-){1,}/, "");
                    break;
                case "d":
                case "j":
                    if (str.search(/^(3[01]|[12][0-9]|0?[1-9])/) != -1) {
                        d = +str.match(/^(3[01]|[12][0-9]|0?[1-9])/)[0];
                        str = str.substr(str.match(/^(3[01]|[12][0-9]|0?[1-9])/)[0].length);
                        break
                    } else {
                        return ""
                    };
                case "D":
                case "l":
                    l = localeDefaults.fullDays.concat(localeDefaults.dayAbbrs);
                    if (localeImport.imported) {
                        l = l.concat(localeImport.fullDays).concat(localeImport.dayAbbrs)
                    };
                    for (var i = 0; i < l.length; i++) {
                        if (new RegExp("^" + l[i], "i").test(str)) {
                            str = str.substr(l[i].length);
                            continue loopLabel
                        }
                    };
                    break;
                case "N":
                case "w":
                    if (str.search(part == "N" ? /^([1-7])/ : /^([0-6])/) != -1) {
                        str = str.substr(1)
                    };
                    break;
                case "S":
                    if (str.search(/^(st|nd|rd|th)/i) != -1) {
                        str = str.substr(2)
                    };
                    break;
                case "W":
                    if (str.search(/^([1-9]|[1234[0-9]|5[0-3])/) != -1) {
                        str = str.substr(str.match(/^([1-9]|[1234[0-9]|5[0-3])/)[0].length)
                    };
                    break;
                case "M":
                case "F":
                    l = localeDefaults.fullMonths.concat(localeDefaults.monthAbbrs);
                    if (localeImport.imported) {
                        l = l.concat(localeImport.fullMonths).concat(localeImport.monthAbbrs)
                    };
                    for (var i = 0; i < l.length; i++) {
                        if (str.search(new RegExp("^" + l[i], "i")) != -1) {
                            str = str.substr(l[i].length);
                            m = ((i + 12) % 12);
                            continue loopLabel
                        }
                    };
                    return "";
                case "m":
                case "n":
                    l = /^(1[012]|0?[1-9])/;
                    if (str.search(l) != -1) {
                        m = +str.match(l)[0] - 1;
                        str = str.substr(str.match(l)[0].length);
                        break
                    } else {
                        return ""
                    };
                case "t":
                    if (str.search(/2[89]|3[01]/) != -1) {
                        str = str.substr(2);
                        break
                    };
                    break;
                case "Y":
                    if (str.search(/^(\d{4})/) != -1) {
                        y = str.substr(0, 4);
                        str = str.substr(4);
                        break
                    } else {
                        return ""
                    };
                case "y":
                    if (str.search(/^(\d{4})/) != -1) {
                        y = str.substr(0, 4);
                        str = str.substr(4);
                        break
                    } else if (str.search(/^(0[0-9]|[1-9][0-9])/) != -1) {
                        y = str.substr(0, 2);
                        y = +y < 50 ? '20' + "" + String(y) : '19' + "" + String(y);
                        str = str.substr(2);
                        break
                    } else return "";
                default:
                    return ""
            }
        };
        if (!(str == "") || (d === false && m === false && y === false)) {
            return false
        };
        m = m === false ? 11 : m;
        y = y === false ? now.getFullYear() : y;
        d = d === false ? daysInMonth(+m, +y) : d;
        if (d > daysInMonth(+m, +y)) {
            return false
        };
        var tmpDate = new Date(y, m, d);
        return !tmpDate || isNaN(tmpDate) ? false : tmpDate
    };
    var findLabelForElement = function (element) {
        var label;
        if (element.parentNode && element.parentNode.tagName.toLowerCase() == "label") lebel = element.parentNode;
        else {
            var labelList = document.getElementsByTagName('label');
            for (var lbl = 0; lbl < labelList.length; lbl++) {
                if ((labelList[lbl]['htmlFor'] && labelList[lbl]['htmlFor'] == element.id) || (labelList[lbl].getAttribute('for') == element.id)) {
                    label = labelList[lbl];
                    break
                }
            }
        }; if (label && !label.id) {
            label.id = element.id + "_label"
        };
        return label
    };
    var updateLanguage = function () {
        if (typeof (window.fdLocale) == "object") {
            localeImport = {
                titles: fdLocale.titles,
                fullMonths: fdLocale.fullMonths,
                monthAbbrs: fdLocale.monthAbbrs,
                fullDays: fdLocale.fullDays,
                dayAbbrs: fdLocale.dayAbbrs,
                firstDayOfWeek: ("firstDayOfWeek" in fdLocale) ? fdLocale.firstDayOfWeek : 0,
                imported: true
            }
        } else if (!localeImport) {
            localeImport = localeDefaults
        }
    };
    var loadLanguage = function () {
        updateLanguage();
        for (dp in datePickers) {
            if (!datePickers[dp].created) continue;
            datePickers[dp].updateTable()
        }
    };
    var checkElem = function (elem) {
        return !(!elem || !elem.tagName || !((elem.tagName.toLowerCase() == "input" && (elem.type == "text" || elem.type == "hidden")) || elem.tagName.toLowerCase() == "select"))
    };
    var addDatePicker = function (options) {
        updateLanguage();
        if (!options.formElements) {
            if (debug) throw "No form elements stipulated within initialisation parameters";
            return
        };
        options.id = (options.id && (options.id in options.formElements)) ? options.id : "";
        options.formatMasks = {};
        var testParts = [dParts, mParts, yParts],
            partsFound = [0, 0, 0],
            tmpPartsFound, matchedPart, newParts, indParts, fmt, fmtBag, fmtParts, newFormats, myMin, myMax;
        for (var elemID in options.formElements) {
            elem = document.getElementById(elemID);
            if (!checkElem(elem)) {
                if (debug) throw "The element with and id of '" + elemID + "' is of the wrong type or does not exist within the DOM";
                return false
            };
            if (!options.id) options.id = elemID;
            fmt = options.formElements[elemID];
            if (!(fmt.match(validFmtRegExp))) {
                if (debug) throw "The element with and id of '" + elemID + "' has the following incorrect date format assigned to it: " + fmt;
                return false
            };
            fmtBag = [fmt];
            if (options.dateFormats && (elemID in options.dateFormats) && options.dateFormats[elemID].length) {
                newFormats = [];
                for (var f = 0, bDft; bDft = options.dateFormats[elemID][f]; f++) {
                    if (!(bDft.match(validFmtRegExp))) {
                        if (debug) throw "The element with and id of '" + elemID + "' has the following incorrect date format assigned to it within the dateFormats parameter: " + bDft;
                        return false
                    };
                    newFormats.push(bDft)
                };
                fmtBag = fmtBag.concat(newFormats)
            };
            tmpPartsFound = [0, 0, 0];
            for (var i = 0, testPart; testPart = testParts[i]; i++) {
                if (fmt.search(new RegExp('(' + testPart + ')')) != -1) {
                    partsFound[i] = tmpPartsFound[i] = 1;
                    if (elem.tagName.toLowerCase() == "input") {
                        matchedPart = fmt.match(new RegExp('(' + testPart + ')'))[0];
                        newParts = String(matchedPart + "|" + testPart.replace(new RegExp("(" + matchedPart + ")"), "")).replace("||", "|");
                        indParts = newParts.split("|");
                        newFormats = [];
                        for (var z = 0, bFmt; bFmt = fmtBag[z]; z++) {
                            for (var x = 0, indPart; indPart = indParts[x]; x++) {
                                if (indPart == matchedPart) continue;
                                newFormats.push(bFmt.replace(new RegExp('(' + testPart + ')(-|$)', 'g'), indPart + "-").replace(/-$/, ""))
                            }
                        };
                        fmtBag = fmtBag.concat(newFormats)
                    }
                }
            };
            options.formatMasks[elemID] = fmtBag.concat();
            if (elem.tagName.toLowerCase() == "select") {
                myMin = myMax = 0;
                var selOptions = elem.options;
                if (tmpPartsFound[0] && tmpPartsFound[1] && tmpPartsFound[2]) {
                    var yyyymmdd, cursorDate = false;
                    if ("disabledDates" in options) {
                        delete(options.disabledDates)
                    };
                    options.enabledDates = {};
                    for (i = 0; i < selOptions.length; i++) {
                        for (var f = 0, fmt; fmt = fmtBag[f]; f++) {
                            dt = parseDateString(selOptions[i].value, fmt);
                            if (dt) {
                                yyyymmdd = dt.getFullYear() + "" + pad(dt.getMonth() + 1) + "" + pad(dt.getDate());
                                if (!cursorDate) cursorDate = yyyymmdd;
                                options.enabledDates[yyyymmdd] = 1;
                                if (!myMin || Number(yyyymmdd) < myMin) {
                                    myMin = yyyymmdd
                                };
                                if (!myMax || Number(yyyymmdd) > myMax) {
                                    myMax = yyyymmdd
                                };
                                break
                            }
                        }
                    };
                    if (!options.cursorDate && cursorDate) options.cursorDate = cursorDate
                } else if (tmpPartsFound[1] && tmpPartsFound[2]) {
                    var yyyymm;
                    for (i = 0; i < selOptions.length; i++) {
                        for (var f = 0, fmt; fmt = fmtBag[f]; f++) {
                            dt = parseDateString(selOptions[i].value, fmt);
                            if (dt) {
                                yyyymm = dt.getFullYear() + "" + pad(dt.getMonth() + 1);
                                if (!myMin || Number(yyyymm) < myMin) {
                                    myMin = yyyymm
                                };
                                if (!myMax || Number(yyyymm) > myMax) {
                                    myMax = yyyymm
                                };
                                break
                            }
                        }
                    };
                    myMin += "" + "01";
                    myMax += "" + daysInMonth(+myMax.substr(4, 2) - 1, +myMax.substr(0, 4))
                } else if (tmpPartsFound[2]) {
                    var yyyy;
                    for (i = 0; i < selOptions.length; i++) {
                        for (var f = 0, fmt; fmt = fmtBag[f]; f++) {
                            dt = parseDateString(selOptions[i].value, fmt);
                            if (dt) {
                                yyyy = dt.getFullYear();
                                if (!myMin || Number(yyyy) < myMin) {
                                    myMin = yyyy
                                };
                                if (!myMax || Number(yyyy) > myMax) {
                                    myMax = yyyy
                                };
                                break
                            }
                        }
                    };
                    myMin += "0101";
                    myMax += "1231"
                };
                if (myMin && (!options.rangeLow || (+options.rangeLow < +myMin))) options.rangeLow = myMin;
                if (myMax && (!options.rangeHigh || (+options.rangeHigh > +myMin))) options.rangeHigh = myMax
            }
        };
        if (!(partsFound[0] && partsFound[1] && partsFound[2])) {
            if (debug) throw "Could not find all of the required date parts for element: " + elem.id;
            return false
        };
        var opts = {
            formElements: options.formElements,
            id: options.id,
            formatMasks: options.formatMasks,
            staticPos: !!(options.staticPos),
            positioned: options.positioned && document.getElementById(options.positioned) ? options.positioned : "",
            rangeLow: options.rangeLow && String(options.rangeLow).search(rangeRegExp) != -1 ? options.rangeLow : "",
            rangeHigh: options.rangeHigh && String(options.rangeHigh).search(rangeRegExp) != -1 ? options.rangeHigh : "",
            statusFormat: options.statusFormat && String(options.statusFormat).search(validFmtRegExp) != -1 ? options.statusFormat : "",
            noFadeEffect: !!(options.staticPos) ? true : !!(options.noFadeEffect),
            dragDisabled: nodrag || !!(options.staticPos) ? true : !!(options.dragDisabled),
            bespokeTabIndex: options.bespokeTabindex && typeof options.bespokeTabindex == 'number' ? parseInt(options.bespokeTabindex, 10) : 0,
            bespokeTitles: options.bespokeTitles || {},
            finalOpacity: options.finalOpacity && typeof options.finalOpacity == 'number' && (options.finalOpacity > 20 && options.finalOpacity <= 100) ? parseInt(+options.finalOpacity, 10) : (!!(options.staticPos) ? 100 : finalOpacity),
            hideInput: !!(options.hideInput),
            noToday: !!(options.noTodayButton),
            showWeeks: !!(options.showWeeks),
            fillGrid: !!(options.fillGrid),
            constrainSelection: "constrainSelection" in options ? !!(options.constrainSelection) : true,
            cursorDate: options.cursorDate && String(options.cursorDate).search(rangeRegExp) != -1 ? options.cursorDate : "",
            labelledBy: findLabelForElement(elem),
            describedBy: (options.describedBy && document.getElementById(options.describedBy)) ? options.describedBy : describedBy && document.getElementById(describedBy) ? describedBy : "",
            callbacks: options.callbackFunctions ? options.callbackFunctions : {},
            highlightDays: options.highlightDays && options.highlightDays.length && options.highlightDays.length == 7 ? options.highlightDays : [0, 0, 0, 0, 0, 1, 1],
            disabledDays: options.disabledDays && options.disabledDays.length && options.disabledDays.length == 7 ? options.disabledDays : [0, 0, 0, 0, 0, 0, 0]
        };
        if (options.disabledDates) {
            if (options.enabledDates) delete(options.enabledDates);
            opts.disabledDates = {};
            var startD;
            for (startD in options.disabledDates) {
                if ((String(startD).search(wcDateRegExp) != -1 && options.disabledDates[startD] == 1) || (String(startD).search(rangeRegExp) != -1 && String(options.disabledDates[startD]).search(rangeRegExp) != -1)) {
                    opts.disabledDates[startD] = options.disabledDates[startD]
                }
            }
        } else if (options.enabledDates) {
            var startD;
            opts.enabledDates = {};
            for (startD in options.enabledDates) {
                if ((String(startD).search(wcDateRegExp) != -1 && options.enabledDates[startD] == 1) || (String(startD).search(rangeRegExp) != -1 && String(options.enabledDates[startD]).search(rangeRegExp) != -1)) {
                    opts.enabledDates[startD] = options.enabledDates[startD]
                }
            }
        };
        datePickers[options.id] = new datePicker(opts);
        datePickers[options.id].callback("create", datePickers[options.id].createCbArgObj())
    };
    var isVisible = function (id) {
        return (!id || !(id in datePickers)) ? false : datePickers[id].visible
    };
    addEvent(window, 'unload', destroy);
    return {
        addEvent: function (obj, type, fn) {
            return addEvent(obj, type, fn)
        },
        removeEvent: function (obj, type, fn) {
            return removeEvent(obj, type, fn)
        },
        stopEvent: function (e) {
            return stopEvent(e)
        },
        show: function (inpID) {
            return showDatePicker(inpID, false)
        },
        hide: function (inpID) {
            return hideDatePicker(inpID)
        },
        createDatePicker: function (options) {
            addDatePicker(options)
        },
        destroyDatePicker: function (inpID) {
            destroySingleDatePicker(inpID)
        },
        cleanUp: function () {
            cleanUp()
        },
        printFormattedDate: function (dt, fmt, useImportedLocale) {
            return printFormattedDate(dt, fmt, useImportedLocale)
        },
        setDateFromInput: function (inpID) {
            if (!inpID || !(inpID in datePickers)) return false;
            datePickers[inpID].setDateFromInput()
        },
        setRangeLow: function (inpID, yyyymmdd) {
            if (!inpID || !(inpID in datePickers)) {
                return false
            };
            datePickers[inpID].setRangeLow(yyyymmdd)
        },
        setRangeHigh: function (inpID, yyyymmdd) {
            if (!inpID || !(inpID in datePickers)) {
                return false
            };
            datePickers[inpID].setRangeHigh(yyyymmdd)
        },
        setBespokeTitles: function (inpID, titles) {
            if (!inpID || !(inpID in datePickers)) {
                return false
            };
            datePickers[inpID].setBespokeTitles(titles)
        },
        addBespokeTitles: function (inpID, titles) {
            if (!inpID || !(inpID in datePickers)) {
                return false
            };
            datePickers[inpID].addBespokeTitles(titles)
        },
        parseDateString: function (str, format) {
            return parseDateString(str, format)
        },
        setGlobalVars: function (json) {
            affectJSON(json)
        },
        setSelectedDate: function (inpID, yyyymmdd) {
            if (!inpID || !(inpID in datePickers)) {
                return false
            };
            datePickers[inpID].setSelectedDate(yyyymmdd)
        },
        dateValidForSelection: function (inpID, dt) {
            if (!inpID || !(inpID in datePickers)) return false;
            return datePickers[inpID].canDateBeSelected(dt)
        },
        addDisabledDates: function (inpID, dts) {
            if (!inpID || !(inpID in datePickers)) return false;
            datePickers[inpID].addDisabledDates(dts)
        },
        setDisabledDates: function (inpID, dts) {
            if (!inpID || !(inpID in datePickers)) return false;
            datePickers[inpID].setDisabledDates(dts)
        },
        addEnabledDates: function (inpID, dts) {
            if (!inpID || !(inpID in datePickers)) return false;
            datePickers[inpID].addEnabledDates(dts)
        },
        setEnabledDates: function (inpID, dts) {
            if (!inpID || !(inpID in datePickers)) return false;
            datePickers[inpID].setEnabledDates(dts)
        },
        disable: function (inpID) {
            if (!inpID || !(inpID in datePickers)) return false;
            datePickers[inpID].disableDatePicker()
        },
        enable: function (inpID) {
            if (!inpID || !(inpID in datePickers)) return false;
            datePickers[inpID].enableDatePicker()
        },
        setCursorDate: function (inpID, yyyymmdd) {
            if (!inpID || !(inpID in datePickers)) return false;
            datePickers[inpID].setCursorDate(yyyymmdd)
        },
        getSelectedDate: function (inpID) {
            return (!inpID || !(inpID in datePickers)) ? false : datePickers[inpID].returnSelectedDate()
        },
        loadLanguage: function () {
            loadLanguage()
        },
        setDebug: function (dbg) {
            debug = !!(dbg)
        }
    }
})();
var fdLocale = {
                fullMonths:["January","February","March","April","May","June","July","August","September","October","November","December"],
                monthAbbrs:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],
                fullDays:  ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],
                dayAbbrs:  ["Mon","Tue","Wed","Thu","Fri","Sat","Sun"],
                titles:    ["Previous month","Next month","Previous year","Next year", "Today", "Open Calendar", "wk", "Week [[%0%]] of [[%1%]]", "Week", "Select a date", "Click \u0026 Drag to move", "Display \u201C[[%0%]]\u201D first", "Go to Today\u2019s date", "Disabled date:"],
                firstDayOfWeek:6
};
try { datePickerController.loadLanguage(); } catch(err) {} 

