Skip to content

Commit

Permalink
Updated minified version
Browse files Browse the repository at this point in the history
  • Loading branch information
freqdec committed Mar 1, 2014
1 parent a641cef commit 0c2d1ef
Showing 1 changed file with 2 additions and 2 deletions.

2 comments on commit 0c2d1ef

@hmuus
Copy link

@hmuus hmuus commented on 0c2d1ef Mar 10, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

date suffix is hard coded
working solution attached

still not glad about remaining hardcoded regex in
datePicker.prototype.updateStatus 3times
datePicker.prototype.setDateFromInput once
var parseDateString case "S" once

languagefile ------------------------------------------------
var fdLocale = {
fullMonths:["January","February","March","April","May","June","July","August","September","October","November","December"],
monthAbbrs:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],
fullDays: ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],
dayAbbrs: ["Mon","Tue","Wed","Thu","Fri","Sat","Sun"],
daySuffix: ["th", "st", "nd", "rd"],
titles: ["Previous month","Next month","Previous year","Next year", "Today", "Open Calendar", "wk", "Week [[%0%]] of [[%1%]]", "Week", "Select a date", "Click \u0026 Drag to move", "Display \u201C[[%0%]]\u201D first", "Go to Today\u2019s date", "Disabled date:"],
firstDayOfWeek:0
};
try {
if("datePickerController" in window) {
datePickerController.loadLanguage();
};
} catch(err) {};
languagefile ------------------------------------------------
datepicker ------------------------------------------------
/*! DatePicker v6.3.4 MIT/GPL2 @freqdec */
var datePickerController = (function datePickerController() {

"use strict";

var debug               = false,
    isOpera             = Object.prototype.toString.call(window.opera) === "[object Opera]",
    describedBy         = "",
    languageInfo        = parseUILanguage(),
    nbsp                = String.fromCharCode(160),
    datePickers         = {},
    weeksInYearCache    = {},
    bespokeTitles       = {},
    uniqueId            = 0,
    finalOpacity        = 100,
    cssAnimations       = null,
    transitionEnd       = "",
    buttonTabIndex      = true,
    mouseWheel          = true,
    deriveLocale        = true,
    localeImport        = false,
    nodrag              = false,
    langFileFolder      = false,
    returnLocaleDate    = false,
    kbEvent             = false,
    dateParseFallback   = true,
    cellFormat          = "%d %F %Y",
    titleFormat         = "%F %d, %Y",
    statusFormat        = "",
    formatParts         = isOpera ? ["%j"] : ["%j", " %F %Y"],
    dPartsRegExp        = /%([d|j])/,
    mPartsRegExp        = /%([M|F|m|n])/,
    yPartsRegExp        = /%[y|Y]/,
    noSelectionRegExp   = /date-picker-unused|out-of-range|day-disabled|not-selectable/,
    formatTestRegExp    = /%([d|j|M|F|m|n|Y|y])/,
    formatSplitRegExp   = /%([d|D|l|j|N|w|S|W|M|F|m|n|t|Y|y])/,
    rangeRegExp         = /^((\d\d\d\d)(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01]))$/,
    wcDateRegExp        = /^(((\d\d\d\d)|(\*\*\*\*))((0[1-9]|1[012])|(\*\*))(0[1-9]|[12][0-9]|3[01]))$/,
    wsCharClass         = "\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029",
    // https://gist.github.com/padolsey/527683
    oldIE               = (function(){var undef,v = 3,div = document.createElement('div'),all = div.getElementsByTagName('i');while (div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',all[0]); return v > 4 ? v : undef;}());

(function() {
    var scriptFiles = document.getElementsByTagName('script'),
        json        = parseJSON(String(scriptFiles[scriptFiles.length - 1].innerHTML).replace(/[\n\r\s\t]+/g, " ").replace(/^\s+/, "").replace(/\s+$/, ""));

    if(typeof json === "object" && !("err" in json)) {
        affectJSON(json);
    };

    if(deriveLocale && typeof(fdLocale) != "object") {
        var head   = document.getElementsByTagName("head")[0] || document.documentElement,
            loc    = langFileFolder ? langFileFolder : scriptFiles[scriptFiles.length - 1].src.substr(0, scriptFiles[scriptFiles.length - 1].src.lastIndexOf("/")) + "/lang/",
            script,
            i;

        for(i = 0; i < languageInfo.length; i++) {
            script          = document.createElement('script');
            script.type     = "text/javascript";
            script.src      = loc + languageInfo[i] + ".js";
            script.charSet  = "utf-8";

            if(oldIE && oldIE < 8) {
                var bases = document.getElementsByTagName('base');
                if (bases.length && bases[0].childNodes.length) {
                        bases[0].appendChild(script);
                } else {
                        head.appendChild(script);
                };
                bases = null;
            } else {
                head.appendChild(script);
            };
        };

        script = null;
    } else {
        returnLocaleDate = true;
    };
})();

function removeChildNodes(elem) {
    while(elem.firstChild) {
        elem.removeChild(elem.firstChild);
    };
};

function addClass(e, c) {
    if(new RegExp("(^|[" + wsCharClass + "])" + c + "([" + wsCharClass + "]|$)").test(e.className)) {
        return;
    };
    e.className += ( e.className ? " " : "" ) + c;
};

function removeClass(e, c) {
    e.className = !c ? "" : e.className.replace(new RegExp("(^|[" + wsCharClass + "])" + c + "([" + wsCharClass + "]|$)"), " ").replace(new RegExp("/^[" + wsCharClass + "][" + wsCharClass + "]*/"), '').replace(new RegExp("/[" + wsCharClass + "][" + wsCharClass + "]*$/"), '');
};

// Attempts to parse the current language from the HTML element. Defaults to "en" if none given
function parseUILanguage() {
    var languageTag = document.getElementsByTagName('html')[0].getAttribute('lang') || document.getElementsByTagName('html')[0].getAttribute('xml:lang');
    languageTag = !languageTag ? "en" : languageTag.toLowerCase();
    return languageTag.search(/^([a-z]{2,3})-([a-z]{2})$/) != -1 ? [languageTag.match(/^([a-z]{2,3})-([a-z]{2})$/)[1], languageTag] : [languageTag];
};

// Cross browser split from http://blog.stevenlevithan.com/archives/cross-browser-split
var cbSplit = function(str, separator, limit) {
    // if `separator` is not a regex, use the native `split`
    if(Object.prototype.toString.call(separator) !== "[object RegExp]") {
            return cbSplit._nativeSplit.call(str, separator, limit);
    };

    var output        = [],
        lastLastIndex = 0,
        flags         = "",
        separator     = RegExp(separator.source, "g"),
        separator2, match, lastIndex, lastLength;

    str = str + "";

    if(!cbSplit._compliantExecNpcg) {
        separator2 = RegExp("^" + separator.source + "$(?!\\s)", flags);
    };

    /* behavior for `limit`: if it's...
    - `undefined`: no limit.
    - `NaN` or zero: return an empty array.
    - a positive number: use `Math.floor(limit)`.
    - a negative number: no limit.
    - other: type-convert, then use the above rules. */
    if(limit === undefined || +limit < 0) {
        limit = Infinity;
    } else {
        limit = Math.floor(+limit);
        if(!limit) {
            return [];
        };
    };

    while(match = separator.exec(str)) {
        lastIndex = match.index + match[0].length; // `separator.lastIndex` is not reliable cross-browser

        if (lastIndex > lastLastIndex) {
            output.push(str.slice(lastLastIndex, match.index));

            // fix browsers whose `exec` methods don't consistently return `undefined` for nonparticipating capturing groups
            if(!cbSplit._compliantExecNpcg && match.length > 1) {
                match[0].replace(separator2, function () {
                    for (var i = 1; i < arguments.length - 2; i++) {
                        if(arguments[i] === undefined) {
                            match[i] = undefined;
                        };
                    };
                });
            };

            if(match.length > 1 && match.index < str.length) {
                Array.prototype.push.apply(output, match.slice(1));
            };

            lastLength = match[0].length;
            lastLastIndex = lastIndex;

            if(output.length >= limit) {
                break;
            };
        };

        if(separator.lastIndex === match.index) {
            // avoid an infinite loop
            separator.lastIndex++;
        };
    };

    if(lastLastIndex === str.length) {
        if (lastLength || !separator.test("")) {
            output.push("");
        };
    } else {
        output.push(str.slice(lastLastIndex));
    };

    return output.length > limit ? output.slice(0, limit) : output;
};
// NPCG: nonparticipating capturing group
cbSplit._compliantExecNpcg = /()??/.exec("")[1] === undefined;
cbSplit._nativeSplit = String.prototype.split;

// Affects the JSON passed to the script
function affectJSON(json) {
    if(!(typeof json === "object")) {
        return;
    };

    var key,
        switchObj = {
            "debug":function(value) {
                debug = !!value;
                return true;
            },
            "lang":function(value) {
                if(typeof value === "string" && value.search(/^[a-z]{2,3}(-([a-z]{2}))?$/i) != -1) {
                    languageInfo = [value.toLowerCase()];
                    returnLocaleDate = true;
                    deriveLocale = true;
                };
                return true;
            },
            "nodrag":function(value) {
                nodrag = !!value;
                return true;
            },
            "buttontabindex":function(value) {
                buttonTabIndex = !!value;
                return true;
            },
            "derivelocale":function(value) {
                deriveLocale = !!value;
                return true;
            },
            "mousewheel":function(value) {
                mouseWheel = !!value;
                return true;
            },
            "cellformat":function(value) {
                if(typeof value === "string") {
                    parseCellFormat(value);
                };
                return true;
            },
            "titleformat":function(value) {
                if(typeof value === "string") {
                    titleFormat = value;
                };
                return true;
            },
            "statusformat":function(value) {
                if(typeof value === "string") {
                    statusFormat = value;
                };
                return true;
            },
            "describedby":function(value) {
                if(typeof value === "string") {
                    describedBy = value;
                };
                return true;
            },
            "finalopacity":function(value) {
                if(typeof value === 'number' && (+value > 20 && +value <= 100)) {
                    finalOpacity = parseInt(value, 10);
                };
                return true;
            },
            "bespoketitles":function(value) {
                if(typeof value === "object") {
                    bespokeTitles = {};
                    for(var dt in value) {
                        if(value.hasOwnProperty(dt) && String(dt).match(wcDateRegExp) != -1) {
                            bespokeTitles[dt] = String(value[dt]);
                        };
                    };
                };
                return true;
            },
            "dateparsefallback":function(value) {
                dateParseFallback = !!value;
                return true;
            },
            "languagefilelocation":function(value) {
                langFileFolder = value;
                return true;
            },
            "_default":function() {
                if(debug) {
                    throw "Unknown key located within JSON data: " + key;
                };
                return true;
            }
        };

    for(key in json) {
        if(!json.hasOwnProperty(key)) {
            continue;
        };
        (switchObj.hasOwnProperty(String(key).toLowerCase()) && switchObj[String(key).toLowerCase()] || switchObj._default)(json[key]);
    };
};

// Parses the JSON passed either between the script tags or by using the
// setGlobalOptions method
function parseJSON(str) {
    if(!(typeof str === 'string') || str == "") {
        return {};
    };
    try {
        // Does a JSON (native or not) Object exist
        if(typeof JSON === "object" && JSON.parse) {
            return window.JSON.parse(str);
        // Genious code taken from: http://kentbrewster.com/badges/
        } else if(/debug|lang|nodrag|buttontabindex|derivelocale|mousewheel|cellformat|titleformat|statusformat|describedby|finalopacity|bespoketitles|dateparsefallback/.test(str.toLowerCase())) {
            var f = Function(['var document,top,self,window,parent,Number,Date,Object,Function,',
                'Array,String,Math,RegExp,Image,ActiveXObject;',
                'return (' , str.replace(/<\!--.+-->/gim,'').replace(/\bfunction\b/g,'function-') , ');'].join(''));
            return f();
        };
    } catch (e) { };

    if(debug) {
        throw "Could not parse the JSON object";
    };

    return {"err":1};
};

// Parses the cell format to use whenever the datepicker has keyboard focus
function parseCellFormat(value) {
    if(isOpera) {
        // Don't use hidden text for opera due to the default
        // "blue" browser focus outline stretching outside of the viewport
        // and degrading visual accessibility. Harsh & hackish though...
        formatParts = ["%j"];
        cellFormat  = "%j %F %Y";
        return;
    };

    // If no day part stipulated then use presets
    if(value.match(/%([d|j])/) == -1) {
        return;
    };

    // Basic split on the %j or %d modifiers
    formatParts = cbSplit(value, /%([d|j])/);
    cellFormat  = value;
};

function pad(value, length) {
    length = Math.min(4, length || 2);
    return "0000".substr(0,length - Math.min(String(value).length, length)) + value;
};

// Very, very basic event functions
function addEvent(obj, type, fn) {
    if(obj.addEventListener) {
        obj.addEventListener(type, fn, true);
    } else if(obj.attachEvent) {
        obj.attachEvent("on"+type, fn);
    };
};
function removeEvent(obj, type, fn) {
    try {
        if(obj.removeEventListener) {
            obj.removeEventListener(type, fn, true);
        } else if(obj.detachEvent) {
            obj.detachEvent("on"+type, fn);
        };
    } catch(err) {};
};
function stopEvent(e) {
    e = e || document.parentWindow.event;
    if(e.stopPropagation) {
        e.stopPropagation();
        e.preventDefault();
    };

    if(oldIE) {
        e.cancelBubble = true;
        e.returnValue = false;
    };

    return false;
};

function setARIARole(element, role) {
    if(element && element.tagName) {
        element.setAttribute("role", role);
    };
};

function setARIAProperty(element, property, value) {
    if(element && element.tagName) {
        element.setAttribute("aria-" + property, value);
    };
};

// Sets a tabindex attribute on an element, bends over for IE.
function setTabIndex(e, i) {
    e.setAttribute(oldIE ? "tabIndex" : "tabindex", i);
    e.tabIndex = i;
};

function dateToYYYYMMDD(dt) {
    return dt instanceof Date && !isNaN(dt) ? dt.getFullYear() + pad(dt.getMonth() + 1) + "" + pad(dt.getDate()) : dt;
};

// The datePicker object itself
function datePicker(options) {
    this.dateSet             = null;
    this.timerSet            = false;
    this.visible             = false;
    this.fadeTimer           = null;
    this.timer               = null;
    this.yearInc             = 0;
    this.monthInc            = 0;
    this.dayInc              = 0;
    this.mx                  = 0;
    this.my                  = 0;
    this.x                   = 0;
    this.y                   = 0;
    this.created             = false;
    this.disabled            = false;
    this.opacity             = 0;
    this.opacityTo           = 100;
    this.finalOpacity        = 100;
    this.inUpdate            = false;
    this.kbEventsAdded       = false;
    this.fullCreate          = false;
    this.selectedTD          = null;
    this.cursorTD            = null;
    this.cursorDate          = options.cursorDate ? options.cursorDate : "",
    this.date                = options.cursorDate ? new Date(+options.cursorDate.substr(0,4), +options.cursorDate.substr(4,2) - 1, +options.cursorDate.substr(6,2),5,0,0) : new Date();
    this.defaults            = {};
    this.dynDisabledDates    = {};
    this.dateList            = [];
    this.bespokeClass        = options.bespokeClass;
    this.firstDayOfWeek      = localeImport.firstDayOfWeek;
    this.interval            = new Date();
    this.clickActivated      = false;
    this.showCursor          = false;
    this.noFocus             = true;
    this.kbEvent             = false;
    this.delayedUpdate       = false;
    this.bespokeTitles       = {};
    this.bespokeTabIndex     = options.bespokeTabIndex;

    for(var thing in options) {
        if(!options.hasOwnProperty(thing) || String(thing).search(/^(callbacks|formElements|enabledDates|disabledDates)$/) != -1) {
            continue;
        };
        this[thing] = options[thing];
    };

    if(oldIE) {
        this.iePopUp = null;
    };

    for(var i = 0, prop; prop = ["callbacks", "formElements"][i]; i++) {
        this[prop] = {};
        if(prop in options) {
            for(thing in options[prop]) {
                if(options[prop].hasOwnProperty(thing)) {
                        this[prop][thing] = options[prop][thing];
                };
            };
        };
    };

    // Adjust time to stop daylight savings madness on windows
    this.date.setHours(5);

    // Called from an associated form elements onchange event
    this.changeHandler = function() {
        // In a perfect world this shouldn't ever happen
        if(o.disabled) {
            return;
        };
        o.setDateFromInput();
        o.callback("dateset", o.createCbArgObj());
    };

    // Creates the object passed to the callback functions
    this.createCbArgObj = function() {
        return this.dateSet ? {
            "id"    :this.id,
            "date"  :this.dateSet,
            "dd"    :pad(this.date.getDate()),
            "mm"    :pad(this.date.getMonth() + 1),
            "yyyy"  :this.date.getFullYear()
            } : {
            "id"    :this.id,
            "date"  :null,
            "dd"    :null,
            "mm"    :null,
            "yyyy"  :null
            };
    };

    // Attempts to grab the window scroll offsets
    this.getScrollOffsets = function() {
        if(typeof(window.pageYOffset) == 'number') {
            //Netscape compliant
            return [window.pageXOffset, window.pageYOffset];
        } else if(document.body && (document.body.scrollLeft || document.body.scrollTop)) {
            //DOM compliant
            return [document.body.scrollLeft, document.body.scrollTop];
        } else if(document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
            //IE6 standards compliant mode
            return [document.documentElement.scrollLeft, document.documentElement.scrollTop];
        };
        return [0,0];
    };

    // Calculates the current list of disabled & enabled dates for a specific year/month
    this.getDateExceptions = function(y, m) {

        m = pad(m);

        var obj     = {},
            lower   = o.firstDateShown,
            upper   = o.lastDateShown,
            rLength = o.dateList.length,
            rNumber, workingDt, workingY, workingM, dtLower, dtUpper, i, dt, dt1, dt2, rngLower, rngUpper, cDate;

        if(!upper || !lower) {
            lower = o.firstDateShown = y + pad(m) + "01";
            upper = o.lastDateShown  = y + pad(m) + pad(daysInMonth(m, y));
        };

        dtLower = Number(lower.substr(0,6));
        dtUpper = Number(upper.substr(0,6));

        workingDt = String(dtLower);

        while(+workingDt <= dtUpper) {
            workingY = workingDt.substr(0,4);
            workingM = workingDt.substr(4,2);

            for(rNumber = 0; rNumber < rLength; rNumber++) {
                dt1 = String(o.dateList[rNumber].rLow).replace(/^(\*\*\*\*)/, workingY).replace(/^(\d\d\d\d)(\*\*)/, "$1"+workingM);
                dt2 = String(o.dateList[rNumber].rHigh).replace(/^(\*\*\*\*)/, workingY).replace(/^(\d\d\d\d)(\*\*)/, "$1"+workingM);

                // Single date
                if(dt2 == 1) {
                    if(+dt1 >= +o.firstDateShown && +dt1 <= +o.lastDateShown) {
                        obj[dt1] = o.dateList[rNumber].type;
                    };
                    continue;
                };

                // Date Range
                if(dt1 <= dt2
                   &&
                   workingDt >= dt1.substr(0,6)
                   &&
                   workingDt <= dt2.substr(0,6)
                   ) {
                    rngLower = Math.max(dt1, Math.max(String(workingDt) + "01", this.firstDateShown));
                    rngUpper = Math.min(dt2, Math.min(String(workingDt) + "31", this.lastDateShown));
                    for(i = rngLower; i <= rngUpper; i++) {
                        obj[i] = o.dateList[rNumber].type;
                    };
                };
            };

            // Let the Date Object take care of month overflowss
            workingDt = new Date(workingY, +workingM, 2);
            workingDt = workingDt.getFullYear()+""+pad(workingDt.getMonth()+1);
        };

        return obj;
    };

    // Repositions the datepicker beside the button - to the bottom by
    // preference but to the top if there is not enough room to display the
    // entire U.I. at the bottom (it really should be updated to favour
    // bottom positioning if not enough room to display the entire U.I. at
    // the top in that scenario though)
    this.reposition = function() {
        if(!o.created || o.staticPos) {
            return;
        };

        o.div.style.visibility = "hidden";
        o.div.style.left = o.div.style.top = "0px";
        o.div.style.display = "block";

        var osh         = o.div.offsetHeight,
            osw         = o.div.offsetWidth,
            elem        = document.getElementById('fd-but-' + o.id),
            pos         = o.truePosition(elem),
            trueBody    = (document.compatMode && document.compatMode!="BackCompat") ? document.documentElement : document.body,
            sOffsets    = o.getScrollOffsets(),
            scrollTop   = sOffsets[1],
            scrollLeft  = sOffsets[0],
            tSpace      = parseInt(pos[1] - 2) - parseInt(scrollTop),
            bSpace      = parseInt(trueBody.clientHeight + scrollTop) - parseInt(pos[1] + elem.offsetHeight + 2);

        o.div.style.visibility = "visible";

console.log("trueBody.clientWidth" + trueBody.clientWidth)
console.log(sOffsets)
o.div.style.left = Number(parseInt(trueBody.clientWidth+scrollLeft) < parseInt(osw+pos[0]) ? Math.abs(parseInt((trueBody.clientWidth+scrollLeft) - osw)) : pos[0]) + "px";
o.div.style.top = (bSpace > tSpace) ? Math.abs(parseInt(pos[1] + elem.offsetHeight + 2)) + "px" : Math.abs(parseInt(pos[1] - (osh + 2))) + "px";
if(oldIE === 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";
};
};

    this.removeCursorHighlight = function() {
        var td = document.getElementById(o.id + "-date-picker-hover");
        if(td) {
            removeClass(td, "date-picker-hover");
        };
    };

    this.addCursorHighlight = function() {
        var td = document.getElementById(o.id + "-date-picker-hover");
        if(td) {
            addClass(td, "date-picker-hover");
        };
    };
    // Resets the tabindex of the previously focused cell
    this.removeOldFocus = function() {
        var td = document.getElementById(o.id + "-date-picker-hover");
        if(td) {
            try {
                setTabIndex(td, -1);
                removeClass(td, "date-picker-hover");
                td.id = "";
                td.onblur  = null;
                td.onfocus = null;
            } catch(err) {};
        };
    };

    // Sets the tabindex & focus on the currently highlighted cell
    this.setNewFocus = function() {
        var td = document.getElementById(o.id + "-date-picker-hover");
        if(td) {
            try {
                setTabIndex(td, 0);
                if(this.showCursor) {
                    addClass(td, "date-picker-hover");
                };
                // If opened with the keyboard then add focus & blur events to the cell
                if(!this.clickActivated) {
                    td.onblur    = o.onblur;
                    td.onfocus   = o.onfocus;
                };

                // If opened with the keyboard (and not in opera) then add a screen-reader friendly date format
                if(!isOpera && !this.clickActivated) {
                    o.addAccessibleDate();
                };

                // Try to programmatically set focus on the cell
                if(!this.noFocus && !this.clickActivated) {
                    setTimeout(function() { try { td.focus(); } catch(err) {}; }, 0);
                };
            } catch(err) { };
        };
    };

    // Adds a screen-reader friendly date to the current cell whenever
    // the datepicker has been opened with the keyboard
    this.addAccessibleDate = function() {
        var td   = document.getElementById(o.id + "-date-picker-hover");

        if(td && !(td.getElementsByTagName("span").length)) {
            var ymd = td.className.match(/cd-([\d]{4})([\d]{2})([\d]{2})/),
                noS = td.className.search(noSelectionRegExp) != -1,
                spn = document.createElement('span'),
                spnC;

            spn.className       = "fd-screen-reader";

            removeChildNodes(td);

            if(noS) {
                spnC = spn.cloneNode(false);
                spnC.appendChild(document.createTextNode(getTitleTranslation(13)));
                td.appendChild(spnC);
            };

            for(var pt = 0, part; part = formatParts[pt]; pt++) {
                if(part == "%j" || part == "%d") {
                    td.appendChild(document.createTextNode(printFormattedDate(new Date(ymd[1], +ymd[2]-1, ymd[3], 5, 0, 0), part, true)));
                } else {
                    spnC = spn.cloneNode(false);
                    spnC.appendChild(document.createTextNode(printFormattedDate(new Date(ymd[1], +ymd[2]-1, ymd[3], 5, 0, 0), part, true)));
                    td.appendChild(spnC);
                };
            };
        };
    };

    // Sets the current cursor to a specific date
    this.setCursorDate = function(yyyymmdd) {
        if(String(yyyymmdd).search(/^([0-9]{8})$/) != -1) {
            this.date = new Date(+yyyymmdd.substr(0,4), +yyyymmdd.substr(4,2) - 1, +yyyymmdd.substr(6,2), 5, 0, 0);
            this.cursorDate = yyyymmdd;

            if(this.staticPos) {
                this.updateTable();
            };
        };
    };

    // Updates the table used to display the datepicker
    this.updateTable = function(noCallback) {
        if(!o || o.inUpdate || !o.created) {
            return;
        };

        // We are currently updating (used to stop public methods from firing)
        o.inUpdate = true;

        // Remove the focus from the currently highlighted cell
        o.removeOldFocus();

        o.div.dir = localeImport.rtl ? "rtl" : "ltr";

        // If the update timer initiated
        if(o.timerSet && !o.delayedUpdate) {
            // Are we incrementing/decrementing the month
            if(o.monthInc) {
                var n = o.date.getDate(),
                    d = new Date(o.date);

                d.setDate(2);
                d.setMonth(d.getMonth() + o.monthInc * 1);
                // Don't go over the days in the month
                d.setDate(Math.min(n, daysInMonth(d.getMonth(),d.getFullYear())));

                o.date = new Date(d);
            } else {
                o.date.setDate(Math.min(o.date.getDate()+o.dayInc, daysInMonth(o.date.getMonth()+o.monthInc,o.date.getFullYear()+o.yearInc)));
                o.date.setMonth(o.date.getMonth() + o.monthInc);
                o.date.setFullYear(o.date.getFullYear() + o.yearInc);
            };
        };

        // Make sure the internal date is within range
        o.outOfRange();

        // Disable/enable the today button
        if(!o.noToday) {
            o.disableTodayButton();
        };

        // Disable/enable the month & year buttons
        o.showHideButtons(o.date);

        var cd = o.date.getDate(),
            cm = o.date.getMonth(),
            cy = o.date.getFullYear(),
            cursorDate = (String(cy) + pad(cm+1) + pad(cd)),
            tmpDate    = new Date(cy, cm, 1, 5, 0, 0);

        tmpDate.setHours(5);

        var dt, dts, cName, row, td, i, currentDate, cellAdded, col, currentStub, abbr, bespokeRenderClass, spnC, dateSetD, selectable, weekDay,
            // Weekday of the fist of the month
            weekDayC            = (tmpDate.getDay() + 6) % 7,
            // The column index this weekday will occupy
            firstColIndex       = (((weekDayC - o.firstDayOfWeek) + 7 ) % 7) - 1,
            // The number of days in the current month
            dpm                 = daysInMonth(cm, cy),
            // Today as a Date Object
            today               = new Date(),
            // Today as a YYYYMMDD String
            today               = today.getFullYear() + pad(today.getMonth()+1) + pad(today.getDate()),
            // A Sring date stub in a YYYYMM format for the current date
            stub                = String(tmpDate.getFullYear()) + pad(tmpDate.getMonth()+1),
            //
            cellAdded           = [4,4,4,4,4,4],
            // The first day of the previous month as a Date Object
            lm                  = new Date(cy, cm-1, 1, 5, 0, 0),
            // The first day of the next month as a Date Object
            nm                  = new Date(cy, cm+1, 1, 5, 0, 0),
            // The number of days in the previous month
            daySub              = daysInMonth(lm.getMonth(), lm.getFullYear()),
            // YYYYMM String date stub for the next month
            stubN               = String(nm.getFullYear()) + pad(nm.getMonth()+1),
            // YYYYMM String date stub for the previous month
            stubP               = String(lm.getFullYear()) + pad(lm.getMonth()+1),
            weekDayN            = (nm.getDay() + 6) % 7,
            weekDayP            = (lm.getDay() + 6) % 7,
            // A SPAN node to clone when adding dates to individual cells
            spn                 = document.createElement('span');

        // Give the "fd-screen-reader" class to the span in order to hide them in the UI
        // but keep them accessible to screen-readers
        spn.className       = "fd-screen-reader";

        // The first & last dates shown on the datepicker UI - could be a date from the previous & next month respectively
        o.firstDateShown    = !o.constrainSelection && o.fillGrid && (0 - firstColIndex < 1) ? String(stubP) + (daySub + (0 - firstColIndex)) : stub + "01";
        o.lastDateShown     = !o.constrainSelection && o.fillGrid ? stubN + pad(41 - firstColIndex - dpm) : stub + String(dpm);

        // Store a reference to the current YYYYMM String representation of the current month
        o.currentYYYYMM     = stub;

        bespokeRenderClass  = o.callback("redraw", {id:o.id, dd:pad(cd), mm:pad(cm+1), yyyy:cy, firstDateDisplayed:o.firstDateShown, lastDateDisplayed:o.lastDateShown}) || {};

        // An Object of dates that have been explicitly disabled (1) or enabled (0)
        dts                 = o.getDateExceptions(cy, cm+1);

        // Double check current date within limits etc
        o.checkSelectedDate();
        //
        dateSetD            = (o.dateSet != null) ? o.dateSet.getFullYear() + pad(o.dateSet.getMonth()+1) + pad(o.dateSet.getDate()) : false;

        // If we have selected a date then set its ARIA selected property
        // to false. We then set the ARIA selected property to true on the
        // newly selected cell after redrawing the table
        if(this.selectedTD != null) {
            setARIAProperty(this.selectedTD, "selected", false);
            this.selectedTD = null;
        };

        // Redraw all of the table cells representing the date parts of the UI
        for(var curr = 0; curr < 42; curr++) {
            // Current row
            row  = Math.floor(curr / 7);
            // Current TD node
            td   = o.tds[curr];
            // Clone our SPAN node
            spnC = spn.cloneNode(false);
            // Remove any previous contents from the cell
            removeChildNodes(td);

            // If the current cell contains a date
            if((curr > firstColIndex && curr <= (firstColIndex + dpm)) || o.fillGrid) {
                currentStub     = stub;
                weekDay         = weekDayC;
                dt              = curr - firstColIndex;
                cName           = [];
                selectable      = true;

                // Are we drawing last month
                if(dt < 1) {
                    dt              = daySub + dt;
                    currentStub     = stubP;
                    weekDay         = weekDayP;
                    selectable      = !o.constrainSelection;
                    cName.push("month-out");
                // Are we drawing next month
                } else if(dt > dpm) {
                    dt -= dpm;
                    currentStub     = stubN;
                    weekDay         = weekDayN;
                    selectable      = !o.constrainSelection;
                    cName.push("month-out");
                };

                // Calcuate this cells weekday
                weekDay = (weekDay + dt + 6) % 7;

                // Push a classname representing the weekday e.g. "day-3"
                cName.push("day-" + weekDay + " cell-" + curr);

                // A YYYYMMDD String representation of this cells date
                currentDate = currentStub + String(dt < 10 ? "0" : "") + dt;

                // If this cells date is out of range
                if(o.rangeLow && +currentDate < +o.rangeLow || o.rangeHigh && +currentDate > +o.rangeHigh) {
                    // Add a classname to style the cell and stop selection
                    td.className = "out-of-range";
                    // Reset this TD nodes title attribute
                    td.title = "";
                    // Append the cells date as a text node to the TD
                    td.appendChild(document.createTextNode(dt));
                    // Jaysus, what the feck does this line do again...
                    if(o.showWeeks) {
                        cellAdded[row] = Math.min(cellAdded[row], 2);
                    };
                // This cells date is within the lower & upper ranges (or no ranges have been defined)
                } else {
                    // If it's a date from last or next month and the "constrainSelection" option
                    // is false then give the cell a CD-YYYYMMDD class
                    if(selectable) {
                        td.title = titleFormat ? printFormattedDate(new Date(+String(currentStub).substr(0,4), +String(currentStub).substr(4, 2) - 1, +dt, 5, 0, 0), titleFormat, true) : "";
                        cName.push("cd-" + currentDate + " yyyymmdd-" + currentDate + " yyyymm-" + currentStub + " mmdd-" + currentStub.substr(4,2) + pad(dt));
                    // Otherwise give a "not-selectable" class (which shouldn't be styled in any way, it's for internal use)
                    } else {
                        td.title = titleFormat ? getTitleTranslation(13) + " " + printFormattedDate(new Date(+String(currentStub).substr(0,4), +String(currentStub).substr(4, 2) - 1, +dt, 5, 0, 0), titleFormat, true) : "";
                        cName.push("yyyymmdd-" + currentDate + " yyyymm-" + currentStub + " mmdd-" + currentStub.substr(4,2) + pad(dt) + " not-selectable");
                    };

                    // Add a classname if the current cells date is today
                    if(currentDate == today) {
                        cName.push("date-picker-today");
                    };

                    // If this cell represents the currently selected date
                    if(dateSetD == currentDate) {
                        // Add a classname (for styling purposes)
                        cName.push("date-picker-selected-date");
                        // Set the ARIA selected property to true
                        setARIAProperty(td, "selected", "true");
                        // And cache a reference to the current cell
                        this.selectedTD = td;
                    };

                    // If the current cell has been explicitly disabled
                    if(((currentDate in dts) && dts[currentDate] == 1)
                       // or
                       ||
                       // ... the current weekday has been disabled
                       (o.disabledDays[weekDay]
                        &&
                       // ... and the current date has not been explicitly enabled
                       !((currentDate in dts) && dts[currentDate] == 0)
                       )
                      ) {
                        // Add a classname to style the cell and stop selection
                        cName.push("day-disabled");
                        // Update the current cells title to say "Disabled date: ..." (or whatever the translation says)
                        if(titleFormat && selectable) {
                            td.title = getTitleTranslation(13) + " " + td.title;
                        };
                    };

                    // Has the redraw callback given us a bespoke classname to add to this cell
                    if(currentDate in bespokeRenderClass) {
                        cName.push(bespokeRenderClass[currentDate]);
                    };

                    // Do we need to highlight this cells weekday representation
                    if(o.highlightDays[weekDay]) {
                        cName.push("date-picker-highlight");
                    };

                    // Is the current onscreen cursor set to this cells date
                    if(cursorDate == currentDate) {
                        td.id = o.id + "-date-picker-hover";
                    };

                    // Add the date to the TD cell as a text node. Note: If the datepicker has been given keyboard
                    // events, this textnode is replaced by a more screen-reader friendly date during the focus event
                    td.appendChild(document.createTextNode(dt));

                    // Add the classnames to the TD node
                    td.className = cName.join(" ");

                    // If the UI displays week numbers then update the celladded
                    if(o.showWeeks) {
                        cellAdded[row] = Math.min(cName[0] == "month-out" ? 3 : 1, cellAdded[row]);
                    };
                };
            // The current TD node is empty i.e. represents no date in the UI
            } else {
                // Add a classname to style the cell
                td.className = "date-picker-unused";
                // Add a non-breaking space to unused TD node (for IEs benefit mostly)
                td.appendChild(document.createTextNode(nbsp));
                // Reset the TD nodes title attribute
                td.title = "";
            };
            // Do we update the week number for this row
            if(o.showWeeks && curr - (row * 7) == 6) {
                removeChildNodes(o.wkThs[row]);
                o.wkThs[row].appendChild(document.createTextNode(cellAdded[row] == 4 && !o.fillGrid ? nbsp : getWeekNumber(cy, cm, curr - firstColIndex - 6)));
                o.wkThs[row].className = "date-picker-week-header" + (["",""," out-of-range"," month-out",""][cellAdded[row]]);
            };
        };

        // Update the UI title bar displaying the year & month
        var span = o.titleBar.getElementsByTagName("span");
        removeChildNodes(span[0]);
        removeChildNodes(span[1]);
        span[0].appendChild(document.createTextNode(getMonthTranslation(cm, false) + nbsp));
        span[1].appendChild(document.createTextNode(cy));

        // If we are in an animation
        if(o.timerSet) {
            // Speed the timer up a little bit to make the pause between updates quicker
            o.timerInc = 50 + Math.round(((o.timerInc - 50) / 1.8));
            // Recall this function in a timeout
            o.timer = window.setTimeout(o.updateTable, o.timerInc);
        };

        // We are not currently updating the UI
        o.inUpdate = o.delayedUpdate = false;
        // Focus on the correct TD node
        o.setNewFocus();
    };

    // Removes all scaffold from the DOM & events from memory
    this.destroy = function() {

        // Remove the button if it exists
        if(document.getElementById("fd-but-" + this.id)) {
            document.getElementById("fd-but-" + this.id).parentNode.removeChild(document.getElementById("fd-but-" + this.id));
        };

        if(!this.created) {
            return;
        };

        // Event cleanup for Internet Explorers benefit
        removeEvent(this.table, "mousedown", o.onmousedown);
        removeEvent(this.table, "mouseover", o.onmouseover);
        removeEvent(this.table, "mouseout", o.onmouseout);
        removeEvent(document, "mousedown", o.onmousedown);
        removeEvent(document, "mouseup",   o.clearTimer);

        if (window.addEventListener && !window.devicePixelRatio) {
            try {
                window.removeEventListener('DOMMouseScroll', this.onmousewheel, false);
            } catch(err) {};
        } else {
            removeEvent(document, "mousewheel", this.onmousewheel);
            removeEvent(window,   "mousewheel", this.onmousewheel);
        };
        o.removeOnFocusEvents();
        clearTimeout(o.fadeTimer);
        clearTimeout(o.timer);

        if(oldIE === 6 && !o.staticPos) {
            try {
                o.iePopUp.parentNode.removeChild(o.iePopUp);
                o.iePopUp = null;
            } catch(err) {};
        };

        if(this.div && this.div.parentNode) {
            this.div.parentNode.removeChild(this.div);
        };

        o = null;
    };

    this.resizeInlineDiv = function()  {
        o.div.style.width = o.table.offsetWidth + "px";
        o.div.style.height = o.table.offsetHeight + "px";
    };

    this.reset = function() {
        var elemID, elem;
        for(elemID in o.formElements) {
            elem = document.getElementById(elemID);
            if(elem) {
                if(elem.tagName.toLowerCase() == "select") {
                    elem.selectedIndex = o.formElements[elemID.defaultVal];
                } else {
                    elem.value = o.formElements[elemID.defaultVal];
                };
            };
        };
        o.changeHandler();
    };

    // Creates the DOM scaffold
    this.create = function() {

        if(document.getElementById("fd-" + this.id)) {
            return;
        };

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

        this.noFocus = true;

        function createTH(details) {
            var th = document.createElement('th');
            if(details.thClassName) {
                th.className = details.thClassName;
            };
            if(details.colspan) {
                th.setAttribute(oldIE ? 'colSpan' : "colspan", details.colspan);
            };
            th.unselectable = "on";
            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 || "";
                but.unselectable = "on";
                th.appendChild(but);
            };
        };

        this.div                     = document.createElement('div');
        this.div.id                  = "fd-" + this.id;
        this.div.className           = "date-picker" + (cssAnimations ? " fd-dp-fade " : "") + this.bespokeClass;

        // Attempt to hide the div from screen readers during content creation
        this.div.style.visibility = "hidden";
        this.div.style.display = "none";

        // Set the ARIA describedby property if the required block available
        if(this.describedBy && document.getElementById(this.describedBy)) {
            setARIAProperty(this.div, "describedby", this.describedBy);
        };

        // Set the ARIA labelled property if the required label available
        if(this.labelledBy) {
            setARIAProperty(this.div, "labelledby", this.labelledBy.id);
        };

        this.idiv                     = document.createElement('div');

        this.table             = document.createElement('table');
        this.table.className   = "date-picker-table";
        this.table.onmouseover = this.onmouseover;
        this.table.onmouseout  = this.onmouseout;
        this.table.onclick     = this.onclick;

        if(this.finalOpacity < 100) {
            this.idiv.style.opacity = Math.min(Math.max(parseInt(this.finalOpacity, 10) / 100, .2), 1);
        };

        if(this.staticPos) {
            this.table.onmousedown  = this.onmousedown;
        };

        this.div.appendChild(this.idiv);
        this.idiv.appendChild(this.table);

        var dragEnabledCN = !this.dragDisabled ? " drag-enabled" : "";

        if(!this.staticPos) {
            this.div.style.visibility = "hidden";
            this.div.className += dragEnabledCN;
            document.getElementsByTagName('body')[0].appendChild(this.div);

            if(oldIE === 6) {
                this.iePopUp = document.createElement('iframe');
                this.iePopUp.src = "javascript:'<html></html>';";
                this.iePopUp.setAttribute('className','iehack');
                // Remove iFrame from tabIndex
                this.iePopUp.setAttribute("tabIndex", -1);
                // Hide it from ARIA aware technologies
                setARIARole(this.iePopUp, "presentation");
                setARIAProperty(this.iePopUp, "hidden", "true");
                this.iePopUp.scrolling = "no";
                this.iePopUp.frameBorder = "0";
                this.iePopUp.name = this.iePopUp.id = this.id + "-iePopUpHack";
                document.body.appendChild(this.iePopUp);
            };

            // Aria "hidden" property for non active popup datepickers
            setARIAProperty(this.div, "hidden", "true");
        } else {
            var elem = document.getElementById(this.positioned ? this.positioned : this.id);
            if(!elem) {
                this.div = null;
                if(debug) {
                    throw this.positioned ? "Could not locate a datePickers associated parent element with an id:" + this.positioned : "Could not locate a datePickers associated input with an id:" + this.id;
                };
                return;
            };

            this.div.className += " static-datepicker";

            if(this.positioned) {
                elem.appendChild(this.div);
            } else {
                elem.parentNode.insertBefore(this.div, elem.nextSibling);
            };

            if(this.hideInput) {
                for(var elemID in this.formElements) {
                    elem = document.getElementById(elemID);
                    if(elem) {
                        elem.className += " fd-hidden-input";
                    };
                };
            };

            setTimeout(this.resizeInlineDiv, 300);
        };
        // ARIA Application role
        setARIARole(this.div, "application");
        setARIARole(this.table, "grid");

        if(this.statusFormat) {
            tableFoot = document.createElement('tfoot');
            this.table.appendChild(tableFoot);
            tr = document.createElement('tr');
            tr.className = "date-picker-tfoot";
            tableFoot.appendChild(tr);
            this.statusBar = createTH({thClassName:"date-picker-statusbar" + dragEnabledCN, colspan:this.showWeeks ? 8 : 7});
            tr.appendChild(this.statusBar);
            this.updateStatus();
        };

        tableHead = document.createElement('thead');
        tableHead.className = "date-picker-thead";
        this.table.appendChild(tableHead);

        tr  = document.createElement('tr');
        setARIARole(tr, "presentation");

        tableHead.appendChild(tr);

        // Title Bar
        this.titleBar = createTH({thClassName:"date-picker-title" + dragEnabledCN, colspan:this.showWeeks ? 8 : 7});

        tr.appendChild(this.titleBar);
        tr = null;

        var span = document.createElement('span');
        span.appendChild(document.createTextNode(nbsp));
        span.className = "month-display" + dragEnabledCN;
        this.titleBar.appendChild(span);

        span = document.createElement('span');
        span.appendChild(document.createTextNode(nbsp));
        span.className = "year-display" + dragEnabledCN;
        this.titleBar.appendChild(span);

        span = null;

        tr  = document.createElement('tr');
        setARIARole(tr, "presentation");
        tableHead.appendChild(tr);

        createThAndButton(tr, [
        {className:"prev-but prev-year",  id:"-prev-year-but", text:"\u00AB", title:getTitleTranslation(2) },
        {className:"prev-but prev-month", id:"-prev-month-but", text:"\u2039", title:getTitleTranslation(0) },
        {colspan:this.showWeeks ? 4 : 3, className:"today-but", id:"-today-but", text:getTitleTranslation(4)},
        {className:"next-but next-month", id:"-next-month-but", text:"\u203A", title:getTitleTranslation(1)},
        {className:"next-but next-year",  id:"-next-year-but", text:"\u00BB", title:getTitleTranslation(3) }
        ]);

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

        var colspanTotal = this.showWeeks ? 8 : 7,
            colOffset    = this.showWeeks ? 0 : -1,
            but, abbr, formElemId, formElem;

        for(var rows = 0; rows < 7; rows++) {
            row = document.createElement('tr');

            if(rows != 0) {
                // ARIA Grid role
                setARIARole(row, "row");
                tableBody.appendChild(row);
            } else {
                tableHead.appendChild(row);
            };

            for(var cols = 0; cols < colspanTotal; cols++) {
                if(rows === 0 || (this.showWeeks && cols === 0)) {
                    col = document.createElement('th');
                } else {
                    col = document.createElement('td');
                    setARIAProperty(col, "describedby", this.id + "-col-" + cols + (this.showWeeks ? " " + this.id + "-row-" + rows : ""));
                    setARIAProperty(col, "selected", "false");
                };

                if(oldIE) {
                    col.unselectable = "on";
                };

                row.appendChild(col);
                if((this.showWeeks && cols > 0 && rows > 0) || (!this.showWeeks && rows > 0)) {
                    setARIARole(col, "gridcell");
                } else {
                    if(rows === 0 && cols > colOffset) {
                        col.className = "date-picker-day-header";
                        col.scope = "col";
                        setARIARole(col, "columnheader");
                        col.id = this.id + "-col-" + cols;
                    } else {
                        col.className = "date-picker-week-header";
                        col.scope = "row";
                        setARIARole(col, "rowheader");
                        col.id = this.id + "-row-" + rows;
                    };
                };
            };
        };

        col = row = null;

        this.ths = this.table.getElementsByTagName('thead')[0].getElementsByTagName('tr')[2].getElementsByTagName('th');

        for (var y = 0; y < colspanTotal; y++) {

            if(y == 0 && this.showWeeks) {
                this.ths[y].appendChild(document.createTextNode(getTitleTranslation(6)));
                this.ths[y].title = getTitleTranslation(8);
                continue;
            };

            if(y > (this.showWeeks ? 0 : -1)) {
                but = document.createElement("span");
                but.className = "fd-day-header";
                if(oldIE) {
                    but.unselectable = "on";
                };
                this.ths[y].appendChild(but);
            };
        };

        but = null;

        this.trs             = this.table.getElementsByTagName('tbody')[0].getElementsByTagName('tr');
        this.tds             = this.table.getElementsByTagName('tbody')[0].getElementsByTagName('td');
        this.butPrevYear     = document.getElementById(this.id + "-prev-year-but");
        this.butPrevMonth    = document.getElementById(this.id + "-prev-month-but");
        this.butToday        = document.getElementById(this.id + "-today-but");
        this.butNextYear     = document.getElementById(this.id + "-next-year-but");
        this.butNextMonth    = document.getElementById(this.id + "-next-month-but");

        if(this.noToday) {
            this.butToday.style.display = "none";
        };

        if(this.showWeeks) {
            this.wkThs = this.table.getElementsByTagName('tbody')[0].getElementsByTagName('th');
            this.div.className += " weeks-displayed";
        };

        tableBody = tableHead = tr = createThAndButton = createTH = null;

        this.updateTableHeaders();
        this.created = true;
        this.updateTable();

        if(this.staticPos) {
            this.visible = true;
            this.opacity = 100;
            this.div.style.visibility = "visible";
            this.div.style.display = "block";
            this.noFocus = true;
            this.fade();
        } else {
            this.reposition();
            this.div.style.visibility = "visible";
            this.fade();
            this.noFocus = true;
        };

        this.callback("domcreate", { "id":this.id });
    };

    this.transEnd = function() {
        o.div.style.display     = "none";
        o.div.style.visibility  = "hidden";
        setARIAProperty(o.div, "hidden", "true");
    };

    this.fade = function() {
        window.clearTimeout(o.fadeTimer);
        o.fadeTimer = null;
        if(cssAnimations) {
            o.opacity = o.opacityTo;
            if(o.opacityTo == 0) {
                o.visible = false;
                addEvent(o.div, transitionEnd, o.transEnd);
                addClass(o.div, "fd-dp-fade");
            } else {
                removeEvent(o.div, transitionEnd, o.transEnd);
                o.visible               = true;
                o.div.style.display     = "block";
                o.div.style.visibility  = "visible";
                setARIAProperty(o.div, "hidden", "false");
                removeClass(o.div, "fd-dp-fade");
            };
            return;
        };

        var diff = Math.round(o.opacity + ((o.opacityTo - o.opacity) / 4));
        o.setOpacity(diff);
        if(Math.abs(o.opacityTo - diff) > 3 && !o.noFadeEffect) {
            o.fadeTimer = window.setTimeout(o.fade, 50);
        } else {
            o.setOpacity(o.opacityTo);
            if(o.opacityTo == 0) {
                o.div.style.display    = "none";
                o.div.style.visibility = "hidden";
                setARIAProperty(o.div, "hidden", "true");
                o.visible = false;
            } else {
                setARIAProperty(o.div, "hidden", "false");
                o.visible = true;
            };
        };
    };
    this.trackDrag = function(e) {
        e = e || window.event;
        var diffx = (e.pageX?e.pageX:e.clientX?e.clientX:e.x) - o.mx;
        var diffy = (e.pageY?e.pageY:e.clientY?e.clientY:e.Y) - o.my;
        o.div.style.left = Math.round(o.x + diffx) > 0 ? Math.round(o.x + diffx) + 'px' : "0px";
        o.div.style.top  = Math.round(o.y + diffy) > 0 ? Math.round(o.y + diffy) + 'px' : "0px";
        if(oldIE === 6 && !o.staticPos) {
            o.iePopUp.style.top    = o.div.style.top;
            o.iePopUp.style.left   = o.div.style.left;
        };
    };
    this.stopDrag = function(e) {
        var b = document.getElementsByTagName("body")[0];
        removeClass(b, "fd-drag-active");
        removeEvent(document,'mousemove',o.trackDrag, false);
        removeEvent(document,'mouseup',o.stopDrag, false);
        o.div.style.zIndex = 9999;
    };
    this.onmousedown = function(e) {
        e = e || document.parentWindow.event;
        var el     = e.target != null ? e.target : e.srcElement,
            origEl = el,
            hideDP = true,
            reg    = new RegExp("^fd-(but-)?" + o.id + "$");

        o.mouseDownElem = null;

        // Are we within the wrapper div or the button
        while(el) {
            if(el.id && el.id.length && el.id.search(reg) != -1) {
                hideDP = false;
                break;
            };
            try {
                el = el.parentNode;
            } catch(err) {
                break;
            };
        };

        // If not, then ...
        if(hideDP) {
            hideAll();
            return true;
        };

        if((o.div.className + origEl.className).search('fd-disabled') != -1) {
            return true;
        };

        // We check the mousedown events on the buttons
        if(origEl.id.search(new RegExp("^" + o.id + "(-prev-year-but|-prev-month-but|-next-month-but|-next-year-but)$")) != -1) {

            o.mouseDownElem = origEl;

            addEvent(document, "mouseup", o.clearTimer);
            addEvent(origEl, "mouseout",  o.clearTimer);

            var incs = {
                    "-prev-year-but":[0,-1,0],
                    "-prev-month-but":[0,0,-1],
                    "-next-year-but":[0,1,0],
                    "-next-month-but":[0,0,1]
                },
                check = origEl.id.replace(o.id, ""),
                dateYYYYMM = Number(o.date.getFullYear() + pad(o.date.getMonth()+1));

            o.timerInc      = 800;
            o.timerSet 

@hmuus
Copy link

@hmuus hmuus commented on 0c2d1ef Mar 13, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

noFadeEffect not working if css support
possibly some where here ?

    this.fade = function() {
        window.clearTimeout(o.fadeTimer);
        o.fadeTimer = null;
        if(cssAnimations) {
            o.opacity = o.opacityTo;
            if(o.opacityTo == 0) {
                o.visible = false;
                addEvent(o.div, transitionEnd, o.transEnd);
                addClass(o.div, "fd-dp-fade");
            } else {
                removeEvent(o.div, transitionEnd, o.transEnd);
                o.visible               = true;
                o.div.style.display     = "block";
                o.div.style.visibility  = "visible";
                setARIAProperty(o.div, "hidden", "false");
                removeClass(o.div, "fd-dp-fade");
            };
            return;
        };

        var diff = Math.round(o.opacity + ((o.opacityTo - o.opacity) / 4));
        o.setOpacity(diff);
        if(Math.abs(o.opacityTo - diff) > 3 && !o.noFadeEffect) {
            o.fadeTimer = window.setTimeout(o.fade, 50);
        } else {
            o.setOpacity(o.opacityTo);
            if(o.opacityTo == 0) {
                o.div.style.display    = "none";
                o.div.style.visibility = "hidden";
                setARIAProperty(o.div, "hidden", "true");
                o.visible = false;
            } else {
                setARIAProperty(o.div, "hidden", "false");
                o.visible = true;
            };
        };
    };

Please sign in to comment.