/*
        DatePicker v4.4 by frequency-decoder.com

        Released under a creative commons Attribution-ShareAlike 2.5 license (http://creativecommons.org/licenses/by-sa/2.5/)

        Please credit frequency-decoder in any derivative work - thanks.
        
        You are free:

        * to copy, distribute, display, and perform the work
        * to make derivative works
        * to make commercial use of the work

        Under the following conditions:

                by Attribution.
                --------------
                You must attribute the work in the manner specified by the author or licensor.

                sa
                --
                Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license identical to this one.

        * For any reuse or distribution, you must make clear to others the license terms of this work.
        * Any of these conditions can be waived if you get permission from the copyright holder.
*/
var datePickerController;

(function() {

function pad(value, length) {
        value = String(value);
        length = parseInt(length) || 2;
        while (value.length < length) value = "0" + value;
        return value;
};

function datePicker(options) {

        this.defaults          = {};
        for(opt in options) { this[opt] = this.defaults[opt] = options[opt]; };
        
        this.date              = new Date();
        this.yearinc           = 1;
        this.timer             = null;
        this.pause             = 1000;
        this.timerSet          = false;
        this.fadeTimer         = null;
        this.interval          = new Date();
        this.firstDayOfWeek    = this.defaults.firstDayOfWeek = this.dayInc = this.monthInc = this.yearInc = this.opacity = this.opacityTo = 0;
        this.dateSet           = null;
        this.visible           = false;
        //this.disabledDates     = [];
        this.enabledDates      = [];
        this.nbsp              = String.fromCharCode( 160 );
        this.created           = false;
        this.weeksInYear       = { year:null, weeks:53 };
        
        var o = this;

        o.events = {
                onblur:function(e) {
                        o.removeKeyboardEvents();
                        if(o.statusBar) { o.updateStatus(o.getMessage(9)); };
                },
                onfocus:function(e) {
                        o.addKeyboardEvents();
                        if(o.statusBar) { o.updateStatus(datePickerController.printFormattedDate(o.date, o.statusFormat, true)); };
                },
                onkeydown: function (e) {
                        o.stopTimer();
                        if(!o.visible) return false;

                        if(e == null) e = document.parentWindow.event;
                        var kc = e.keyCode ? e.keyCode : e.charCode;

                        if( kc == 13 ) {
                                // close (return)
                                var td = document.getElementById(o.id + "-date-picker-hover");
                                if(!td || td.className.search(/out-of-range|day-disabled/) != -1) return o.killEvent(e);
                                o.returnFormattedDate();
                                o.hide();
                                return o.killEvent(e);
                        } else if(kc == 27) {
                                // close (esc)
                                o.hide();
                                return o.killEvent(e);
                        } else if(kc == 32 || kc == 0) {
                                // today (space)
                                o.date =  new Date();
                                o.updateTable();
                                return o.killEvent(e);
                        };

                        // Internet Explorer fires the keydown event faster than the JavaScript engine can
                        // update the interface. The following attempts to fix this.
                        /*@cc_on
                        @if(@_win32)
                                if(new Date().getTime() - o.interval.getTime() < 100) return o.killEvent(e);
                                o.interval = new Date();
                        @end
                        @*/

                        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();
                                o.updateTable();
                                return o.killEvent(e);
                        };

                        if ( kc < 37 || kc > 40 ) return true;

                        var d = new Date( o.date ).valueOf();

                        if ( kc == 37 ) {
                                // ctrl + left = previous month
                                if( e.ctrlKey ) {
                                        d = new Date( o.date );
                                        d.setDate( Math.min(d.getDate(), datePickerController.getDaysPerMonth(d.getMonth() - 1,d.getFullYear())) );
                                        d.setMonth( d.getMonth() - 1 );
                                } else {
                                        d = new Date( o.date.getFullYear(), o.date.getMonth(), o.date.getDate() - 1 );
                                };
                        } else if ( kc == 39 ) {
                                // ctrl + right = next month
                                if( e.ctrlKey ) {
                                        d = new Date( o.date );
                                        d.setDate( Math.min(d.getDate(), datePickerController.getDaysPerMonth(d.getMonth() + 1,d.getFullYear())) );
                                        d.setMonth( d.getMonth() + 1 );
                                } else {
                                        d = new Date( o.date.getFullYear(), o.date.getMonth(), o.date.getDate() + 1 );
                                };
                        } else if ( kc == 38 ) {
                                // ctrl + up = next year
                                if( e.ctrlKey ) {
                                        d = new Date( o.date );
                                        d.setDate( Math.min(d.getDate(), datePickerController.getDaysPerMonth(d.getMonth(),d.getFullYear() + 1)) );
                                        d.setFullYear( d.getFullYear() + 1 );
                                } else {
                                        d = new Date( o.date.getFullYear(), o.date.getMonth(), o.date.getDate() - 7 );
                                };
                        } else if ( kc == 40 ) {
                                // ctrl + down = prev year
                                if( e.ctrlKey ) {
                                        d = new Date( o.date );
                                        d.setDate( Math.min(d.getDate(), datePickerController.getDaysPerMonth(d.getMonth(),d.getFullYear() - 1)) );
                                        d.setFullYear( d.getFullYear() - 1 );
                                } else {
                                        d = new Date( o.date.getFullYear(), o.date.getMonth(), o.date.getDate() + 7 );
                                };
                        };

                        var tmpDate = new Date(d);

                        if(o.outOfRange(tmpDate)) return o.killEvent(e);
                        
                        var cacheDate = new Date(o.date);
                        o.date = tmpDate;

                        if(o.statusBar) { o.updateStatus(datePickerController.printFormattedDate(o.date, o.statusFormat, true)); };
                        
                        if(cacheDate.getFullYear() != o.date.getFullYear() || cacheDate.getMonth() != o.date.getMonth()) {
                                o.updateTable();
                        } else {
                                o.disableTodayButton();
                                var tds = o.table.getElementsByTagName('td');
                                var txt;
                                var start = o.date.getDate() - 6;
                                if(start < 0) start = 0;

                                for(var i = start, td; td = tds[i]; i++) {
                                        txt = Number(td.firstChild.nodeValue);
                                        if(isNaN(txt) || txt != o.date.getDate()) continue;
                                        o.removeHighlight();
                                        td.id = o.id + "-date-picker-hover";
                                        td.className = td.className.replace(/date-picker-hover/g, "") + " date-picker-hover";
                                };
                        };
                        return o.killEvent(e);
                },
                gotoToday: function(e) {
                        o.date = new Date();
                        o.updateTable();
                        return o.killEvent(e);
                },
                onmousedown: function(e) {
                        if ( e == null ) e = document.parentWindow.event;
                        var el = e.target != null ? e.target : e.srcElement;

                        var found = false;
                        while(el.parentNode) {
                                if(el.id && (el.id == "fd-"+o.id || el.id == "fd-but-"+o.id)) {
                                        found = true;
                                        break;
                                };
                                try {
                                        el = el.parentNode;
                                } catch(err) {
                                        break;
                                };
                        };
                        if(found) return true;
                        o.stopTimer();
                        datePickerController.hideAll();
                },
                ontablemouseout: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.className.replace('dp-row-highlight', '');
                                o.currentTR = null;
                        };
                        if(o.statusBar) { o.updateStatus(datePickerController.printFormattedDate(o.date, o.statusFormat, true)); };
                },
                ontablemouseover: 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 = o.getMessage(9);
                        switch (el.tagName.toLowerCase()) {
                                case "td":
                                        if(el.className.search(/date-picker-unused|out-of-range/) != -1) {
                                                statusText = o.getMessage(9);
                                        } else {
                                                o.stopTimer();
                                                var txt = el.firstChild.nodeValue;
                                                o.removeHighlight();
                                                el.id = o.id+"-date-picker-hover";
                                                el.className = el.className.replace(/date-picker-hover/g, "") + " date-picker-hover";
                                                o.date.setDate(el.firstChild.nodeValue);
                                                o.disableTodayButton();
                                                statusText = datePickerController.printFormattedDate(o.date, o.statusFormat, true);
                                        };
                                        break;
                                case "th":
                                        if(el.className.search(/drag-enabled/) != -1) {
                                                statusText = o.getMessage(10);
                                        } else if(el.className.search(/date-picker-week-header/) != -1) {
                                                var txt = el.firstChild.nodeValue;
                                                statusText = txt.search(/^(\d+)$/) != -1 ? o.getMessage(7, [txt, o.weeksInYear.weeks]) : o.getMessage(9);
                                        };
                                        break;
                                case "span":
                                        if(el.className.search(/drag-enabled/) != -1) {
                                                statusText = o.getMessage(10);
                                        } else if(el.className.search(/day-([0-6])/) != -1) {
                                                var day = el.className.match(/day-([0-6])/)[1];
                                                statusText = o.getMessage(11, [datePickerController.localeImport.fullDays[day]]);
                                        } else if(el.className.search(/prev-year/) != -1) {
                                                statusText = o.getMessage(2);
                                        } else if(el.className.search(/prev-month/) != -1) {
                                                statusText = o.getMessage(0);
                                        } else if(el.className.search(/next-year/) != -1) {
                                                statusText = o.getMessage(3);
                                        } else if(el.className.search(/next-month/) != -1) {
                                                statusText = o.getMessage(1);
                                        } else if(el.className.search(/today-but/) != -1 && el.className.search(/disabled/) == -1) {
                                                statusText = o.getMessage(12);
                                        };
                                        break;
                                default:
                                        statusText = "";
                        };
                        
                        /*@cc_on
                        var highLight = false;
                        @if (@_jscript_version >= 5.7)
                                if(document.compatMode == "BackCompat") { var highLight = true; };
                        @else
                                var highLight = true;
                        @end
                        if(highLight) {
                                while(el.parentNode) {
                                        el = el.parentNode;
                                        if(el.nodeType == 1 && el.tagName.toLowerCase() == "tr") {
                                                if(o.currentTR) {
                                                        o.currentTR.className = o.currentTR.className.replace('dp-row-highlight', '');
                                                };
                                                el.className = el.className + " dp-row-highlight";
                                                o.currentTR = el;
                                                break;
                                        };
                                };
                        };
                        @*/
                        
                        if(o.statusBar && statusText) { o.updateStatus(statusText); };
                },
                onclick: function(e) {
                        if(o.opacity != o.opacityTo || this.className.search(/out-of-range|day-disabled/) != -1) return false;
                        e = e || document.parentWindow.event;
                        var el = e.target != null ? e.target : e.srcElement;
                        while ( el.nodeType != 1 ) el = el.parentNode;

                        var txt = el.firstChild.data;

                        if(txt.search(/^[\d]+$/) == -1) return;
                        
                        var d = new Date( o.date );
                        var n = Number( txt );
                        if(isNaN(n)) { return true; };
                        
                        d.setDate( n );
                        o.date = d;
                        o.returnFormattedDate(true);
                        if(!o.staticPos) o.hide();
                        o.stopTimer();
                        return o.killEvent(e);
                },
                incDec: function(e) {
                        if ( e == null ) e = document.parentWindow.event;
                        var el = e.target != null ? e.target : e.srcElement;

                        if(el && el.className && el.className.search('fd-disabled') != -1) { return false; }
                        datePickerController.addEvent(document, "mouseup", o.events.clearTimer);
                        o.timerInc      = 800;
                        o.dayInc        = arguments[1];
                        o.yearInc       = arguments[2];
                        o.monthInc      = arguments[3];
                        o.timerSet      = true;

                        o.updateTable();
                        return true;
                },
                clearTimer: function(e) {
                        o.stopTimer();
                        o.timerInc      = 1000;
                        o.yearInc       = 0;
                        o.monthInc      = 0;
                        o.dayInc        = 0;
                        datePickerController.removeEvent(document, "mouseup", o.events.clearTimer);
                }
        };
        o.getMessage = function(num, replacements) {
                replacements = replacements || [];
                if(datePickerController.localeImport.titles.length > num) {
                         var txt = datePickerController.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 "";
        };
        o.stopTimer = function() {
                o.timerSet = false;
                window.clearTimeout(o.timer);
        };
        o.removeHighlight = function() {
                if(document.getElementById(o.id+"-date-picker-hover")) {
                        document.getElementById(o.id+"-date-picker-hover").className = document.getElementById(o.id+"-date-picker-hover").className.replace("date-picker-hover", "");
                        document.getElementById(o.id+"-date-picker-hover").id = "";
                };
        };
        o.reset = function() {
                for(def in o.defaults) { o[def] = o.defaults[def]; };
        };
        o.setOpacity = function(op) {
                o.div.style.opacity = op/100;
                o.div.style.filter = 'alpha(opacity=' + op + ')';
                o.opacity = op;
        };
        o.fade = function() {
                window.clearTimeout(o.fadeTimer);
                o.fadeTimer = null;
                delete(o.fadeTimer);
                
                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.visible = false;
                        } else {
                                o.visible = true;
                        };
                };
        };
        o.killEvent = function(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;
        };
        o.getElem = function() {
                return document.getElementById(o.id.replace(/^fd-/, '')) || false;
        };
        o.setRangeLow = function(range) {
                if(String(range).search(/^(\d\d\d\d)(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])$/) == -1) range = false;
                o.low = o.defaults.low = range;
                if(o.staticPos) o.updateTable(true);
        };
        o.setRangeHigh = function(range) {
                if(String(range).search(/^(\d\d\d\d)(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])$/) == -1) range = false;
                o.high = o.defaults.high = range;
                if(o.staticPos) o.updateTable(true);
        };
        o.setDisabledDays = function(dayArray) {
                o.disableDays = o.defaults.disableDays = dayArray;
                if(o.staticPos) o.updateTable(true);
        };
        o.setDisabledDates = function(dateArray) {
                var disabledDateObj = {}, parts;
                for(var i = dateArray.length; i-- ;) {
                        if(dateArray[i].match(/^(\d\d\d\d|\*\*\*\*)(0[1-9]|1[012]|\*\*)(0[1-9]|[12][0-9]|3[01])$/) != -1) {
                                disabledDateObj[dateArray[i]] = 1;
                        };
                };
                o.disabledDates = disabledDateObj;
                if(o.staticPos) { o.updateTable(true); };
        };
        o.getDisabledDates = function(y, m) {
                m = pad(m);
        
                var obj    = {},
                    d      = datePickerController.getDaysPerMonth(m - 1, y),
                    lower  = Number(String(y)+m+"01"),
                    upper  = Number(y+String(m)+d),
                    yyyymm = Number(String(y)+m),
                    dt1, dt2, rngLower, rngUpper;

                for(var dt in o.disabledDates) {
                        dt1 = dt.replace(/^(\*\*\*\*)/, y).replace(/^(\d\d\d\d)(\*\*)/, "$1"+m);
                        dt2 = o.disabledDates[dt];

                        if(dt2 === 1) {
                                if(lower <= dt1 && upper >= dt1) {
                                        obj[dt1] = dt2;
                                };
                                continue;
                        };
                        
                        // Range
                        if(Number(dt1.substr(0,6)) <= yyyymm && Number(dt2.substr(0,6)) >= yyyymm) {
                                // Same month
                                if(Number(dt1.substr(0,6)) == Number(dt2.substr(0,6))) {
                                        for(var i = dt1; i <= dt2; i++) {
                                                obj[i] = 1;
                                        };
                                        continue;
                                };
                        
                                // Different months but we only want this month
                                rngLower = Number(dt1.substr(0,6)) == yyyymm ? dt1 : lower;
                                rngUpper = Number(dt2.substr(0,6)) == yyyymm ? dt2 : upper;
                                for(var i = rngLower; i <= rngUpper; i++) {
                                                obj[i] = 1;
                                };
                        };
                };
                return obj;
        };

        o.setFirstDayOfWeek = function(e) {
                if ( e == null ) e = document.parentWindow.event;
                var elem = e.target != null ? e.target : e.srcElement;
                if(elem.tagName.toLowerCase() != "th") {
                        while(elem.tagName.toLowerCase() != "th") elem = elem.parentNode;
                };
                var cnt = o.showWeeks ? -1 : 0;
                while(elem.previousSibling) {
                        elem = elem.previousSibling;
                        if(elem.tagName.toLowerCase() == "th") cnt++;
                };
                o.firstDayOfWeek = (o.firstDayOfWeek + cnt) % 7;
                o.updateTableHeaders();
                return o.killEvent(e);
        };
        o.truePosition = function(element) {
                var pos = o.cumulativeOffset(element);
                if(window.opera) { return pos; }
                var iebody      = (document.compatMode && document.compatMode != "BackCompat")? document.documentElement : document.body;
                var dsocleft    = document.all ? iebody.scrollLeft : window.pageXOffset;
                var dsoctop     = document.all ? iebody.scrollTop  : window.pageYOffset;
                var posReal     = o.realOffset(element);
                return [pos[0] - posReal[0] + dsocleft, pos[1] - posReal[1] + dsoctop];
        };
        o.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];
        };
        o.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];
        };
        o.resize = function() {
                if(!o.created || !o.getElem() || 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;
                var osw = o.div.offsetWidth;
                
                o.div.style.visibility = "visible";
                o.div.style.display = "none";

                var elem          = document.getElementById('fd-but-' + o.id);
                var pos           = o.truePosition(elem);
                var trueBody      = (document.compatMode && document.compatMode!="BackCompat") ? document.documentElement : document.body;
                var scrollTop     = window.devicePixelRatio || window.opera ? 0 : trueBody.scrollTop;
                var scrollLeft    = window.devicePixelRatio || window.opera ? 0 : trueBody.scrollLeft;

                if(parseInt(trueBody.clientWidth+scrollLeft) < parseInt(osw+pos[0])) {
                        o.div.style.left = Math.abs(parseInt((trueBody.clientWidth+scrollLeft) - osw)) + "px";
                } else {
                        o.div.style.left  = pos[0] + "px";
                };

                if(parseInt(trueBody.clientHeight+scrollTop) < parseInt(osh+pos[1]+elem.offsetHeight+2)) {
                        o.div.style.top   = Math.abs(parseInt(pos[1] - (osh + 2))) + "px";
                } else {
                        o.div.style.top   = Math.abs(parseInt(pos[1] + elem.offsetHeight + 2)) + "px";
                };
                /*@cc_on
                @if(@_jscript_version <= 5.6)
                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
                @*/
        };
        o.equaliseDates = function() {
                var clearDayFound = false;
                var tmpDate;
                for(var i = o.low; i <= o.high; i++) {
                        tmpDate = String(i);
                        if(!o.disableDays[new Date(tmpDate.substr(0,4), tmpDate.substr(6,2), tmpDate.substr(4,2)).getDay() - 1]) {
                                clearDayFound = true;
                                break;
                        };
                };
                if(!clearDayFound) o.disableDays = o.defaults.disableDays = [0,0,0,0,0,0,0];
        };
        o.outOfRange = function(tmpDate) {
                if(!o.low && !o.high) return false;

                var level = false;
                if(!tmpDate) {
                        level = true;
                        tmpDate = o.date;
                };
                
                var d  = pad(tmpDate.getDate()),
                    m  = pad(tmpDate.getMonth() + 1),
                    y  = tmpDate.getFullYear(),
                    dt = String(y)+String(m)+String(d);

                if(o.low && +dt < +o.low) {
                        if(!level) return true;
                        o.date = new Date(o.low.substr(0,4), o.low.substr(4,2)-1, o.low.substr(6,2), 5, 0, 0);
                        return false;
                };
                if(o.high && +dt > +o.high) {
                        if(!level) return true;
                        o.date = new Date( o.high.substr(0,4), o.high.substr(4,2)-1, o.high.substr(6,2), 5, 0, 0);
                };
                return false;
        };
        o.createButton = function() {
                if(o.staticPos) { return; };
                
                var but = document.getElementById("fd-but-" + o.id);
                
                if(but) { return; };

                var inp = o.getElem();
                        
                but = document.createElement('a');
                but.href = "#";

                var span = document.createElement('span');
                span.appendChild(document.createTextNode(String.fromCharCode( 160 )));

                but.className = "date-picker-control";

                but.title = datePickerController.localeImport.titles && datePickerController.localeImport.titles.length > 5 ? datePickerController.localeImport.titles[5] : datePickerController.localeDefaults.titles[5];

                but.id = "fd-but-" + o.id;
                but.appendChild(span);

                if(inp.nextSibling) {
                        inp.parentNode.insertBefore(but, inp.nextSibling);
                } else {
                        inp.parentNode.appendChild(but);
                };
                
                but.onclick = but.onpress = function(e) {
                        e = e || window.event;
                        var inpId = this.id.replace('fd-but-','');
                        try { var dp = datePickerController.getDatePicker(inpId); } catch(err) { return false; };

                        if(e.type == "press") {
                                var kc = e.keyCode != null ? e.keyCode : e.charCode;
                                if(kc != 13) { return true; };
                                if(dp.visible) {
                                        hideAll();
                                        return false;
                                };
                        };

                        if(!dp.visible) {
                                datePickerController.hideAll(inpId);
                                dp.show();
                        } else {
                                datePickerController.hideAll();
                        };
                        return false;
                };
                
                but = null;
        },
        o.updateStatus = function(msg) {
                while(o.statusBar.firstChild) o.statusBar.removeChild(o.statusBar.firstChild);
                o.statusBar.appendChild(document.createTextNode(msg ? msg : o.getMessage(9)));
        },
        o.create = function() {
                if(o.created) { return; };
                
                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 || "";
                                if(details.onmousedown) but.onmousedown = details.onmousedown;
                                if(details.onclick)     but.onclick     = details.onclick;
                                if(details.onmouseout)  but.onmouseout  = details.onmouseout;
                                /*@cc_on
                                /*@if(@_win32)
                                but.unselectable = "on";
                                /*@end@*/
                                th.appendChild(but);
                        };
                };
                
                o.div = document.createElement('div');
                o.div.id = "fd-"+o.id;
                o.div.className = "datePicker";
                o.div.style.visibility = "hidden";
                
                if(!o.staticPos) {
                        document.getElementsByTagName('body')[0].appendChild(o.div);
                        /*@cc_on
                        @if(@_jscript_version <= 5.6)
                        o.iePopUp = document.createElement('iframe');
                        o.iePopUp.src = "javascript:'<html></html>';";
                        o.iePopUp.setAttribute('className','iehack');
                        o.iePopUp.scrolling="no";
                        o.iePopUp.frameBorder="0";
                        o.iePopUp.name = o.iePopUp.id = o.id + "-iePopUpHack";
                        document.body.appendChild(o.iePopUp);
                        @end
                        @*/
                } else {
                        elem = o.positioned ? document.getElementById(o.positioned) : o.getElem();
                        if(!elem) {
                                o.div = null;
                                throw o.positioned ? "Could not locate a datePickers associated parent element with an id:" + o.positioned : "Could not locate a datePickers associated input with an id:" + o.inp.id;
                        };
                        
                        o.div.className += " static-datepicker";
                        o.div.setAttribute("tabIndex", "0");
                        o.div.onfocus = o.events.onfocus;
                        o.div.onblur  = o.events.onblur;
                        if(o.positioned) {
                                elem.appendChild(o.div);
                        } else {
                                elem.parentNode.insertBefore(o.div, elem.nextSibling);
                        };
                        if(o.hideInput && elem.type && elem.type == "text") { elem.setAttribute("type", "hidden"); };
                };

                var tr, row, col, tableHead, tableBody, tableFoot;

                o.table = document.createElement('table');
                o.table.className = "datePickerTable";

                o.table.onmouseover = o.events.ontablemouseover;
                o.table.onmouseout  = o.events.ontablemouseout;
                
                o.div.appendChild( o.table );
                
                if(o.statusFormat) {
                        tablefoot = document.createElement('tfoot');
                        o.table.appendChild(tablefoot);
                        tr  = document.createElement('tr');
                        tr.className = "date-picker-tfoot";
                        tablefoot.appendChild(tr);
                        o.statusBar = createTH({thClassName:"date-picker-statusbar", colspan:o.showWeeks ? 8 : 7});
                        tr.appendChild(o.statusBar);
                        o.updateStatus();
                        if(!o.dragDisabled) {
                                o.statusBar.className += " drag-enabled";
                                datePickerController.addEvent(o.statusBar,'mousedown',o.startDrag, false);
                        };
                };
                
                tableHead = document.createElement('thead');
                o.table.appendChild( tableHead );
                
                tr  = document.createElement('tr');
                tableHead.appendChild(tr);

                // Title Bar
                o.titleBar = createTH({thClassName:!o.dragDisabled ? "date-picker-title drag-enabled" : "date-picker-title", colspan:o.showWeeks ? 8 : 7});
                if(!o.dragDisabled) {
                        datePickerController.addEvent(o.titleBar,'mousedown',o.startDrag, false);
                };
                
                tr.appendChild( o.titleBar );
                tr = null;
                
                var span = document.createElement('span');
                span.appendChild(document.createTextNode(o.nbsp));
                span.className = !o.dragDisabled ? "month-display drag-enabled" : "month-display";
                o.titleBar.appendChild(span);

                span = document.createElement('span');
                span.appendChild(document.createTextNode(o.nbsp));
                span.className = !o.dragDisabled ? "year-display drag-enabled" : "year-display";
                o.titleBar.appendChild(span);

                span = null;

                tr  = document.createElement('tr');
                tableHead.appendChild(tr);

                createThAndButton(tr, [
                        {className:"prev-but prev-year", id:"-prev-year-but", text:"\u00AB", title:datePickerController.localeImport.titles.length > 2 ? datePickerController.localeImport.titles[2] : datePickerController.localeDefaults.titles[2], onmousedown:function(e) { o.events.incDec(e,0,-1,0); }, onmouseout:o.events.clearTimer },
                        {className:"prev-but prev-month", id:"-prev-month-but", text:"\u2039", title:datePickerController.localeImport.titles.length > 0 ? datePickerController.localeImport.titles[0] : datePickerController.localeDefaults.titles[0], onmousedown:function(e) { o.events.incDec(e,0,0,-1); }, onmouseout:o.events.clearTimer },
                        {colspan:o.showWeeks ? 4 : 3, className:"today-but", id:"-today-but", text:datePickerController.localeImport.titles.length > 4 ? datePickerController.localeImport.titles[4] : datePickerController.localeDefaults.titles[4], onclick:o.events.gotoToday},
                        {className:"next-but next-month", id:"-next-month-but", text:"\u203A", title:datePickerController.localeImport.titles.length > 1 ? datePickerController.localeImport.titles[1] : datePickerController.localeDefaults.titles[1], onmousedown:function(e) { o.events.incDec(e,0,0,1); }, onmouseout:o.events.clearTimer },
                        {className:"next-but next-year", id:"-next-year-but", text:"\u00BB", title:datePickerController.localeImport.titles.length > 3 ? datePickerController.localeImport.titles[3] : datePickerController.localeDefaults.titles[3], onmousedown:function(e) { o.events.incDec(e,0,1,0); }, onmouseout:o.events.clearTimer }]);

                tableBody = document.createElement('tbody');
                o.table.appendChild( tableBody );

                var colspanTotal = o.showWeeks ? 8 : 7;
                var colOffset    = o.showWeeks ? 0 : -1;
                
                //
                for(var rows = 0; rows < 7; rows++) {
                        row = document.createElement('tr');

                        if(rows != 0) tableBody.appendChild(row);
                        else          tableHead.appendChild(row);
                        
                        for(var cols = 0; cols < colspanTotal; cols++) {
                                col = (rows === 0 || (o.showWeeks && cols === 0)) ? document.createElement('th') : document.createElement('td');
                                /*@cc_on@*/
                                /*@if(@_win32)
                                col.unselectable = "on";
                                /*@end@*/

                                row.appendChild(col);
                                if(!(rows === 0 || (o.showWeeks && cols === 0))) col.appendChild(document.createTextNode(o.nbsp));
                                if((o.showWeeks && cols > 0 && rows > 0) || (!o.showWeeks && rows > 0)) {
                                        col.onclick = o.events.onclick;
                                } else {
                                        if(rows === 0 && cols > colOffset) {
                                                col.className = "date-picker-day-header";
                                                col.scope = "col";

                                        } else {
                                                col.appendChild(document.createTextNode(o.nbsp));
                                                col.className = "date-picker-week-header";
                                                col.scope = "row";
                                        };
                                };
                        };
                };
                
                col = row = null;
                
                // Table headers
                var but;
                var ths = o.table.getElementsByTagName('thead')[0].getElementsByTagName('tr')[2].getElementsByTagName('th');
                for ( var y = 0; y < colspanTotal; y++ ) {
                        if(y == 0 && o.showWeeks) {
                                ths[y].removeChild(ths[y].firstChild);
                                ths[y].appendChild(document.createTextNode(o.getMessage(6)));
                                ths[y].title = o.getMessage(8);
                                continue;
                        };

                        if(y > (o.showWeeks ? 0 : -1)) {
                                but = document.createElement("span");
                                but.className = "fd-day-header";
                                but.onclick = ths[y].onclick = o.setFirstDayOfWeek;
                                /*@cc_on@*/
                                /*@if(@_win32)
                                but.unselectable = "on";
                                /*@end@*/
                                ths[y].appendChild(but);
                        };
                };
                but = null;
                
                o.ths = o.table.getElementsByTagName('thead')[0].getElementsByTagName('tr')[2].getElementsByTagName('th');
                o.trs = o.table.getElementsByTagName('tbody')[0].getElementsByTagName('tr');
                o.tds = [];
                
                for(i = 0; i < o.trs.length; i++) {
                        o.tds[i] = o.trs[i].getElementsByTagName('td');
                };
                
                if(o.showWeeks) {
                        o.wkThs = o.table.getElementsByTagName('tbody')[0].getElementsByTagName('th');
                        o.div.className += " weeks-displayed";
                };
                
                o.updateTableHeaders();
                
                tableBody = tableHead = tr = createThAndButton = createTH = null;

                if(o.low && o.high && (o.high - o.low < 7)) { o.equaliseDates(); };
                
                o.created = true;
                
                if(o.staticPos) {
                        var yyN = document.getElementById(o.id);
                        datePickerController.addEvent(yyN, "change", o.changeHandler);
                        if(o.splitDate) {
                                var mmN = document.getElementById(o.id+'-mm');
                                var ddN = document.getElementById(o.id+'-dd');
                                datePickerController.addEvent(mmN, "change", o.changeHandler);
                                datePickerController.addEvent(ddN, "change", o.changeHandler);
                        };
                        
                        o.show();
                        o.div.style.visibility = "visible";
                } else {
                        o.createButton();
                        o.resize();
                        o.div.style.visibility = "visible";
                        o.fade();
                };
        };
        o.startDrag = function(e) {
                e = e || window.event;
                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);
                datePickerController.addEvent(document,'mousemove',o.trackDrag, false);
                datePickerController.addEvent(document,'mouseup',o.stopDrag, false);
                o.div.style.zIndex = 10000;
                return o.killEvent(e);
        };
        o.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.6)
                if(o.staticPos) return;
                o.iePopUp.style.top    = o.div.style.top;
                o.iePopUp.style.left   = o.div.style.left;
                @end
                @*/
        };
        o.stopDrag = function(e) {
                datePickerController.removeEvent(document,'mousemove',o.trackDrag, false);
                datePickerController.removeEvent(document,'mouseup',o.stopDrag, false);
                o.div.style.zIndex = 9999;
        };
        o.changeHandler = function() {
                o.setDateFromInput();
                if(!o.splitDate) o.returnFormattedDate(true);
                o.updateTable();
        };
        o.getInnerText = function(el) {
                if (typeof el == "string" || typeof el == "undefined") return el;
                if(el.innerText) return el.innerText;
                var txt = '', i;
                for(i = el.firstChild; i; i = i.nextSibling) {
                        if(i.nodeType == 3)            txt += i.nodeValue;
                        else if(i.nodeType == 1)       txt += o.getInnerText(i);
                };
                return txt;
        };
        o.setDateFromInput = function() {
                o.dateSet = null;
                
                var elem = o.getElem();
                if(!elem) return;

                if(!o.splitDate) {
                        var date = datePickerController.parseDateString(elem.tagName.toLowerCase() == "input" ? elem.value : o.getInnerText(elem), o.format);
                } else {
                        var mmN  = document.getElementById(o.id+'-mm');
                        var ddN  = document.getElementById(o.id+'-dd');
                        var tm   = parseInt(mmN.tagName.toLowerCase() == "input"  ? mmN.value  : mmN.options[mmN.selectedIndex || 0].value, 10);
                        var td   = parseInt(ddN.tagName.toLowerCase() == "input"  ? ddN.value  : ddN.options[ddN.selectedIndex || 0].value, 10);
                        var ty   = parseInt(elem.tagName.toLowerCase() == "input" ? elem.value : elem.options[elem.selectedIndex || 0].value, 10);
                        var date = !(/\d\d\d\d/.test(ty)) || !(/^(0?[1-9]|1[012])$/.test(tm)) || !(/^(0?[1-9]|[12][0-9]|3[01])$/.test(td)) ? false : new Date(ty,tm-1,td);
                };

                if(!date || isNaN(date)) {
                        o.date = new Date();
                        o.date.setHours(5);
                        o.outOfRange();
                        return;
                };

                o.date = new Date(date);
                o.date.setHours(5);
                o.outOfRange();
                o.dateSet = new Date(o.date);
        };
        o.setSelectIndex = function(elem, indx) {
                var len = elem.options.length;
                indx = Number(indx);
                for(var opt = 0; opt < len; opt++) {
                        if(elem.options[opt].value == indx) {
                                elem.selectedIndex = opt;
                                return;
                        };
                };
        },
        o.returnFormattedDate = function(noChange) {
                var elem = o.getElem();
                if(!elem) return;

                var d                   = (o.date.getDate() < 10) ? "0" + o.date.getDate() : o.date.getDate();
                var m                   = ((o.date.getMonth() + 1) < 10) ? "0" + (o.date.getMonth() + 1) : o.date.getMonth() + 1;
                var yyyy                = o.date.getFullYear();
                var disabledDates       = o.getDisabledDates(yyyy, m);
                var weekDay             = ( o.date.getDay() + 6 ) % 7;

                if(!(o.disableDays[weekDay] || String(yyyy)+m+d in disabledDates)) {
                        if(o.splitDate) {
                                var ddE = document.getElementById(o.id+"-dd");
                                var mmE = document.getElementById(o.id+"-mm");

                                if(ddE.tagName.toLowerCase() == "input") { ddE.value = d; }
                                else { o.setSelectIndex(ddE, d); };
                                
                                if(mmE.tagName.toLowerCase() == "input") { mmE.value = m; }
                                else { o.setSelectIndex(mmE, m); };
                                
                                if(elem.tagName.toLowerCase() == "input") elem.value = yyyy;
                                else {
                                        o.setSelectIndex(elem, yyyy);
                                };
                        } else {
                                if(elem.tagName.toLowerCase() == "input") {
                                        elem.value = datePickerController.printFormattedDate(o.date, o.format);
                                } else {
                                        while(elem.firstChild) { elem.removeChild(elem.firstChild); };
                                        elem.appendChild(document.createTextNode(datePickerController.printFormattedDate(o.date, o.format)));
                                };
                        };
                        if(/input|select/.test(elem.tagName) && (!elem.type || elem.type && elem.type != "hidden")){ elem.focus(); }
                        if(o.staticPos) {
                                o.dateSet = new Date( o.date );
                                o.updateTable();
                        };
                        
                        if(noChange || /input|select/.test(elem.tagName)) return;

                        if(document.createEvent) {
                                var onchangeEvent = document.createEvent('HTMLEvents');
                                onchangeEvent.initEvent('change', true, false);
                                elem.dispatchEvent(onchangeEvent);
                        } else if(document.createEventObject) {
                                elem.fireEvent('onchange');
                        };
                };
        };
        o.disableTodayButton = function() {
                var today = new Date();
                document.getElementById(o.id + "-today-but").className = document.getElementById(o.id + "-today-but").className.replace("fd-disabled", "");
                if(o.outOfRange(today) || (o.date.getDate() == today.getDate() && o.date.getMonth() == today.getMonth() && o.date.getFullYear() == today.getFullYear())) {
                        document.getElementById(o.id + "-today-but").className += " fd-disabled";
                        document.getElementById(o.id + "-today-but").onclick = null;
                } else {
                        document.getElementById(o.id + "-today-but").onclick = o.events.gotoToday;
                };
        };
        o.updateTableHeaders = function() {
                var d, but;
                var ths          = o.ths;
                var colspanTotal = o.showWeeks ? 8 : 7;
                var colOffset    = o.showWeeks ? 1 : 0;

                for ( var col = colOffset; col < colspanTotal; col++ ) {
                        d = (o.firstDayOfWeek + (col - colOffset)) % 7;
                        ths[col].title = datePickerController.localeImport.fullDays[d];

                        if(col > colOffset) {
                                but = ths[col].getElementsByTagName("span")[0];
                                while(but.firstChild) but.removeChild(but.firstChild);
                                but.appendChild(document.createTextNode(datePickerController.localeImport.dayAbbrs ? datePickerController.localeImport.dayAbbrs[d] : datePickerController.localeImport.fullDays[d].charAt(0)));
                                but.title = datePickerController.localeImport.fullDays[d];
                                but.className = but.className.replace(/day-([0-6])/, "") + " day-" + d;
                                but = null;
                        } else {
                                while(ths[col].firstChild) ths[col].removeChild(ths[col].firstChild);
                                ths[col].appendChild(document.createTextNode(datePickerController.localeImport.dayAbbrs ? datePickerController.localeImport.dayAbbrs[d] : datePickerController.localeImport.fullDays[d].charAt(0)));
                        };
                        
                        ths[col].className = ths[col].className.replace(/date-picker-highlight/g, "");
                        if(o.highlightDays[d]) {
                                ths[col].className += " date-picker-highlight";
                        };
                };
                o.updateTable();
        };
        o.updateTable = function(noCallback) {
                if(o.timerSet) {
                        o.date.setDate( Math.min(o.date.getDate()+o.dayInc, datePickerController.getDaysPerMonth(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();
                o.disableTodayButton();
                
                var cd = o.date.getDate();
                var cm = o.date.getMonth();
                var cy = o.date.getFullYear();

                if(!cy in o.weeksInYear) {
                        o.weeksInYear[cy] = datePickerController.getWeeksInYear(cy);
                };
                
                // Set the tmpDate to the second day of this month (to avoid daylight savings time madness on Windows)
                var tmpDate = new Date( cy, cm, 2 );
                tmpDate.setHours(5);

                if(o.showWeeks) { var weekAdded = datePickerController.getWeekNumber(tmpDate); };
                
                var tdm                 = tmpDate.getMonth();
                var tdy                 = tmpDate.getFullYear();
                var disabledDates       = o.getDisabledDates(cy, cm + 1);

                // Previous buttons out of range
                var b = document.getElementById(o.id + "-prev-year-but");
                b.className = b.className.replace("fd-disabled", "");
                if(o.outOfRange(new Date((tdy - 1), tdm, datePickerController.getDaysPerMonth(+tdm, tdy-1)))) {
                        b.className += " fd-disabled";
                        if(o.yearInc == -1) o.stopTimer();
                };

                b = document.getElementById(o.id + "-prev-month-but")
                b.className = b.className.replace("fd-disabled", "");
                if(o.outOfRange(new Date(tdy, (+tdm - 1), datePickerController.getDaysPerMonth(+tdm-1, tdy)))) {
                        b.className += " fd-disabled";
                        if(o.monthInc == -1)  o.stopTimer();
                };

                // Next buttons out of range
                b= document.getElementById(o.id + "-next-year-but")
                b.className = b.className.replace("fd-disabled", "");
                if(o.outOfRange(new Date((tdy + 1), +tdm, 1))) {
                        b.className += " fd-disabled";
                        if(o.yearInc == 1)  o.stopTimer();
                };

                b = document.getElementById(o.id + "-next-month-but")
                b.className = b.className.replace("fd-disabled", "");
                if(o.outOfRange(new Date(tdy, +tdm + 1, 1))) {
                        b.className += " fd-disabled";
                        if(o.monthInc == 1)  o.stopTimer();
                };

                // Title Bar
                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(datePickerController.localeImport.fullMonths[cm] + o.nbsp));
                span[1].appendChild(document.createTextNode(cy));

                tmpDate.setDate( 1 );
                        
                var dt, cName, td, tds, i, currentDate, cellAdded, col;
                var weekDay             = ( tmpDate.getDay() + 6 ) % 7;
                var wkDay = weekDay;
                var firstColIndex       = (((weekDay - o.firstDayOfWeek) + 7 ) % 7) - 1;
                var dpm                 = datePickerController.getDaysPerMonth(cm, cy);
                var today               = new Date();
                today                   = today.getFullYear() + pad(today.getMonth()+1) + pad(today.getDate());
                var dateSetD            = (o.dateSet != null) ? o.dateSet.getFullYear() + pad(o.dateSet.getMonth()+1) + pad(o.dateSet.getDate()) : false;

                var stub                = String(tdy) + pad(tdm+1);
                var cellAdded           = [false, false, false, false, false, false];

                for(var curr = 0; curr < 42; curr++) {
                        row = Math.floor(curr / 7);
                        col = curr - (row * 7);
                        td  = o.tds[row][col];

                        if(curr > firstColIndex && curr <= (firstColIndex + dpm)) {
                                dt              = curr - firstColIndex;
                                currentDate     = stub + String(dt < 10 ? "0" : "") + dt;
                                td.replaceChild(document.createTextNode(dt), td.firstChild);
                                
                                if(o.low && +currentDate < o.low || o.high && +currentDate > o.high) { td.className = "out-of-range"; continue; };

                                cName = [];
                                weekDay = ( wkDay + dt + 6 ) % 7;
                                
                                if(currentDate == today) { cName.push("date-picker-today"); };
                                
                                if(dateSetD == currentDate) {cName.push("date-picker-selected-date");}

                                if(o.disableDays[weekDay] || currentDate in disabledDates) { cName.push("day-disabled"); }
                                else if(o.highlightDays[weekDay]) { cName.push("date-picker-highlight"); };
                                
                                if(cd == dt) { td.id = o.id + "-date-picker-hover"; cName.push("date-picker-hover");}
                                else { td.title = td.id = ""; };
                                
                                td.className = cName.join(" ");

                                if(o.showWeeks && !cellAdded[row]) {
                                         cellAdded[row] = true;
                                };
                        } else {
                                td.className = "date-picker-unused";
                                td.title = td.id = "";
                                td.replaceChild(document.createTextNode(o.nbsp), td.firstChild);
                        };
                        
                        if(o.showWeeks && col == 6) {
                                o.wkThs[row].innerHTML = cellAdded[row] ? datePickerController.getWeekNumber(cy, cm, curr - firstColIndex - 6) : o.nbsp;
                        };
                };
                
                if(o.timerSet) {
                        o.timerInc = 50 + Math.round(((o.timerInc - 50) / 1.8));
                        o.timer = window.setTimeout(o.updateTable, o.timerInc);
                };
        };
        o.addKeyboardEvents = function() {
                datePickerController.addEvent(document, "keypress", o.events.onkeydown);
                /*@cc_on
                @if(@_win32)
                datePickerController.removeEvent(document, "keypress", o.events.onkeydown);
                datePickerController.addEvent(document, "keydown", o.events.onkeydown);
                @end
                @*/
                if(window.devicePixelRatio) {
                        datePickerController.removeEvent(document, "keypress", o.events.onkeydown);
                        datePickerController.addEvent(document, "keydown", o.events.onkeydown);
                };
        };
        o.removeKeyboardEvents =function() {
                datePickerController.removeEvent(document, "keypress", o.events.onkeydown);
                datePickerController.removeEvent(document, "keydown",  o.events.onkeydown);
        };
        o.show = function() {
                var elem = o.getElem();
                if((!elem && o.created) || o.visible || elem.disabled) { return; };

                o.setDateFromInput();
                o.outOfRange();
                
                if(!o.created) {
                        o.create();
                } else {
                        o.updateTable();
                        if(!o.staticPos) o.resize();
                };
                
                datePickerController.addEvent(o.staticPos ? o.table : document, "mousedown", o.events.onmousedown);
                o.opacityTo = o.noFadeEffect ? 99 : 90;
                o.div.style.display = "block";
                if(!o.staticPos) {
                        /*@cc_on
                        @if(@_jscript_version <= 5.6)
                        o.iePopUp.style.display = "block";
                        @end
                        @*/
                        o.addKeyboardEvents();
                        o.fade();
                } else { o.opacity = o.opacityTo = 99 };
                
                o.visible = true;
        };
        o.hide = function() {
                if(!o.visible) return;
                o.stopTimer();
                if(o.staticPos) return;
                
                datePickerController.removeEvent(document, "mousedown", o.events.onmousedown);
                datePickerController.removeEvent(document, "mouseup",  o.events.clearTimer);
                o.removeKeyboardEvents();
                
                /*@cc_on
                @if(@_jscript_version <= 5.6)
                o.iePopUp.style.display = "none";
                @end
                @*/
                
                o.opacityTo = 0;
                o.fade();
                o.visible = false;
                var elem = o.getElem();
                if(!elem.type || elem.type && elem.type != "hidden") { /* elem.focus();*/ };
        };
        o.destroy = function() {
                // Cleanup for Internet Explorer
                datePickerController.removeEvent(o.staticPos ? o.table : document, "mousedown", o.events.onmousedown);
                datePickerController.removeEvent(document, "mouseup",   o.events.clearTimer);
                o.removeKeyboardEvents();

                if(o.staticPos) {
                        var yyN = document.getElementById(o.id);
                        datePickerController.removeEvent(yyN, "change", o.changeHandler);
                        if(o.splitDate) {
                                var mmN = document.getElementById(o.id+'-mm');
                                var ddN = document.getElementById(o.id+'-dd');

                                datePickerController.removeEvent(mmN, "change", o.changeHandler);
                                datePickerController.removeEvent(ddN, "change", o.changeHandler);
                        };
                        o.div.onfocus = o.div.onblur = null;
                };
                
                var ths = o.table.getElementsByTagName("th");
                for(var i = 0, th; th = ths[i]; i++) {
                        th.onmouseover = th.onmouseout = th.onmousedown = th.onclick = null;
                };
                
                var tds = o.table.getElementsByTagName("td");
                for(var i = 0, td; td = tds[i]; i++) {
                        td.onmouseover = td.onclick = null;
                };

                var butts = o.table.getElementsByTagName("span");
                for(var i = 0, butt; butt = butts[i]; i++) {
                        butt.onmousedown = butt.onclick = butt.onkeypress = null;
                };

                clearTimeout(o.fadeTimer);
                clearTimeout(o.timer);

                /*@cc_on
                @if(@_jscript_version <= 5.6)
                if(!o.staticPos) {
                        o.iePopUp.parentNode.removeChild(o.iePopUp);
                        o.iePopUp = null;
                };
                @end
                @*/
                
                if(!o.staticPos && document.getElementById(o.id.replace(/^fd-/, 'fd-but-'))) {
                        var butt = document.getElementById(o.id.replace(/^fd-/, 'fd-but-'));
                        butt.onclick = butt.onpress = null;
                };
                
                if(o.div && o.div.parentNode) {
                        o.div.parentNode.removeChild(o.div);
                };
                
                o.fadeTimer = o.timer = o.ths = o.trs = o.titleBar = o.table = o.div = null;
                if(o.wkThs) o.wkThs = null;
                
                o = null;
        };

        if(o.staticPos) { o.create(); }
        else { o.createButton(); };
};

datePickerController = function() {
        var datePickers   = {};
        var uniqueId      = 0;

        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%]]", "Week", "Select a date", "Click \u0026 Drag to move", "Display \u201C[[%0%]]\u201D first", "Go to Today\u2019s date"]
        };

        localeDefaults.monthAbbrStr = localeDefaults.monthAbbrs.join(",");
        localeDefaults.fullMonthStr = localeDefaults.fullMonths.join(",");
        localeDefaults.dayAbbrStr   = localeDefaults.dayAbbrs.join(",");
        localeDefaults.fullDayStr   = localeDefaults.fullDays.join(",");
        
        var localeImport = false;

        var addEvent = function(obj, type, fn) {
                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 );
                };
        };
        var removeEvent = function(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) {};
        };
        var hideAll = function(exception) {
                var dp;
                for(dp in datePickers) {
                        if(!datePickers[dp].created || datePickers[dp].staticPos) continue;
                        if(exception && exception == datePickers[dp].id) { continue; };
                        if(document.getElementById(datePickers[dp].id))  { datePickers[dp].hide(); };
                };
        };
        var cleanUp = function() {
                var dp;
                for(dp in datePickers) {
                        if(!document.getElementById(datePickers[dp].id)) {
                                if(!datePickers[dp].created) continue;
                                datePickers[dp].destroy();
                                datePickers[dp] = null;
                                delete datePickers[dp];
                        };
                };
        };
        var destroy = function() {
                for(dp in datePickers) {
                        if(!datePickers[dp].created) continue;
                        datePickers[dp].destroy();
                        datePickers[dp] = null;
                        delete datePickers[dp];
                };
                datePickers = null;
                removeEvent(window, 'load', datePickerController.create);
                removeEvent(window, 'unload', datePickerController.destroy);
        };
        var dateFormat = function(dateIn, favourMDY) {
                var dateTest = [
                        { regExp:/^(0?[1-9]|[12][0-9]|3[01])([- \/.])(0?[1-9]|1[012])([- \/.])((\d\d)?\d\d)$/, d:1, m:3, y:5 },  // dmy
                        { regExp:/^(0?[1-9]|1[012])([- \/.])(0?[1-9]|[12][0-9]|3[01])([- \/.])((\d\d)?\d\d)$/, d:3, m:1, y:5 },  // mdy
                        { regExp:/^(\d\d\d\d)([- \/.])(0?[1-9]|1[012])([- \/.])(0?[1-9]|[12][0-9]|3[01])$/,    d:5, m:3, y:1 }   // ymd
                        ];

                var start;
                var cnt = 0;
                while(cnt < 3) {
                        start = (cnt + (favourMDY ? 4 : 3)) % 3;
                        if(dateIn.match(dateTest[start].regExp)) {
                                res = dateIn.match(dateTest[start].regExp);
                                y = res[dateTest[start].y];
                                m = res[dateTest[start].m];
                                d = res[dateTest[start].d];
                                if(m.length == 1) m = "0" + m;
                                if(d.length == 1) d = "0" + d;
                                if(y.length != 4) y = (parseInt(y) < 50) ? '20' + y : '19' + y;
                                return String(y)+m+d;
                        };
                        cnt++;
                };
                return 0;
        };
        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 addDatePicker = function(options) {
                if(!options.id || options.id in datePickers) { return; };
                var elem = document.getElementById(options.id);
                if(!elem) throw "Cannot locate a datePicker parent element with an id of:" + options.id;
                
                if(elem.tagName.toLowerCase().search(/select|input/) == -1) {
                        options.staticPos       = true;
                        options.dragDisabled    = true;
                        options.splitDate       = 0;
                        options.noFadeEffect    = true;
                        options.hideInput       = false;
                };

                datePickers[options.id] = new datePicker(options);
        };
        var getDatePicker = function(inpId) {
                if(!(inpId in datePickers)) { throw "No datePicker has been created for the form element with an id of '" + inpId.toString() + "'"; };
                return datePickers[inpId];
        };
        var grepRangeLimits = function(sel) {
                var range = [];
                for(var i = 0; i < sel.options.length; i++) {
                        if(sel.options[i].value.search(/^\d\d\d\d$/) == -1) { continue; };
                        if(!range[0] || Number(sel.options[i].value) < range[0]) { range[0] = Number(sel.options[i].value); };
                        if(!range[1] || Number(sel.options[i].value) > range[1]) { range[1] = Number(sel.options[i].value); };
                };
                return range;
        };
        var getDaysPerMonth = 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) {
                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);
                }
                return Math.round((X2 - X1) / 604800000);
        };
        var parseRangeFromString = function(str) {
                var low = str.search(/^range-low-/) != -1;
                str = str.replace(/range-(low|high)-/, "");

                if(str.search(/^(\d\d\d\d)(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])$/) != -1) {
                        return dateFormat(str);
                };

                var tmpDate = new Date();
                
                if(str.search(/^today$/) != -1) {
                        return tmpDate.getFullYear() + pad(tmpDate.getMonth() + 1) + pad(tmpDate.getDate());
                };
                
                var regExp = /^(\d)-(day|week|month|year)$/;
                
                if(str.search(regExp) != -1) {
                        var parts       = str.match(regExp);
                        var acc         = { day:0,week:0,month:0,year:0 };
                        acc[parts[2]]   = low ? -(+parts[1]) : +parts[1];
                        tmpDate.setFullYear(tmpDate.getFullYear() + +acc.year);
                        tmpDate.setMonth(tmpDate.getMonth() + +acc.month);
                        tmpDate.setDate(tmpDate.getDate() + +acc.day + (7 * +acc.week));
                        return !tmpDate || isNaN(tmpDate) ? "" : tmpDate.getFullYear() + pad(tmpDate.getMonth() + 1) + pad(tmpDate.getDate());
                };
                
                return false;
        };
        
        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); // Nearest Thu
                var ms = d.valueOf(); // GMT
                d.setMonth(0);
                d.setDate(4); // Thu in Week 1
                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,2),
                                "D":useImportedLocale ? datePickerController.localeImport.dayAbbrs[D == 0 ? 6 : D - 1] : datePickerController.localeDefaults.dayAbbrs[D == 0 ? 6 : D - 1],
                                "l":useImportedLocale ? datePickerController.localeImport.fullDays[D == 0 ? 6 : D - 1] : datePickerController.localeDefaults.fullDays[D == 0 ? 6 : D - 1],
                                "j":d,
                                "N":D == 0 ? 7 : D,
                                "w":D,
                                "S":String(d).substr(-(Math.min(String(d).length, 2))) > 3 && String(d).substr(-(Math.min(String(d).length, 2))) < 21 ? "th" : ["th", "st", "nd", "rd", "th"][Math.min(+d%10, 4)],
                                "z":"?",
                                "W":datePickerController.getWeekNumber(date),
                                "M":useImportedLocale ? datePickerController.localeImport.monthAbbrs[m] : datePickerController.localeDefaults.monthAbbrs[m],
                                "F":useImportedLocale ? datePickerController.localeImport.fullMonths[m] : datePickerController.localeDefaults.fullMonths[m],
                                "m":pad(m),
                                "n":m,
                                "t":datePickerController.getDaysPerMonth(m + 1, y),
                                "Y":y,
                                "o":y,
                                "y":String(y).substr(2,2)
                            };

                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.split("-");

                loopLabel:
                for(var pt = 0, part; part = parts[pt]; pt++) {

                        if(str.length == 0) { return now; };
                                
                        switch(part) {
                                // Dividers
                                case "sp": // Space " "
                                                if(str.charAt(0).search(/\s/) != -1) {
                                                        // Be easy on the spaces...
                                                        while(str.charAt(0).search(/\s/) != -1) { str = str.substr(1); };
                                                        break;
                                                } else return "";
                                case "dt": // Dot "."
                                                if(str.charAt(0) == ".") {
                                                        str = str.substr(1);
                                                        break;
                                                } else return "";
                                case "sl": // slash "/"
                                                if(str.charAt(0) == "/") {
                                                        str = str.substr(1);
                                                        break;
                                                } else return "";
                                case "ds": // Dash "-"
                                                if(str.charAt(0) == "-") {
                                                        str = str.substr(1);
                                                        break;
                                                } else return "";
                                case "cc": // comma ","
                                                if(str.charAt(0) == ",") {
                                                        str = str.substr(1);
                                                        break;
                                                } else return "";
                                // DAY
                                case "d": // Day of the month, 2 digits with leading zeros (01 - 31)
                                                if(str.search(/^(0[1-9]|[12][0-9]|3[01])/) != -1) {
                                                        d = +str.substr(0,2);
                                                        str = str.substr(2);
                                                        break;
                                                } else return "";
                                                
                                case "D": // A textual representation of a day, three letters (Mon - Sun)
                                case "l": // A full textual representation of the day of the week (Monday - Sunday)
                                                l = part == "D" ? datePickerController.localeDefaults.dayAbbrs : datePickerController.localeDefaults.fullDays;
                                                for(var i = 0; i < 7; i++) {
                                                        if(new RegExp("^" + l[i], "i").test(str)) {
                                                                str = str.substr(l[i].length);
                                                                continue loopLabel;
                                                        };
                                                };
                                                return "";
                                case "j": // Day of the month without leading zeros (1 - 31)
                                                if(str.search(/^([1-9]|[12][0-9]|3[01])/) != -1) {
                                                        d = +str.match(/^([1-9]|[12][0-9]|3[01])/)[0];
                                                        str = str.substr(str.match(/^(\s?[1-9]|[12][0-9]|3[01])/)[0].length);
                                                        break;
                                                } else return "";
                                case "N": // ISO-8601 numeric representation of the day of the week (added in PHP 5.1.0) 1 (for Monday) through 7 (for Sunday)
                                case "w": // Numeric representation of the day of the week 0 (for Sunday) through 6 (for Saturday)
                                                if(str.search(part == "N" ? /^([1-7])/ : /^([0-6])/) != -1) {
                                                        str = str.substr(1);
                                                        break;
                                                } else return "";
                                case "S": // English ordinal suffix for the day of the month, 2 characters: st, nd, rd or th
                                                if(str.search(/^(st|nd|rd|th)/i) != -1) {
                                                        str = str.substr(2);
                                                        break;
                                                } else return "";
                                case "z": // The day of the year (starting from 0): 0 - 365
                                                if(str.search(/^([0-9]|[1-9][0-9]|[12][0-9]{2}|3[0-5][0-9]|36[0-5])/) != -1) {
                                                        str = str.substr(str.match(/^([0-9]|[1-9][0-9]|[12][0-9]{2}|3[0-5][0-9]|36[0-5])/)[0].length);
                                                        break;
                                                } else return "";
                                // WEEK
                                case "W": // ISO-8601 week number of year, weeks starting on Monday (added in PHP 4.1.0): 1 - 53
                                                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;
                                                } else return "";
                                // MONTH
                                case "M": // A short textual representation of a month, three letters
                                case "F": // A full textual representation of a month, such as January or March
                                                l = part == "M" ? datePickerController.localeDefaults.monthAbbrs : datePickerController.localeDefaults.fullMonths;
                                                for(var i = 0; i < 12; i++) {
                                                        if(str.search(new RegExp("^" + l[i],"i")) != -1) {
                                                                str = str.substr(l[i].length);
                                                                m = i;
                                                                continue loopLabel;
                                                        };
                                                };
                                                return "";
                                case "m": // Numeric representation of a month, with leading zeros
                                case "n": // Numeric representation of a month, without leading zeros
                                                l = part == "m" ? /^(0[1-9]|1[012])/ : /^([1-9]|1[012])/;
                                                if(str.search(l) != -1) {
                                                        m = +str.match(l)[0] - 1;
                                                        str = str.substr(str.match(l)[0].length);
                                                        break;
                                                } else return "";
                                case "t": // Number of days in the given month: 28 through 31
                                                if(str.search(/2[89]|3[01]/) != -1) {
                                                        str = str.substr(2);
                                                        break;
                                                } else return "";
                                // YEAR
                                case "Y": // A full numeric representation of a year, 4 digits
                                case "o": // ISO-8601 year number. This has the same value as Y
                                                if(str.search(/^(\d{4})/) != -1) {
                                                        y = str.substr(0,4);
                                                        str = str.substr(4);
                                                        break;
                                                } else return "";
                                case "y": // A two digit representation of a year
                                                if(str.search(/^(0[0-9]|[1-9][0-9])/) != -1) {
                                                        y = +str.substr(0,2);
                                                        y = +y < 50 ? '20' + y : '19' + y;
                                                        str = str.substr(2);
                                                        break;
                                                } else return "";
                                default:
                                                return "";
                        };
                };

                d = d === false ? now.getDate() : d;
                m = m === false ? now.getMonth() : m;
                y = y === false ? now.getFullYear() : y;
                        
                var tmpDate = new Date(y,m,d);
                return isNaN(tmpDate) ? "" : tmpDate;
        };
        
        var create = function(inp) {
                if(!(typeof document.createElement != "undefined" && typeof document.documentElement != "undefined" && typeof document.documentElement.offsetWidth == "number")) { return; };

                // Has the locale file loaded
                if(typeof(fdLocale) == "object" && !datePickerController.localeImport) {

                        localeImport = {
                                titles          : fdLocale.titles,
                                fullMonths      : fdLocale.fullMonths,
                                fullDays        : fdLocale.fullDays,
                                firstDayOfWeek  : ("firstDayOfWeek" in fdLocale) ? fdLocale.firstDayOfWeek : 0
                        };

                        if(fdLocale.dayAbbrs && fdLocale.dayAbbrs.length && fdLocale.dayAbbrs.length == 7) { localeImport.dayAbbrs = fdLocale.dayAbbrs; }
                        else {
                                localeImport.dayAbbr = [];
                                for(var i = 0; i < 7; i++) {
                                        localeImport.dayAbbr[i] = localeImport.fullDays[i].substr(0,3);
                                };
                        };
                        if(fdLocale.monthAbbrs && fdLocale.monthAbbrs.length && fdLocale.monthAbbrs.length == 12) { localeImport.monthAbbrs = fdLocale.monthAbbrs; }
                        else {
                                localeImport.monthAbbrs = [];
                                for(var i = 0; i < 12; i++) {
                                        localeImport.monthAbbrs[i] = localeImport.fullMonths[i].substr(0,3);
                                };
                        };
                        
                        localeImport.monthAbbrStr = localeImport.monthAbbrs.join(",");
                        localeImport.fullMonthStr = localeImport.fullMonths.join(",");
                        localeImport.dayAbbrStr   = localeImport.dayAbbrs.join(",");
                        localeImport.fullDayStr   = localeImport.fullDays.join(",");
                        localeImport.imported     = true;
                        
                        datePickerController.localeImport = localeImport;
                        
                } else if(!datePickerController.localeImport) {
                        datePickerController.localeImport.imported      = false;
                        datePickerController.localeImport               = localeDefaults;
                };

                var inputs = (inp && inp.tagName) ? [inp] : joinNodeLists(document.getElementsByTagName('input'), document.getElementsByTagName('select'));

                var disableDays  = /disable-days-([1-7]){1,6}/g;
                var highlight    = /highlight-days-([1-7]){1,7}/g;
                var rangeLow     = /range-low-(((\d\d\d\d)-?(0?[1-9]|1[012])-?(0?[1-9]|[12][0-9]|3[01]))|((\d)-(day|week|month|year))|(today))/;        // the lowest selectable date
                var rangeHigh    = /range-high-(((\d\d\d\d)-?(0?[1-9]|1[012])-?(0?[1-9]|[12][0-9]|3[01]))|((\d)-(day|week|month|year))|(today))/;       // the highest selectable date
                var dateFormat   = /dateformat(-((sp|dt|sl|ds|cc)|([d|D|l|j|N|w|S|z|W|M|F|m|n|t|Y|o|y|O|p])))+/;
                var statusFormat = /statusformat(-((sp|dt|sl|ds|cc)|([d|D|l|j|N|w|S|z|W|M|F|m|n|t|Y|o|y|O|p])))+/;
                var showXmonths  = /show-(\d)-months/i;
                var disableDates = /disable((-(\d\d\d\d)(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])){2}|(-((\d\d\d\d)|(xxxx))((0[1-9]|1[012])|(xx))(0[1-9]|[12][0-9]|3[01])))/g;
                var range, tmp, j, t;
                
                for(var i=0, inp; inp = inputs[i]; i++) {

                        if(inp.className && (inp.className.search(dateFormat) != -1 || inp.className.search(/split-date/) != -1) && ((inp.tagName.toLowerCase() == "input" && (inp.type == "text" || inp.type == "hidden")) || inp.tagName.toLowerCase() == "select")) {

                                if(inp.id && document.getElementById('fd-'+inp.id)) {
                                        datePickers[inp.id].createButton();
                                        continue;
                                };
                                
                                if(!inp.id) { inp.id = "fdDatePickerInput-" + uniqueId++; };
                                
                                var options = {
                                        id:inp.id,
                                        low:"",
                                        high:"",
                                        format:"d-sl-m-sl-Y",
                                        statusFormat:"",
                                        monthsToShow:1,
                                        highlightDays:[0,0,0,0,0,1,1],
                                        disableDays:[0,0,0,0,0,0,0],
                                        disabledDates:{},
                                        locale:inp.className.search(/no-locale/i) == -1,
                                        splitDate:0,
                                        noFadeEffect:inp.className.search(/no-animation/i) != -1,
                                        staticPos:inp.className.search(/display-inline/i) != -1,
                                        hideInput:inp.className.search(/hide-input/i) != -1,
                                        showWeeks:inp.className.search(/show-week/i) != -1,
                                        dragDisabled:inp.className.search(/disable-drag/i) != -1,
                                        positioned:""
                                };

                                if(!options.staticPos) {
                                        options.hideInput = false;
                                } else {
                                        options.noFadeEffect = true;
                                        options.dragDisabled = true;
                                        //options.positioned   = "test"; //inp.className.search(/display-inline-([^\S]+)/i) == -1 : "" : inp.className.match(/display-inline-([^\S]+)/i)[1];
                                };
                                
                                // Dates to disable
                                var dts = inp.className.match(disableDates), parts;
                                if(dts) {
                                        for(t = 0; t < dts.length; t++) {
                                                parts = dts[t].replace(/xxxx/, "****").replace(/xx/, "**").replace("disable-", "").split("-");
                                                options.disabledDates[parts[0]] = (parts.length && parts.length == 2) ? parts[1] : 1;
                                        };
                                };
                                
                                // Months to show...
                                if(inp.className.search(showXmonths) != -1) {
                                        options.monthsToShow = +inp.className.match(showXmonths)[1];
                                };
                                
                                // Split the date into three parts ?
                                if(inp.className.search(/split-date/) != -1) {
                                        if(document.getElementById(inp.id+'-dd') && document.getElementById(inp.id+'-mm') && document.getElementById(inp.id+'-dd').tagName.search(/input|select/i) != -1 && document.getElementById(inp.id+'-mm').tagName.search(/input|select/i) != -1) {
                                                options.splitDate = 1;
                                        } else throw "Cannot locate the two associated form elements for the element " + inp.id;
                                };
                                
                                // Date format
                                if(inp.className.search(dateFormat) != -1) {
                                        options.format = inp.className.match(dateFormat)[0].replace('dateformat-','');

                                };

                                // Status bar date format
                                if(inp.className.search(statusFormat) != -1) {
                                        options.statusFormat = inp.className.match(statusFormat)[0].replace('statusformat-','');
                                };
                                
                                // The days of the week to highlight
                                if(inp.className.search(highlight) != -1) {
                                        tmp = inp.className.match(highlight)[0].replace(/highlight-days-/, '');
                                        options.highlightDays = [0,0,0,0,0,0,0];
                                        for(j = 0; j < tmp.length; j++) {
                                                options.highlightDays[tmp.charAt(j) - 1] = 1;
                                        };
                                };

                                // The days of the week to disable
                                if(inp.className.search(disableDays) != -1) {
                                        tmp = inp.className.match(disableDays)[0].replace(/disable-days-/, '');
                                        options.disableDays = [0,0,0,0,0,0,0];
                                        for(j = 0; j < tmp.length; j++) {
                                                options.disableDays[tmp.charAt(j) - 1] = 1;
                                        };
                                };

                                // The lower limit
                                if(inp.className.search(rangeLow) != -1) {
                                        options.low = parseRangeFromString(inp.className.match(rangeLow)[0]);
                                };

                                // The higher limit
                                if(inp.className.search(rangeHigh) != -1) {
                                        options.high = parseRangeFromString(inp.className.match(rangeHigh)[0]);
                                };

                                // Always round lower & higher limits if a selectList involved
                                if(inp.tagName.search(/select/i) != -1) {
                                        range        = grepRangeLimits(inp);
                                        options.low  = options.low  ? range[0] + String(options.low).substr(4,4)  : range[0] + "0101";
                                        options.high = options.high ? range[1] + String(options.high).substr(4,4) : range[1] + "1231";
                                };

                                addDatePicker(options);
                        };
                };
        };
        
        return {
                addEvent:addEvent,
                removeEvent:removeEvent,
                create:create,
                destroy:destroy,
                cleanUp:cleanUp,
                addDatePicker:addDatePicker,
                getDatePicker:getDatePicker,
                dateFormat:dateFormat,
                datePickers:datePickers,
                hideAll:hideAll,
                localeDefaults:localeDefaults,
                localeImport:localeImport,
                getDaysPerMonth:getDaysPerMonth,
                getWeekNumber:getWeekNumber,
                printFormattedDate:printFormattedDate,
                parseDateString:parseDateString,
                getWeeksInYear:getWeeksInYear
        };
}();

// Load the appropriate language file
var languageinfo = navigator.language ? navigator.language.toLowerCase().replace(/-[a-z]+$/, "") : navigator.userLanguage ? navigator.userLanguage.toLowerCase().replace(/-[a-z]+$/, "") : "en";

if(languageinfo != "en") {
        var scriptFiles  = document.getElementsByTagName('head')[0].getElementsByTagName('script');
        var loc          = scriptFiles[scriptFiles.length - 1].src.substr(0, scriptFiles[scriptFiles.length - 1].src.lastIndexOf("/")) + "/lang/" + languageinfo + ".js";

        var script  = document.createElement('script');
        script.type = "text/javascript";
        script.src  = loc;
        script.setAttribute("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);
        };
        @else @*/
        document.getElementsByTagName('head')[0].appendChild(script);
        /*@end
        @*/
        script  = null;
};
})();


datePickerController.addEvent(window, 'load', datePickerController.create);
datePickerController.addEvent(window, 'unload', datePickerController.destroy);

