user-friendlier date chosing in events
authorThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Mon, 9 Feb 2009 17:57:16 +0000 (17:57 +0000)
committerThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Mon, 9 Feb 2009 17:57:16 +0000 (17:57 +0000)
planetlab/datepicker/URL [new file with mode: 0644]
planetlab/datepicker/datepicker.css [new file with mode: 0644]
planetlab/datepicker/datepicker.js [new file with mode: 0644]
planetlab/events/index.php
planetlab/includes/plc_datepicker.php [new file with mode: 0644]
planetlab/includes/plc_objects.php
planetlab/includes/plc_tables.php
planetlab/tablesort/URL [new file with mode: 0644]

diff --git a/planetlab/datepicker/URL b/planetlab/datepicker/URL
new file mode 100644 (file)
index 0000000..6a63884
--- /dev/null
@@ -0,0 +1 @@
+http://www.frequency-decoder.com/
diff --git a/planetlab/datepicker/datepicker.css b/planetlab/datepicker/datepicker.css
new file mode 100644 (file)
index 0000000..c3d0f0b
--- /dev/null
@@ -0,0 +1,438 @@
+/* This is a very basic stylesheet for the date-picker. Feel free to create your own. */\r
+\r
+/* The wrapper div */\r
+div.datePicker\r
+        {\r
+        position:absolute;        \r
+        z-index:9999;\r
+        text-align:center;\r
+\r
+        /* Change the font-size to suit your design's CSS. The following line is for the demo that has a 12px font-size defined on the body tag */\r
+        font:900 0.8em/1em Verdana, Sans-Serif;\r
+\r
+        /* For Example: If using the YUI font CSS, uncomment the following line to get a 10px font-size within the datePicker */\r
+        /* font:900 77%/77% Verdana, sans-serif; */\r
+        \r
+        /* Or, if you prefer a pixel precision */\r
+        /* font:900 12px/12px Verdana, sans-serif; */\r
+        \r
+        background:transparent;\r
+\r
+        /* Mozilla & Webkit extensions to stop text-selection. Remove if you wish to validate the CSS */\r
+        -moz-user-select:none;\r
+        -khtml-user-select:none;                 \r
+        }    \r
+/* You can add focus effects (for everything but IE6) like so: */\r
+div.datePicker:focus\r
+        {\r
+        /* Naughty, naughty - but we add a highlight using the table's border colour */\r
+        outline:none;\r
+        }\r
+div.datePicker:focus table\r
+        {\r
+        border-color:#aaa;\r
+        }\r
+/* Make the wrapper div larger if weeks are to be displayed */\r
+div.weeks-displayed\r
+        {\r
+        /* min-width:28em; \r
+        width:28em; */\r
+        }\r
+/* Styles for the static datePickers */\r
+div.static-datepicker\r
+        {\r
+        position:relative;        \r
+        top:5px;\r
+        left:0;\r
+        }\r
+div.datePicker table\r
+        {\r
+        width:auto;\r
+        height:auto;\r
+        }\r
+/* Draggable datepickers */\r
+div.datePicker tfoot th.drag-enabled,\r
+div.datePicker thead th.drag-enabled,\r
+div.datePicker thead th.drag-enabled span\r
+        {\r
+        cursor:move;\r
+        }\r
+/* The iframe hack to cover selectlists in Internet Explorer <= v6 */\r
+iframe.iehack\r
+        {\r
+        position:absolute;\r
+        background:#fff;\r
+        z-index:9998;\r
+        padding:0;\r
+        border:0;\r
+        display:none;\r
+        margin:0;\r
+        }\r
+/* The "button" created beside each input for non-static datePickers */\r
+a.date-picker-control:link,\r
+a.date-picker-control:visited\r
+        {\r
+        position:relative;\r
+        /* Moz & FF */\r
+        display: -moz-inline-stack;\r
+        border:0 none;\r
+        padding:0;\r
+        margin:0 0 0 4px;\r
+        background:transparent url(../media/cal-grey.gif) no-repeat 50% 50%;\r
+        min-width:16px;\r
+        line-height:1;\r
+        cursor:pointer;\r
+        visibility:visible;\r
+        text-decoration:none;\r
+        vertical-align:top;\r
+        }\r
+a.date-picker-control:hover,\r
+a.date-picker-control:active,\r
+a.date-picker-control:focus,\r
+a.dp-button-active:link,\r
+a.dp-button-active:visited,\r
+a.dp-button-active:hover,\r
+a.dp-button-active:active,\r
+a.dp-button-active:focus\r
+        {\r
+        background:transparent url(../media/cal.gif) no-repeat 50% 50% !important;\r
+        }\r
+/* Feed IE6 the following rule, IE7 should handle the min-width declared above */\r
+* html a.date-picker-control\r
+        {\r
+        width:16px;\r
+        }\r
+/* IE, Safari & Opera. Seperate CSS rule seems to be required. */\r
+a.date-picker-control\r
+        {\r
+        display:inline-block;\r
+        }\r
+a.date-picker-control span\r
+        {\r
+        display:block;\r
+        width:16px;\r
+        height:16px;\r
+        margin:auto 0;\r
+        }\r
+/* Default "button" styles */\r
+div.datePicker thead th span\r
+        {\r
+        display:block;\r
+        padding:0;\r
+        margin:0;\r
+        text-align:center;\r
+        line-height:1em;\r
+        border:0 none;\r
+        background:transparent;\r
+        font-weight:bold;\r
+        cursor:pointer;\r
+        }\r
+/* The "month, year" display */\r
+div.datePicker th span.month-display,\r
+div.datePicker th span.year-display\r
+        {\r
+        display:inline;\r
+        text-transform:uppercase;\r
+        letter-spacing:1px;\r
+        font:normal 1.2em Verdana, Sans-Serif;\r
+        cursor:default;          \r
+        }\r
+/* Next & Previous (month, year) buttons */\r
+div.datePicker th span.prev-but,\r
+div.datePicker th span.next-but\r
+        {\r
+        font-weight:lighter;\r
+        font-size:2.4em;\r
+        font-family: georgia, times new roman, palatino, times, bookman, serif;\r
+        cursor:pointer !important;\r
+        }\r
+/* Hover effect for Next & Previous (month, year) buttons */\r
+div.datePicker th span.prev-but:hover,\r
+div.datePicker th span.next-but:hover,\r
+div.datePicker th span.today-but:hover\r
+        {\r
+        color:#a84444;\r
+        }\r
+/* Today button */\r
+div.datePicker th span.today-but\r
+        {\r
+        text-align:center;\r
+        margin:0 auto;\r
+        font:normal 1em Verdana, Sans-Serif;\r
+        width:100%;\r
+        text-decoration:none;\r
+        padding-top:0.3em;\r
+        text-transform:uppercase;\r
+        vertical-align:middle;\r
+        cursor:pointer !important          \r
+        }\r
+/* Disabled Today button - IE6 will not see this rule as it should */\r
+div.datePicker th span.today-but.fd-disabled\r
+        {\r
+        display:none;\r
+        }\r
+/* Disabled buttons */\r
+div.datePicker th span.prev-but.fd-disabled:hover,\r
+div.datePicker th span.next-but.fd-disabled:hover,\r
+div.datePicker thead th span.fd-disabled\r
+        {\r
+        color:#aaa;\r
+        cursor:default !important; \r
+        display:block; /* required to get IE6 to play ball */\r
+        }\r
+\r
+/* The mon, tue, wed etc day buttons */\r
+div.datePicker th span.fd-day-header\r
+        {\r
+        text-align:center;\r
+        margin:0 auto;\r
+        font:900 1em Verdana, Sans-Serif;\r
+        text-decoration:none;\r
+        text-transform:lowercase;\r
+        cursor:pointer;          \r
+        }\r
+/* The table */\r
+div.datePicker table\r
+        {               \r
+        margin:0;\r
+        padding:0px;\r
+        border:1px solid #ccc;        \r
+        background:#fff url(../media/gradient-e5e5e5-ffffff.gif) repeat-x 0 -20px;\r
+        text-align:center;\r
+        border-spacing:2px;\r
+        padding:0.3em; \r
+        width:auto;             \r
+        empty-cells:show;               \r
+        -moz-border-radius:0.8em;        \r
+        }\r
+/* Common TD & TH styling */\r
+div.datePicker table td,\r
+div.datePicker table tbody th\r
+        {                 \r
+        border:0 none;\r
+        padding:0;\r
+        text-align:center;\r
+        vertical-align:middle;               \r
+        cursor:pointer;\r
+        background:#fff url(../media/gradient-e5e5e5-ffffff.gif) repeat-x 0 -40px;\r
+        width:3em;\r
+        height:3em;         \r
+        outline:none;        \r
+        border:1px solid #ccc;\r
+        text-transform:none;\r
+        -moz-border-radius:2px;\r
+        -webkit-border-radius:2px;\r
+        border-radius:2px;\r
+        }\r
+div.datePicker table th\r
+        {\r
+        border:0 none;\r
+        padding:0;        \r
+        font-weight:bold;\r
+        color:#222;\r
+        text-align:center;\r
+        vertical-align:middle; \r
+        text-transform:none;        \r
+        }\r
+div.datePicker table thead th\r
+        {\r
+        height:auto !important;\r
+        }\r
+div.datePicker table tbody th\r
+        {                          \r
+        border:1px solid #dcdcdc;        \r
+        }\r
+/* Week number display */\r
+div.datePicker table thead th.date-picker-week-header,\r
+div.datePicker table tbody th.date-picker-week-header\r
+        {\r
+        font-style:oblique;  \r
+        background:transparent;\r
+        cursor:default;         \r
+        }\r
+div.datePicker table thead th.date-picker-week-header\r
+        {\r
+        cursor:help;\r
+        border:0 none;\r
+        padding:0 0 0.2em 0;\r
+        }\r
+/* tfoot status bar */\r
+div.datePicker tfoot th\r
+        {\r
+        cursor:default;\r
+        font-weight:normal;\r
+        text-transform:uppercase;\r
+        letter-spacing:0.1em;\r
+        border:0 none;\r
+        background:transparent;\r
+        height:2.8em;\r
+        }\r
+/* TD cell that is _not_ used to display a day of the month */\r
+div.datePicker table tbody td.date-picker-unused\r
+        {\r
+        background:#fff url(../media/backstripes.gif);\r
+        border-color:#dcdcdc;          \r
+        cursor:default !important;\r
+        }\r
+\r
+/* The TH cell used to display the "month, year" title */\r
+div.datePicker table thead th.date-picker-title\r
+        {\r
+        width:auto;\r
+        height:auto;\r
+        padding:0.4em 0;\r
+        }\r
+/* The "mon tue wed etc" day header styles */\r
+div.datePicker table thead th.date-picker-day-header\r
+        {\r
+        text-transform:lowercase;\r
+        cursor:help;\r
+        height:auto;\r
+        }\r
+/* The "todays date" style */\r
+div.datePicker table tbody td.date-picker-today\r
+        {\r
+        background:#fff url(../media/bullet2.gif) no-repeat 0 0;\r
+        color:rgb(100,100,100) !important;\r
+        }\r
+\r
+div.datePicker table tbody td.month-out.date-picker-highlight \r
+        {\r
+        color:#aa8866 !important;\r
+        }\r
+/* The "highlight days" style */\r
+div.datePicker table tbody td.date-picker-highlight,\r
+div.datePicker table thead th.date-picker-highlight\r
+        {\r
+        color:#a86666 !important;\r
+        }\r
+/* The "active cursor" style */\r
+div.datePicker table tbody td.date-picker-hover\r
+        {\r
+        background:#fff url(../media/bg_header.jpg) no-repeat 0 0;\r
+        cursor:pointer;\r
+        border-color:rgb(100,130,170) !important;\r
+        color:rgb(100,130,170);                 \r
+        }\r
+/* The "disabled days" style */\r
+div.datePicker table tbody td.day-disabled\r
+        {          \r
+        background:#fff url(../media/backstripes.gif) no-repeat 0 0;\r
+        color:#aaa !important;\r
+        cursor:default;\r
+        text-decoration:line-through;\r
+        } \r
+div.datePicker table tbody td.month-out \r
+        {\r
+        border-color:#ddd;\r
+        color:#aaa !important;\r
+        background:#fff url(../media/gradient-e5e5e5-ffffff.gif) repeat-x 0 -40px;                       \r
+        } \r
+/* The "selected date" style */\r
+div.datePicker table tbody td.date-picker-selected-date\r
+        {\r
+        color:#333 !important;\r
+        border-color:#333 !important;\r
+        }\r
+/* The date "out of range" style */\r
+div.datePicker table tbody td.out-of-range,\r
+div.datePicker table tbody td.not-selectable\r
+        {\r
+        color:#ccc !important;\r
+        font-style:oblique;\r
+        background:#fcfcfc !important;\r
+        cursor:default !important;\r
+        opacity:0.6;\r
+        } \r
+/* Week number "out of range" && "month-out" styles */\r
+div.datePicker table tbody th.month-out,\r
+div.datePicker table tbody th.out-of-range\r
+        {\r
+        color:#aaa !important;\r
+        font-style:oblique;\r
+        background:#fcfcfc !important;          \r
+        }\r
+div.datePicker table tbody th.out-of-range\r
+        {\r
+        opacity:0.6;\r
+        }  \r
+/* Used when the entire grid is full but next/prev months cannot be selected */\r
+div.datePicker table tbody td.not-selectable\r
+        {\r
+        opacity:0.8;\r
+        }\r
+div.datePicker table tbody tr\r
+        {\r
+        display:table-row;\r
+        }\r
+div.datePicker table tfoot sup\r
+        {\r
+        font-size:0.8em;\r
+        letter-spacing:normal;\r
+        text-transform:none;\r
+        height: 0;\r
+       line-height: 1;\r
+       position: relative;\r
+       top: -0.2em;    \r
+       vertical-align: baseline !important;\r
+       vertical-align: bottom;  \r
+        }\r
+/* INTERNET EXPLORER WOES\r
+   ======================\r
+   \r
+   Hover Effects\r
+   -------------\r
+   \r
+   Cannot deal with :focus and so the datePicker script adds the class "dp-row-highlight" to the\r
+   row currently being hovered over. This should enable you to add hover effects if desired.\r
+   \r
+   e.g. the following rule will highlight the cell borders in another colour when a row is moused over,\r
+   it looks like crap though so I didn't include the rule within the demo:\r
+   \r
+div.datePicker table tbody tr.dp-row-highlight td\r
+        {\r
+        border-color:#aaa;\r
+        }\r
+*/\r
+\r
+/* Remove the images for Internet Explorer <= v6 using the "* html" hack - (NTS: move this to it's own file) \r
+   This is a workaround for a nasty IE6 bug that never caches background images on dynamically created DOM nodes\r
+   which means that they are downloaded for every cell for every table - nasty shit indeed! */    \r
+* html div.datePicker table td\r
+        {\r
+        background-image:none;\r
+        }\r
+* html div.datePicker table td.date-picker-unused\r
+        {\r
+        background:#f2f2f2;\r
+        }        \r
+@media screen and (-webkit-min-device-pixel-ratio:0) {\r
+        div.datePicker table\r
+                {\r
+                border-spacing:0.3em;\r
+                /* Naughty, naughty */\r
+                -webkit-box-shadow:0px 0px 5px #aaa;\r
+                -webkit-border-radius:0.8em;\r
+                }\r
+        div.static-datepicker table\r
+                {\r
+                -webkit-box-shadow:0 0 0 transparent;\r
+                }\r
+        div.static-datepicker:focus table\r
+                {\r
+                -webkit-box-shadow:0px 0px 5px #aaa;\r
+                }\r
+        div.datePicker table td,\r
+        div.datePicker table tbody th\r
+                {\r
+                padding:0.1em;\r
+                -webkit-border-radius:2px;\r
+                }\r
+        div.datePicker table tbody td.date-picker-hover\r
+                {\r
+                text-shadow:0px 0px 1px #fff;\r
+                -webkit-box-shadow:0px 0px 1px rgb(100,130,170);\r
+                }\r
+\r
+}\r
+\r
diff --git a/planetlab/datepicker/datepicker.js b/planetlab/datepicker/datepicker.js
new file mode 100644 (file)
index 0000000..16b099f
--- /dev/null
@@ -0,0 +1,2107 @@
+/*\r
+        DatePicker v4b rc1 by frequency-decoder.com\r
+\r
+        Released under a creative commons Attribution-ShareAlike 2.5 license (http://creativecommons.org/licenses/by-sa/2.5/)\r
+\r
+        Please credit frequency-decoder in any derivative work - thanks.\r
+        \r
+        You are free:\r
+\r
+        * to copy, distribute, display, and perform the work\r
+        * to make derivative works\r
+        * to make commercial use of the work\r
+\r
+        Under the following conditions:\r
+\r
+                by Attribution.\r
+                --------------\r
+                You must attribute the work in the manner specified by the author or licensor.\r
+\r
+                sa\r
+                --\r
+                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.\r
+\r
+        * For any reuse or distribution, you must make clear to others the license terms of this work.\r
+        * Any of these conditions can be waived if you get permission from the copyright holder.\r
+*/\r
+\r
+var datePickerController = (function datePickerController() {\r
+        var languageInfo        = navigator.language ? navigator.language.toLowerCase().replace(/-[a-z]+$/, "") : navigator.userLanguage ? navigator.userLanguage.toLowerCase().replace(/-[a-z]+$/, "") : "en",\r
+            datePickers         = {},\r
+            uniqueId            = 0,\r
+            weeksInYearCache    = {},\r
+            localeImport        = false,\r
+            nbsp                = String.fromCharCode(160),\r
+            nodrag              = false,\r
+            splitAppend         = ["-dd","-mm"],\r
+            formatMasks         = ["Y-sl-m-sl-d","m-sl-d-sl-Y","d-sl-m-sl-Y","Y-ds-m-ds-d","m-ds-d-ds-Y","d-ds-m-ds-Y"];                \r
+        \r
+        void function() {\r
+                var scriptFiles = document.getElementsByTagName('head')[0].getElementsByTagName('script'),                    \r
+                    scriptInner = scriptFiles[scriptFiles.length - 1].innerHTML.replace(/[\n\r\s\t]+/g, " ").replace(/^\s+/, "").replace(/\s+$/, ""),                    \r
+                    json        = parseJSON(scriptInner);                \r
+               \r
+                if(typeof json === "object" && !("err" in json)) {                          \r
+                        affectJSON(json);\r
+                };\r
+       \r
+                if(typeof(fdLocale) != "object" && languageInfo != "en") {\r
+                        var loc    = scriptFiles[scriptFiles.length - 1].src.substr(0, scriptFiles[scriptFiles.length - 1].src.lastIndexOf("/")) + "/lang/" + languageInfo + ".js",\r
+                            script = document.createElement('script');\r
+                                                          \r
+                        script.type = "text/javascript";                         \r
+                        script.src  = loc;\r
+                        script.setAttribute("charset", "utf-8");\r
+                        /*@cc_on\r
+                        /*@if(@_win32)\r
+                        var bases = document.getElementsByTagName('base');\r
+                        if (bases.length && bases[0].childNodes.length) {\r
+                                bases[0].appendChild(script);\r
+                        } else {\r
+                                document.getElementsByTagName('head')[0].appendChild(script);\r
+                        };\r
+                        bases = null;\r
+                        @else @*/\r
+                        document.getElementsByTagName('head')[0].appendChild(script);\r
+                        /*@end\r
+                        @*/    \r
+                        \r
+                        script = null;                      \r
+                };                              \r
+        }();\r
+        \r
+        function affectJSON(json) {\r
+                if(typeof json !== "object") { return; };\r
+                for(key in json) {\r
+                        value = json[key];                                                                \r
+                        switch(key.toLower()) { \r
+                                case "lang":\r
+                                        if(value.search(/^[a-z]{2}$/i) != -1) {\r
+                                                languageInfo = value;\r
+                                        };\r
+                                        break;\r
+                                case "split":                                                 \r
+                                        if(typeof value === 'object') {\r
+                                                if(value.length && value.length == 2) {                                                        \r
+                                                        splitAppend = value;\r
+                                                };\r
+                                        }; \r
+                                case "formats":                                                 \r
+                                        if(typeof value === 'object') {\r
+                                                if(value.length) {\r
+                                                        formatMasks = value;\r
+                                                };\r
+                                        };\r
+                                        break;\r
+                                case "nodrag":\r
+                                        nodrag = !!value;                                                                                                                                         \r
+                        };          \r
+                };        \r
+        };\r
+                \r
+        // Functions shared between the datePickerController object & the datePicker objects    \r
+        function pad(value, length) { \r
+                length = length || 2; \r
+                return "0000".substr(0,length - Math.min(String(value).length, length)) + value; \r
+        };\r
+        \r
+        function addEvent(obj, type, fn) {\r
+                if( obj.attachEvent ) {\r
+                        obj["e"+type+fn] = fn;\r
+                        obj[type+fn] = function(){obj["e"+type+fn]( window.event );};\r
+                        obj.attachEvent( "on"+type, obj[type+fn] );\r
+                } else {\r
+                        obj.addEventListener( type, fn, true );\r
+                };\r
+        };\r
+        \r
+        function removeEvent(obj, type, fn) {\r
+                try {\r
+                        if( obj.detachEvent ) {\r
+                                obj.detachEvent( "on"+type, obj[type+fn] );\r
+                                obj[type+fn] = null;\r
+                        } else {\r
+                                obj.removeEventListener( type, fn, true );\r
+                        };\r
+                } catch(err) {};\r
+        };   \r
+\r
+        function stopEvent(e) {\r
+                e = e || document.parentWindow.event;\r
+                if(e.stopPropagation) {\r
+                        e.stopPropagation();\r
+                        e.preventDefault();\r
+                };\r
+                /*@cc_on\r
+                @if(@_win32)\r
+                e.cancelBubble = true;\r
+                e.returnValue = false;\r
+                @end\r
+                @*/\r
+                return false;\r
+        };\r
+        \r
+        function parseJSON(str) {\r
+                // Check we have a String\r
+                if(typeof str !== 'string' || str == "") { return {}; };                 \r
+                try {\r
+                        // Does the Douglas Crockford JSON parser exist in the global scope?\r
+                        if("JSON" in window && "parse" in window.JSON && typeof window.JSON.parse == "function") {                                               \r
+                                return window.JSON.parse(str);  \r
+                        // Genious code taken from: http://kentbrewster.com/badges/                                                      \r
+                        } else if(/lang|split|formats|nodrag/.test(str.toLower())) {                                               \r
+                                var f = Function(['var document,top,self,window,parent,Number,Date,Object,Function,',\r
+                                        'Array,String,Math,RegExp,Image,ActiveXObject;',\r
+                                        'return (' , str.replace(/<\!--.+-->/gim,'').replace(/\bfunction\b/g,'function­') , ');'].join(''));\r
+                                return f();                          \r
+                        };\r
+                } catch (e) {                                 \r
+                        return {"err":"Trouble parsing JSON object"};\r
+                };\r
+                return {};                                            \r
+        };        \r
+\r
+        // The datePicker object itself \r
+        function datePicker(options) {                                      \r
+                this.dateSet             = null;                 \r
+                this.timerSet            = false;\r
+                this.visible             = false;\r
+                this.fadeTimer           = null;\r
+                this.timer               = null;\r
+                this.yearInc             = 0;\r
+                this.monthInc            = 0;\r
+                this.dayInc              = 0;\r
+                this.mx                  = 0;\r
+                this.my                  = 0;\r
+                this.x                   = 0;\r
+                this.y                   = 0;                  \r
+                this.date                = new Date();\r
+                this.defaults            = {};\r
+                this.created             = false;\r
+                this.id                  = options.id;\r
+                this.opacity             = 0;          \r
+                this.firstDayOfWeek      = 0; \r
+                this.buttonWrapper       = "buttonWrapper" in options ? options.buttonWrapper : false;                \r
+                this.staticPos           = "staticPos" in options ? !!options.staticPos : false;\r
+                this.disabledDays        = "disabledDays" in options && options.disabledDays.length ? options.disabledDays : [0,0,0,0,0,0,0];\r
+                this.disabledDates       = "disabledDates" in options ? options.disabledDates : {};\r
+                this.enabledDates        = "enabledDates" in options ? options.enabledDates : {};\r
+                this.showWeeks           = "showWeeks" in options ? !!options.showWeeks : false;\r
+                this.low                 = options.low || "";\r
+                this.high                = options.high || "";\r
+                this.dragDisabled        = nodrag ? true : ("dragDisabled" in options ? !!options.dragDisabled : false);\r
+                this.positioned          = "positioned" in options ? options.positioned : false;\r
+                this.hideInput           = this.staticPos ? false : "hideInput" in options ? !!options.hideInput : false;\r
+                this.splitDate           = "splitDate" in options ? !!options.splitDate : false;\r
+                this.format              = options.format || "d-sl-m-sl-Y";\r
+                this.statusFormat        = options.statusFormat || "";\r
+                this.highlightDays       = options.highlightDays && options.highlightDays.length ? options.highlightDays : [0,0,0,0,0,1,1];\r
+                this.noFadeEffect        = "noFadeEffect" in options ? !!options.noFadeEffect : false;\r
+                this.opacityTo           = this.noFadeEffect || this.staticPos ? 99 : 90;\r
+                this.callbacks           = {};\r
+                this.fillGrid            = !!options.fillGrid;\r
+                this.noToday             = !!options.noToday;\r
+                this.constrainSelection  = this.fillGrid && !!options.constrainSelection;\r
+                this.finalOpacity        = !this.staticPos && "finalOpacity" in options ? +options.finalOpacity : 90;                \r
+                this.dynDisabledDates    = {};\r
+                this.inUpdate            = false;\r
+                /*@cc_on\r
+                /*@if(@_win32)\r
+                this.interval            = new Date();\r
+                this.iePopUp             = null;\r
+                /*@end@*/\r
+                \r
+                for(var thing in options.callbacks) {\r
+                        this.callbacks[thing] = options.callbacks[thing];                 \r
+                };\r
+                \r
+                // Adjust time to stop daylight savings madness on windows\r
+                this.date.setHours(12);              \r
+          \r
+                this.startDrag = function(e) {\r
+                        e = e || document.parentWindow.event;\r
+                        o.mx = e.pageX?e.pageX:e.clientX?e.clientX:e.x;\r
+                        o.my = e.pageY?e.pageY:e.clientY?e.clientY:e.Y;\r
+                        o.x = parseInt(o.div.style.left);\r
+                        o.y = parseInt(o.div.style.top);\r
+                        addEvent(document,'mousemove',o.trackDrag, false);\r
+                        addEvent(document,'mouseup',o.stopDrag, false);\r
+                        o.div.style.zIndex = 10000;\r
+                        return stopEvent(e);\r
+                };\r
+                this.trackDrag = function(e) {\r
+                        e = e || window.event;\r
+                        var diffx = (e.pageX?e.pageX:e.clientX?e.clientX:e.x) - o.mx;\r
+                        var diffy = (e.pageY?e.pageY:e.clientY?e.clientY:e.Y) - o.my;\r
+                        o.div.style.left = Math.round(o.x + diffx) > 0 ? Math.round(o.x + diffx) + 'px' : "0px";\r
+                        o.div.style.top  = Math.round(o.y + diffy) > 0 ? Math.round(o.y + diffy) + 'px' : "0px";\r
+                        /*@cc_on\r
+                        @if(@_jscript_version <= 5.6)\r
+                        if(o.staticPos) return;\r
+                        o.iePopUp.style.top    = o.div.style.top;\r
+                        o.iePopUp.style.left   = o.div.style.left;\r
+                        @end\r
+                        @*/\r
+                };\r
+                this.stopDrag = function(e) {\r
+                        removeEvent(document,'mousemove',o.trackDrag, false);\r
+                        removeEvent(document,'mouseup',o.stopDrag, false);\r
+                        o.div.style.zIndex = 9999;\r
+                };\r
+                this.changeHandler = function() {                        \r
+                        o.setDateFromInput();                        \r
+                        if(o.created) o.updateTable();\r
+                };\r
+                this.reposition = function() {\r
+                        if(!o.created || !o.getElem() || o.staticPos) { return; };\r
+\r
+                        o.div.style.visibility = "hidden";\r
+                        o.div.style.left = o.div.style.top = "0px";                           \r
+                        o.div.style.display = "block";\r
+\r
+                        var osh         = o.div.offsetHeight,\r
+                            osw         = o.div.offsetWidth,\r
+                            elem        = document.getElementById('fd-but-' + o.id),\r
+                            pos         = o.truePosition(elem),\r
+                            trueBody    = (document.compatMode && document.compatMode!="BackCompat") ? document.documentElement : document.body,\r
+                            scrollTop   = window.devicePixelRatio || window.opera ? 0 : trueBody.scrollTop,\r
+                            scrollLeft  = window.devicePixelRatio || window.opera ? 0 : trueBody.scrollLeft;\r
+\r
+                        o.div.style.visibility = "visible";\r
+\r
+                        o.div.style.left  = Number(parseInt(trueBody.clientWidth+scrollLeft) < parseInt(osw+pos[0]) ? Math.abs(parseInt((trueBody.clientWidth+scrollLeft) - osw)) : pos[0]) + "px";\r
+                        o.div.style.top   = Number(parseInt(trueBody.clientHeight+scrollTop) < parseInt(osh+pos[1]+elem.offsetHeight+2) ? Math.abs(parseInt(pos[1] - (osh + 2))) : Math.abs(parseInt(pos[1] + elem.offsetHeight + 2))) + "px";\r
+\r
+                        /*@cc_on\r
+                        @if(@_jscript_version <= 5.6)\r
+                        o.iePopUp.style.top    = o.div.style.top;\r
+                        o.iePopUp.style.left   = o.div.style.left;\r
+                        o.iePopUp.style.width  = osw + "px";\r
+                        o.iePopUp.style.height = (osh - 2) + "px";\r
+                        @end\r
+                        @*/\r
+                }; \r
+                this.updateTable = function(noCallback) {  \r
+                        if(o.inUpdate) return;\r
+                         \r
+                        o.inUpdate = true;\r
+                        o.removeHighlight();\r
+                                             \r
+                        if(o.timerSet) {\r
+                                o.date.setDate(Math.min(o.date.getDate()+o.dayInc, daysInMonth(o.date.getMonth()+o.monthInc,o.date.getFullYear()+o.yearInc)) );\r
+                                o.date.setMonth(o.date.getMonth() + o.monthInc);\r
+                                o.date.setFullYear(o.date.getFullYear() + o.yearInc);\r
+                        }; \r
+        \r
+                        o.outOfRange();\r
+                        if(!o.noToday) { o.disableTodayButton(); };\r
+                        o.showHideButtons(o.date);\r
+                \r
+                        var cd = o.date.getDate(),\r
+                            cm = o.date.getMonth(),\r
+                            cy = o.date.getFullYear(),\r
+                            cursorDate = (String(cy) + pad(cm+1) + pad(cd)),\r
+                            tmpDate    = new Date(cy, cm, 1);                      \r
+                \r
+                        tmpDate.setHours(5);\r
+                        \r
+                        var dt, cName, td, i, currentDate, cellAdded, col, currentStub, abbr, bespokeRenderClass,\r
+                        weekDayC            = ( tmpDate.getDay() + 6 ) % 7,                \r
+                        firstColIndex       = (((weekDayC - o.firstDayOfWeek) + 7 ) % 7) - 1,\r
+                        dpm                 = daysInMonth(cm, cy),\r
+                        today               = new Date(),\r
+                        dateSetD            = (o.dateSet != null) ? o.dateSet.getFullYear() + pad(o.dateSet.getMonth()+1) + pad(o.dateSet.getDate()) : false,\r
+                        stub                = String(tmpDate.getFullYear()) + pad(tmpDate.getMonth()+1),\r
+                        cellAdded           = [4,4,4,4,4,4],                                                                   \r
+                        lm                  = new Date(cy, cm-1, 1),\r
+                        nm                  = new Date(cy, cm+1, 1),                          \r
+                        daySub              = daysInMonth(lm.getMonth(), lm.getFullYear()),                \r
+                        stubN               = String(nm.getFullYear()) + pad(nm.getMonth()+1),\r
+                        stubP               = String(lm.getFullYear()) + pad(lm.getMonth()+1),                \r
+                        weekDayN            = (nm.getDay() + 6) % 7,\r
+                        weekDayP            = (lm.getDay() + 6) % 7,                                       \r
+                        today               = today.getFullYear() + pad(today.getMonth()+1) + pad(today.getDate());\r
+                        \r
+                        o.firstDateShown    = !o.constrainSelection && o.fillGrid && (0 - firstColIndex < 1) ? String(stubP) + (daySub + (0 - firstColIndex)) : stub + "01";            \r
+                        o.lastDateShown     = !o.constrainSelection && o.fillGrid ? stubN + pad(41 - firstColIndex - dpm) : stub + String(dpm);\r
+                        o.currentYYYYMM     = stub;                    \r
+                \r
+                        bespokeRenderClass  = o.callback("redraw", {id:o.id, dd:pad(cd), mm:pad(cm+1), yyyy:cy, firstDateDisplayed:o.firstDateShown, lastDateDisplayed:o.lastDateShown}) || {};                    \r
+                        o.dynDisabledDates  = o.getDisabledDates(cy, cm + 1);\r
+                       \r
+                        for(var curr = 0; curr < 42; curr++) {\r
+                                row  = Math.floor(curr / 7);                         \r
+                                td   = o.tds[curr];\r
+                                \r
+                                while(td.firstChild) td.removeChild(td.firstChild);\r
+                                if((curr > firstColIndex && curr <= (firstColIndex + dpm)) || o.fillGrid) {\r
+                                        currentStub     = stub;\r
+                                        weekDay         = weekDayC;                                \r
+                                        dt              = curr - firstColIndex;\r
+                                        cName           = [];                                         \r
+                                        selectable      = true;\r
+                                \r
+                                        if(dt < 1) {\r
+                                                dt              = daySub + dt;\r
+                                                currentStub     = stubP;\r
+                                                weekDay         = weekDayP;                                        \r
+                                                selectable      = !o.constrainSelection;\r
+                                                cName.push("month-out");                                                  \r
+                                        } else if(dt > dpm) {\r
+                                                dt -= dpm;\r
+                                                currentStub     = stubN;\r
+                                                weekDay         = weekDayN;                                        \r
+                                                selectable      = !o.constrainSelection; \r
+                                                cName.push("month-out");                                                                                           \r
+                                        }; \r
+                                                                                                   \r
+                                        td.appendChild(document.createTextNode(dt));\r
+                                        currentDate = currentStub + String(dt < 10 ? "0" : "") + dt;                            \r
+                                        \r
+                                        if(o.low && +currentDate < +o.low || o.high && +currentDate > +o.high) {                                          \r
+                                                td.className = "out-of-range";                                                \r
+                                                if(o.showWeeks) { cellAdded[row] = Math.min(cellAdded[row], 2); };                                                  \r
+                                        \r
+                                        } else {                               \r
+                                                if(selectable) {                                                 \r
+                                                        cName.push("cd-" + currentDate + " yyyymm-" + currentStub + " mmdd-" + currentStub.substr(4,2) + pad(dt));\r
+                                                } else {                                                    \r
+                                                        cName.push("not-selectable yyyymm-" + currentStub + " mmdd-" + currentStub.substr(4,2) + pad(dt));\r
+                                                };                                                                                                      \r
+                                        \r
+                                                weekDay = ( weekDay + dt + 6 ) % 7;\r
+\r
+                                                if(currentDate == today) { cName.push("date-picker-today"); };\r
+\r
+                                                if(dateSetD == currentDate) { cName.push("date-picker-selected-date"); };\r
+\r
+                                                if(o.disabledDays[weekDay] || currentDate in o.dynDisabledDates) { cName.push("day-disabled"); }\r
+                                        \r
+                                                if(currentDate in bespokeRenderClass) { cName.push(bespokeRenderClass[currentDate]); }\r
+                                        \r
+                                                if(o.highlightDays[weekDay]) { cName.push("date-picker-highlight"); };\r
+\r
+                                                if(cursorDate == currentDate) { td.id = o.id + "-date-picker-hover"; cName.push("date-picker-hover"); }\r
+                                                else { td.id = ""; };\r
+                                        \r
+                                                td.className = cName.join(" ");\r
+\r
+                                                if(o.showWeeks) {                                                         \r
+                                                        cellAdded[row] = Math.min(cName[0] == "month-out" ? 3 : 1, cellAdded[row]);                                                          \r
+                                                }; \r
+                                        };                       \r
+                                } else {\r
+                                        td.className = "date-picker-unused";\r
+                                        td.id = "";                                         \r
+                                        td.appendChild(document.createTextNode(nbsp));                                        \r
+                                };                                 \r
+                                \r
+                                if(o.showWeeks && curr - (row * 7) == 6) { \r
+                                        while(o.wkThs[row].firstChild) o.wkThs[row].removeChild(o.wkThs[row].firstChild);                                         \r
+                                        o.wkThs[row].appendChild(document.createTextNode(cellAdded[row] == 4 && !o.fillGrid ? nbsp : getWeekNumber(cy, cm, curr - firstColIndex - 6)));\r
+                                        o.wkThs[row].className = "date-picker-week-header" + (["",""," out-of-range"," month-out",""][cellAdded[row]]);                                          \r
+                                };                                \r
+                        };\r
+\r
+                        // Title Bar\r
+                        var span = o.titleBar.getElementsByTagName("span");\r
+                        while(span[0].firstChild) span[0].removeChild(span[0].firstChild);\r
+                        while(span[1].firstChild) span[1].removeChild(span[1].firstChild);\r
+                        span[0].appendChild(document.createTextNode(getMonthTranslation(cm, false) + nbsp));\r
+                        span[1].appendChild(document.createTextNode(cy));\r
+                        \r
+                        if(o.timerSet) {\r
+                                o.timerInc = 50 + Math.round(((o.timerInc - 50) / 1.8));\r
+                                o.timer = window.setTimeout(o.updateTable, o.timerInc);\r
+                        };\r
+                        \r
+                        o.inUpdate = false;                          \r
+                };\r
+                \r
+                this.show = function() {\r
+                        var elem = this.getElem();\r
+                        if(!elem || this.visible || elem && elem.disabled) { return; };\r
+\r
+                        if(!document.getElementById('fd-' + this.id)) {\r
+                                this.created = false;\r
+                                this.create();\r
+                        } else {                           \r
+                                this.setDateFromInput();\r
+                                this.outOfRange();\r
+                                this.updateTable();\r
+                        };                         \r
+                        \r
+                        if(!this.staticPos) this.reposition();                        \r
+\r
+                        addEvent(this.staticPos ? this.table : document, "mousedown", this.events.onmousedown);\r
+                        this.opacityTo = this.finalOpacity;\r
+                        this.div.style.display = "block";\r
+                        if(!this.staticPos) {\r
+                                /*@cc_on\r
+                                @if(@_jscript_version <= 5.6)\r
+                                this.iePopUp.style.width = this.div.offsetWidth + "px";\r
+                                this.iePopUp.style.height = this.div.offsetHeight + "px";\r
+                                this.iePopUp.style.display = "block";\r
+                                @end\r
+                                @*/\r
+                                this.addKeyboardEvents();\r
+                                this.fade();\r
+                                var butt = document.getElementById('fd-but-' + this.id);\r
+                                if(butt) butt.className = butt.className.replace("dp-button-active", "") + " dp-button-active";\r
+\r
+                        } else {\r
+                                this.opacity = this.opacityTo;\r
+                        };\r
+                };\r
+                this.hide = function() {\r
+                        if(!this.visible) return;\r
+                        this.stopTimer();\r
+                        if(this.staticPos) return;\r
+\r
+                        var butt = document.getElementById('fd-but-' + this.id);\r
+                        if(butt) butt.className = butt.className.replace("dp-button-active", "");\r
+                \r
+                        removeEvent(document, "mousedown", this.events.onmousedown);\r
+                        removeEvent(document, "mouseup",  this.events.clearTimer);\r
+                        this.removeKeyboardEvents();\r
+\r
+                        /*@cc_on\r
+                        @if(@_jscript_version <= 5.6)\r
+                        this.iePopUp.style.display = "none";\r
+                        @end\r
+                        @*/\r
+\r
+                        this.opacityTo = 0;\r
+                        this.fade();\r
+                        \r
+                        //var elem = this.getElem();\r
+                        //if(!elem.type || elem.type && elem.type != "hidden") { elem.focus(); };\r
+                };\r
+                this.destroy = function() {\r
+                        // Cleanup for Internet Explorer\r
+                        removeEvent(this.staticPos ? this.table : document, "mousedown", o.events.onmousedown);\r
+                        removeEvent(document, "mouseup",   o.events.clearTimer);\r
+                        o.removeKeyboardEvents();\r
+                        clearTimeout(o.fadeTimer);\r
+                        clearTimeout(o.timer);\r
+\r
+                        /*@cc_on\r
+                        @if(@_jscript_version <= 5.6)\r
+                        if(!o.staticPos) {\r
+                                o.iePopUp.parentNode.removeChild(o.iePopUp);\r
+                                o.iePopUp = null;\r
+                        };\r
+                        @end\r
+                        @*/\r
+\r
+                        if(!this.staticPos && document.getElementById(this.id.replace(/^fd-/, 'fd-but-'))) {\r
+                                var butt = document.getElementById(this.id.replace(/^fd-/, 'fd-but-'));\r
+                                butt.onclick = butt.onpress = null;\r
+                        };\r
+\r
+                        if(this.div && this.div.parentNode) {\r
+                                this.div.parentNode.removeChild(this.div);\r
+                        };\r
+\r
+                        o = null;\r
+                };\r
+                this.resizeInlineDiv = function()  {                        \r
+                        o.div.style.width = o.table.offsetWidth + "px";\r
+                };\r
+                this.create = function() {\r
+                        if(this.created) { return; };\r
+\r
+                        function createTH(details) {\r
+                                var th = document.createElement('th');\r
+                                if(details.thClassName) th.className = details.thClassName;\r
+                                if(details.colspan) {\r
+                                        /*@cc_on\r
+                                        /*@if (@_win32)\r
+                                        th.setAttribute('colSpan',details.colspan);\r
+                                        @else @*/\r
+                                        th.setAttribute('colspan',details.colspan);\r
+                                        /*@end\r
+                                        @*/\r
+                                };\r
+                                /*@cc_on\r
+                                /*@if (@_win32)\r
+                                th.unselectable = "on";\r
+                                /*@end@*/\r
+                                return th;\r
+                        };\r
+                        function createThAndButton(tr, obj) {\r
+                                for(var i = 0, details; details = obj[i]; i++) {\r
+                                        var th = createTH(details);\r
+                                        tr.appendChild(th);\r
+                                        var but = document.createElement('span');\r
+                                        but.className = details.className;\r
+                                        but.id = o.id + details.id;\r
+                                        but.appendChild(document.createTextNode(details.text || o.nbsp));\r
+                                        but.title = details.title || "";\r
+                                        if(details.onmousedown) but.onmousedown = details.onmousedown;\r
+                                        if(details.onclick)     but.onclick     = details.onclick;\r
+                                        if(details.onmouseout)  but.onmouseout  = details.onmouseout;\r
+                                        /*@cc_on\r
+                                        /*@if(@_win32)\r
+                                        th.unselectable = but.unselectable = "on";\r
+                                        /*@end@*/\r
+                                        th.appendChild(but);\r
+                                };\r
+                        };  \r
+                        \r
+                        this.div                     = document.createElement('div');\r
+                        this.div.id                  = "fd-" + this.id;\r
+                        this.div.className           = "datePicker";                   \r
+                        \r
+                        var tr, row, col, tableHead, tableBody, tableFoot;\r
+\r
+                        this.table             = document.createElement('table');\r
+                        this.table.className   = "datePickerTable";                         \r
+                        this.table.onmouseover = this.events.ontablemouseover;\r
+                        this.table.onmouseout  = this.events.ontablemouseout;\r
+\r
+                        this.div.appendChild(this.table);   \r
+                                \r
+                        if(!this.staticPos) {\r
+                                this.div.style.visibility = "hidden";\r
+                                if(!this.dragDisabled) { this.div.className += " drag-enabled"; };\r
+                                document.getElementsByTagName('body')[0].appendChild(this.div);\r
+                                                                \r
+                                /*@cc_on\r
+                                @if(@_jscript_version <= 5.6)                                            \r
+                                this.iePopUp = document.createElement('iframe');\r
+                                this.iePopUp.src = "javascript:'<html></html>';";\r
+                                this.iePopUp.setAttribute('className','iehack');\r
+                                this.iePopUp.scrolling="no";\r
+                                this.iePopUp.frameBorder="0";\r
+                                this.iePopUp.name = this.iePopUp.id = this.id + "-iePopUpHack";\r
+                                document.body.appendChild(this.iePopUp);\r
+                                @end\r
+                                @*/\r
+                        } else {\r
+                                elem = this.positioned ? document.getElementById(this.positioned) : this.getElem();\r
+                                if(!elem) {\r
+                                        this.div = null;\r
+                                        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;\r
+                                };\r
+\r
+                                this.div.className += " static-datepicker";                               \r
+                                                               \r
+                                // tabIndex\r
+                                this.div.setAttribute(!/*@cc_on!@*/false ? "tabIndex" : "tabindex", "0");\r
+                                this.div.tabIndex = 0;\r
+\r
+                                this.div.onfocus = this.events.onfocus;\r
+                                this.div.onblur  = this.events.onblur;                                                                                                                         \r
+                                \r
+                                if(this.positioned) {\r
+                                        elem.appendChild(this.div);\r
+                                } else {\r
+                                        elem.parentNode.insertBefore(this.div, elem.nextSibling);\r
+                                };\r
+                                \r
+                                if(this.hideInput) {\r
+                                        var elemList = [elem];                                        \r
+                                        if(this.splitDate) {\r
+                                                elemList[elemList.length] = document.getElementById(this.id + splitAppend[1]);\r
+                                                elemList[elemList.length] = document.getElementById(this.id + splitAppend[0]);                                         \r
+                                        };\r
+                                        for(var i = 0; i < elemList.length; i++) {\r
+                                                if(elemList[i].tagName) elemList[i].className += " fd-hidden-input";        \r
+                                        };\r
+                                };                                                                  \r
+                                                                          \r
+                                setTimeout(this.resizeInlineDiv, 300);                               \r
+                        };\r
+\r
+                        \r
+                        if(this.statusFormat) {\r
+                                tableFoot = document.createElement('tfoot');\r
+                                this.table.appendChild(tableFoot);\r
+                                tr = document.createElement('tr');\r
+                                tr.className = "date-picker-tfoot";\r
+                                tableFoot.appendChild(tr);\r
+                                this.statusBar = createTH({thClassName:"date-picker-statusbar", colspan:this.showWeeks ? 8 : 7});\r
+                                tr.appendChild(this.statusBar);\r
+                                this.updateStatus();\r
+                                if(!this.dragDisabled) {\r
+                                        this.statusBar.className += " drag-enabled";\r
+                                        addEvent(this.statusBar,'mousedown',this.startDrag,false);\r
+                                };\r
+                        };\r
+\r
+                        tableHead = document.createElement('thead');\r
+                        this.table.appendChild(tableHead);\r
+\r
+                        tr  = document.createElement('tr');\r
+                        tableHead.appendChild(tr);\r
+\r
+                        // Title Bar\r
+                        this.titleBar = createTH({thClassName:!this.dragDisabled ? "date-picker-title drag-enabled" : "date-picker-title", colspan:this.showWeeks ? 8 : 7});\r
+                        if(!this.dragDisabled) {\r
+                                addEvent(this.titleBar,'mousedown',o.startDrag,false);\r
+                        };\r
+\r
+                        tr.appendChild(this.titleBar);\r
+                        tr = null;\r
+\r
+                        var span = document.createElement('span');\r
+                        span.appendChild(document.createTextNode(nbsp));\r
+                        span.className = !this.dragDisabled ? "month-display drag-enabled" : "month-display";\r
+                        this.titleBar.appendChild(span);\r
+\r
+                        span = document.createElement('span');\r
+                        span.appendChild(document.createTextNode(nbsp));\r
+                        span.className = !this.dragDisabled ? "year-display drag-enabled" : "year-display";\r
+                        this.titleBar.appendChild(span);\r
+\r
+                        span = null;\r
+\r
+                        tr  = document.createElement('tr');\r
+                        tableHead.appendChild(tr);\r
+\r
+                        createThAndButton(tr, [\r
+                        {className:"prev-but prev-year", id:"-prev-year-but", text:"\u00AB", title:getTitleTranslation(2), onmousedown:function(e) { addEvent(document, "mouseup", o.events.clearTimer);  o.events.incDec(e,0,-1,0); }, onmouseout:this.events.clearTimer },\r
+                        {className:"prev-but prev-month", id:"-prev-month-but", text:"\u2039", title:getTitleTranslation(0), onmousedown:function(e) { addEvent(document, "mouseup", o.events.clearTimer); if(o.currentYYYYMM > Number(o.date.getFullYear() + pad(o.date.getMonth()+1))) { o.stopTimer(); o.updateTable(); o.timer = window.setTimeout(function() { o.events.incDec(e,0,0,-1); }, 800); return; }; o.events.incDec(e,0,0,-1); }, onmouseout:this.events.clearTimer },\r
+                        {colspan:this.showWeeks ? 4 : 3, className:"today-but", id:"-today-but", text:getTitleTranslation(4), onclick:this.events.gotoToday},\r
+                        {className:"next-but next-month", id:"-next-month-but", text:"\u203A", title:getTitleTranslation(1), onmousedown:function(e) { addEvent(document, "mouseup", o.events.clearTimer); if(o.currentYYYYMM < Number(o.date.getFullYear() + pad(o.date.getMonth()+1))) { o.stopTimer(); o.updateTable(); o.timer = window.setTimeout(function() { o.events.incDec(e,0,0,1); }, 800);  return; }; o.events.incDec(e,0,0,1); }, onmouseout:this.events.clearTimer },\r
+                        {className:"next-but next-year", id:"-next-year-but", text:"\u00BB", title:getTitleTranslation(3), onmousedown:function(e) { addEvent(document, "mouseup", o.events.clearTimer); o.events.incDec(e,0,1,0); }, onmouseout:this.events.clearTimer }]);\r
+\r
+                        tableBody = document.createElement('tbody');\r
+                        this.table.appendChild(tableBody);\r
+\r
+                        var colspanTotal = this.showWeeks ? 8 : 7,\r
+                            colOffset    = this.showWeeks ? 0 : -1,\r
+                            but, abbr;   \r
+                \r
+                        for(var rows = 0; rows < 7; rows++) {\r
+                                row = document.createElement('tr');\r
+\r
+                                if(rows != 0) {\r
+                                        tableBody.appendChild(row);   \r
+                                } else {\r
+                                        tableHead.appendChild(row);\r
+                                };\r
+\r
+                                for(var cols = 0; cols < colspanTotal; cols++) {\r
+                                                                                \r
+                                        if(rows === 0 || (this.showWeeks && cols === 0)) {\r
+                                                col = document.createElement('th');\r
+                                        } else {\r
+                                                col = document.createElement('td');\r
+                                        };\r
+                                        \r
+                                        /*@cc_on@*/\r
+                                        /*@if(@_win32)\r
+                                        col.unselectable = "on";\r
+                                        /*@end@*/  \r
+                                        \r
+                                        row.appendChild(col);\r
+                                        if((this.showWeeks && cols > 0 && rows > 0) || (!this.showWeeks && rows > 0)) {\r
+                                                col.onclick = this.events.onclick;\r
+                                        } else {\r
+                                                if(rows === 0 && cols > colOffset) {\r
+                                                        col.className = "date-picker-day-header";\r
+                                                        col.scope = "col";                                           \r
+                                                } else {\r
+                                                        col.className = "date-picker-week-header";\r
+                                                        col.scope = "row";\r
+                                                };\r
+                                        };\r
+                                };\r
+                        };\r
+\r
+                        col = row = null; \r
+                \r
+                        this.ths = this.table.getElementsByTagName('thead')[0].getElementsByTagName('tr')[2].getElementsByTagName('th');\r
+                        for (var y = 0; y < colspanTotal; y++) {\r
+                                if(y == 0 && this.showWeeks) {\r
+                                        this.ths[y].appendChild(document.createTextNode(getTitleTranslation(6)));\r
+                                        this.ths[y].title = getTitleTranslation(8);\r
+                                        continue;\r
+                                };\r
+\r
+                                if(y > (this.showWeeks ? 0 : -1)) {\r
+                                        but = document.createElement("span");\r
+                                        but.className = "fd-day-header";\r
+                                        but.onclick = this.ths[y].onclick = this.setFirstDayOfWeek;\r
+                                        /*@cc_on@*/\r
+                                        /*@if(@_win32)\r
+                                        but.unselectable = "on";\r
+                                        /*@end@*/\r
+                                        this.ths[y].appendChild(but);\r
+                                };\r
+                        };\r
+                \r
+                        but = null; \r
+                                        \r
+                        this.trs             = this.table.getElementsByTagName('tbody')[0].getElementsByTagName('tr');\r
+                        this.tds             = this.table.getElementsByTagName('tbody')[0].getElementsByTagName('td');\r
+                        this.butPrevYear     = document.getElementById(this.id + "-prev-year-but");\r
+                        this.butPrevMonth    = document.getElementById(this.id + "-prev-month-but");\r
+                        this.butToday        = document.getElementById(this.id + "-today-but");\r
+                        this.butNextYear     = document.getElementById(this.id + "-next-year-but"); \r
+                        this.butNextMonth    = document.getElementById(this.id + "-next-month-but");\r
+        \r
+                        if(this.noToday) {\r
+                                this.butToday.style.display = "none";        \r
+                        };\r
+                        \r
+                        if(this.showWeeks) {\r
+                                this.wkThs = this.table.getElementsByTagName('tbody')[0].getElementsByTagName('th');\r
+                                this.div.className += " weeks-displayed";\r
+                        };\r
+\r
+                        tableBody = tableHead = tr = createThAndButton = createTH = null;\r
+\r
+                        if(this.low && this.high && (this.high - this.low < 7)) { this.equaliseDates(); }; \r
+                        \r
+                        this.setDateFromInput();                                       \r
+                        this.updateTableHeaders();\r
+                        this.created = true;                         \r
+                        this.callback("create", {id:this.id});                        \r
+                        this.updateTable();                         \r
+                        \r
+                        if(this.staticPos) {                                 \r
+                                this.visible = true;\r
+                                this.show();\r
+                                this.div.style.visibility = "visible";\r
+                                this.opacity = this.opacityTo;\r
+                        } else {                                     \r
+                                this.reposition();\r
+                                this.div.style.visibility = "visible";\r
+                                this.fade();\r
+                        };                                               \r
+                };\r
+                this.setFirstDayOfWeek = function(e) {\r
+                        e = e || document.parentWindow.event;\r
+                        var elem = e.target != null ? e.target : e.srcElement;\r
+                        while(elem.tagName.toLowerCase() != "th") elem = elem.parentNode;                         \r
+                        var cnt = o.showWeeks ? -1 : 0;\r
+                        while(elem.previousSibling) {\r
+                                elem = elem.previousSibling;\r
+                                if(elem.tagName.toLowerCase() == "th") cnt++;\r
+                        };\r
+                        o.firstDayOfWeek = (o.firstDayOfWeek + cnt) % 7;\r
+                        o.updateTableHeaders();\r
+                        return stopEvent(e);\r
+                };\r
+                this.fade = function() {\r
+                        window.clearTimeout(o.fadeTimer);\r
+                        o.fadeTimer = null;   \r
+                        var diff = Math.round(o.opacity + ((o.opacityTo - o.opacity) / 4)); \r
+                        o.setOpacity(diff);  \r
+                        if(Math.abs(o.opacityTo - diff) > 3 && !o.noFadeEffect) {\r
+                                o.fadeTimer = window.setTimeout(o.fade, 50);\r
+                        } else {\r
+                                o.setOpacity(o.opacityTo);\r
+                                if(o.opacityTo == 0) {\r
+                                        o.div.style.display = "none";\r
+                                        o.visible = false;\r
+                                } else {\r
+                                        o.visible = true;\r
+                                };\r
+                        };\r
+                };          \r
+                this.events = {\r
+                        onblur:function(e) {                                    \r
+                                o.removeKeyboardEvents();                                 \r
+                                if(o.statusBar) { o.updateStatus(getTitleTranslation(9)); };\r
+                        },\r
+                        onfocus:function(e) {                                 \r
+                                o.addKeyboardEvents();                                 \r
+                                if(o.statusBar) { o.updateStatus(printFormattedDate(o.date, o.statusFormat, true)); };\r
+                        },\r
+                        onkeydown: function (e) {\r
+                                o.stopTimer();\r
+                                if(!o.visible) return false;\r
+\r
+                                if(e == null) e = document.parentWindow.event;\r
+                                var kc = e.keyCode ? e.keyCode : e.charCode;\r
+                                \r
+                                if( kc == 13 ) {\r
+                                        // RETURN/ENTER: close & select the date\r
+                                        var td = document.getElementById(o.id + "-date-picker-hover");                                         \r
+                                        if(!td || td.className.search(/cd-([0-9]{8})/) == -1 || td.className.search(/no-selection|out-of-range|day-disabled/) != -1) return stopEvent(e);\r
+                                        o.dateSet = new Date(o.date);\r
+                                        o.returnFormattedDate();\r
+                                        o.hide();\r
+                                        return stopEvent(e);\r
+                                } else if(kc == 27) {\r
+                                        // ESC: close, no date selection \r
+                                        o.hide();\r
+                                        return stopEvent(e);\r
+                                } else if(kc == 32 || kc == 0) {\r
+                                        // SPACE: goto today's date \r
+                                        o.date = new Date();\r
+                                        o.updateTable();\r
+                                        return stopEvent(e);\r
+                                };    \r
+                                 \r
+                                // Internet Explorer fires the keydown event faster than the JavaScript engine can\r
+                                // update the interface. The following attempts to fix this.\r
+                                /*@cc_on\r
+                                @if(@_win32)\r
+                                if(new Date().getTime() - o.interval.getTime() < 50) return stopEvent(e);\r
+                                o.interval = new Date();\r
+                                @end\r
+                                @*/\r
+                        \r
+                                if ((kc > 49 && kc < 56) || (kc > 97 && kc < 104)) {\r
+                                        if (kc > 96) kc -= (96-48);\r
+                                        kc -= 49;\r
+                                        o.firstDayOfWeek = (o.firstDayOfWeek + kc) % 7;\r
+                                        o.updateTableHeaders();\r
+                                        return stopEvent(e);\r
+                                };\r
+\r
+                                if ( kc < 33 || kc > 40 ) return true;\r
+\r
+                                var d = new Date(o.date), tmp, cursorYYYYMM = o.date.getFullYear() + pad(o.date.getMonth()+1); \r
+\r
+                                // HOME: Set date to first day of current month\r
+                                if(kc == 36) {\r
+                                        d.setDate(1); \r
+                                // END: Set date to last day of current month                                 \r
+                                } else if(kc == 35) {\r
+                                        d.setDate(daysInMonth(d.getMonth(),d.getFullYear())); \r
+                                // PAGE UP & DOWN                                   \r
+                                } else if ( kc == 33 || kc == 34) {\r
+                                        var add = (kc == 34) ? 1 : -1; \r
+                                        // CTRL + PAGE UP/DOWN: Moves to the same date in the previous/next year\r
+                                        if(e.ctrlKey) {                                                                                                               \r
+                                                d.setFullYear(d.getFullYear() + add);\r
+                                        // PAGE UP/DOWN: Moves to the same date in the previous/next month                                            \r
+                                        } else {                                                     \r
+                                                if(!((kc == 33 && o.currentYYYYMM > cursorYYYYMM) || (kc == 34 && o.currentYYYYMM < cursorYYYYMM))) {                                                    \r
+                                                        tmp = new Date(d);\r
+                                                        tmp.setDate(2);\r
+                                                        tmp.setMonth(d.getMonth() + add);                                         \r
+                                                        d.setDate(Math.min(d.getDate(), daysInMonth(tmp.getMonth(),tmp.getFullYear())));                                        \r
+                                                        d.setMonth(d.getMonth() + add);\r
+                                                };      \r
+                                        };                                 \r
+                                // LEFT ARROW                                    \r
+                                } else if ( kc == 37 ) {                                         \r
+                                        d = new Date(o.date.getFullYear(), o.date.getMonth(), o.date.getDate() - 1);                                       \r
+                                // RIGHT ARROW\r
+                                } else if ( kc == 39 || kc == 34) {                                         \r
+                                        d = new Date(o.date.getFullYear(), o.date.getMonth(), o.date.getDate() + 1 ); \r
+                                // UP ARROW                                        \r
+                                } else if ( kc == 38 ) {                                          \r
+                                        d = new Date(o.date.getFullYear(), o.date.getMonth(), o.date.getDate() - 7);  \r
+                                // DOWN ARROW                                        \r
+                                } else if ( kc == 40 ) {                                          \r
+                                        d = new Date(o.date.getFullYear(), o.date.getMonth(), o.date.getDate() + 7);                                         \r
+                                };\r
+\r
+                                if(o.outOfRange(d)) return stopEvent(e);\r
+                                o.date = d;\r
+                        \r
+                                if(o.statusBar) { o.updateStatus(printFormattedDate(o.date, o.statusFormat, true)); };\r
+                                var t = String(o.date.getFullYear()) + pad(o.date.getMonth()+1) + pad(o.date.getDate())\r
+\r
+                                if(e.ctrlKey || (kc == 33 || kc == 34) || t < o.firstDateShown || t > o.lastDateShown) {                                         \r
+                                        o.updateTable(); \r
+                                        o.interval = new Date();                                        \r
+                                } else {                                    \r
+                                        if(!o.noToday) { o.disableTodayButton(); }\r
+                                        o.removeHighlight();\r
+                                \r
+                                        var dt = "cd-" + o.date.getFullYear() + pad(o.date.getMonth()+1) + pad(o.date.getDate());\r
+                                            \r
+                                        for(var i = 0, td; td = o.tds[i]; i++) {  \r
+                                                td.className = td.className.replace(/date-picker-hover/g, "");                                               \r
+                                                if(td.className.search(dt) == -1) continue;                                                 \r
+                                                o.showHideButtons(o.date);\r
+                                                td.id = o.id + "-date-picker-hover";\r
+                                                td.className = td.className.replace(/date-picker-hover/g, "") + " date-picker-hover";\r
+                                                break;\r
+                                        };\r
+                                };\r
+\r
+                                return stopEvent(e);\r
+                        },\r
+                        gotoToday: function(e) {\r
+                                o.date = new Date();\r
+                                o.updateTable();\r
+                                return stopEvent(e);\r
+                        },\r
+                        onmousedown: function(e) {\r
+                                e = e || document.parentWindow.event;\r
+                                var el = e.target != null ? e.target : e.srcElement;\r
+                                while(el.parentNode) {\r
+                                        if(el.id && (el.id == "fd-" + o.id || el.id == "fd-but-" + o.id)) {\r
+                                                return true;\r
+                                        };\r
+                                        try { el = el.parentNode; } catch(err) { break; };\r
+                                };\r
+                                o.stopTimer();\r
+                                hideAll();\r
+                        },\r
+                        ontablemouseout:function(e) {\r
+                                e = e || document.parentWindow.event;\r
+                                var p = e.toElement || e.relatedTarget;\r
+                                while (p && p != this) try { p = p.parentNode } catch(e) { p = this; };\r
+                                if (p == this) return false;\r
+                                if(o.currentTR) {\r
+                                        o.currentTR.className = o.currentTR.className.replace('dp-row-highlight', '');\r
+                                        o.currentTR = null;\r
+                                };\r
+                                if(o.statusBar) { o.updateStatus(printFormattedDate(o.date, o.statusFormat, true)); };\r
+                        },\r
+                        ontablemouseover: function(e) {\r
+                                e = e || document.parentWindow.event;\r
+                                var el = e.target != null ? e.target : e.srcElement;\r
+                                while ( el.nodeType != 1 ) el = el.parentNode;\r
+\r
+                                if(!el || ! el.tagName) { return; };\r
+                                var statusText = getTitleTranslation(9);\r
+                                switch (el.tagName.toLowerCase()) {\r
+                                case "td":    \r
+                                        if(el.className.search(/date-picker-unused|out-of-range/) != -1) {\r
+                                                statusText = getTitleTranslation(9);\r
+                                        } else if(el.className.search(/cd-([0-9]{8})/) == -1) {\r
+                                                break;\r
+                                        } else {                                                \r
+                                                o.stopTimer();\r
+                                                var cellDate = el.className.match(/cd-([0-9]{8})/)[1];                                                                              \r
+                                                o.removeHighlight();\r
+                                                el.id = o.id+"-date-picker-hover";\r
+                                                el.className = el.className.replace(/date-picker-hover/g, "") + " date-picker-hover";                                                 \r
+                                                o.date = new Date(cellDate.substr(0,4),cellDate.substr(4,2)-1,cellDate.substr(6,2));                                                \r
+                                                if(!o.noToday) { o.disableTodayButton(); };\r
+                                                statusText = printFormattedDate(o.date, o.statusFormat, true);\r
+\r
+                                        };\r
+                                        break;\r
+                                case "th":\r
+                                        if(!o.statusBar) { break; };\r
+                                        if(el.className.search(/drag-enabled/) != -1) {\r
+                                                statusText = getTitleTranslation(10);\r
+                                        } else if(el.className.search(/date-picker-week-header/) != -1) {\r
+                                                var txt = el.firstChild ? el.firstChild.nodeValue : "";\r
+                                                statusText = txt.search(/^(\d+)$/) != -1 ? getTitleTranslation(7, [txt, txt < 3 && o.date.getMonth() == 11 ? getWeeksInYear(o.date.getFullYear()) + 1 : getWeeksInYear(o.date.getFullYear())]) : getTitleTranslation(9);\r
+                                        };\r
+                                        break;\r
+                                case "span":\r
+                                        if(!o.statusBar) { break; };\r
+                                        if(el.className.search(/drag-enabled/) != -1) {\r
+                                                statusText = getTitleTranslation(10);\r
+                                        } else if(el.className.search(/day-([0-6])/) != -1) {\r
+                                                var day = el.className.match(/day-([0-6])/)[1];\r
+                                                statusText = getTitleTranslation(11, [getDayTranslation(day, false)]);\r
+                                        } else if(el.className.search(/prev-year/) != -1) {\r
+                                                statusText = getTitleTranslation(2);\r
+                                        } else if(el.className.search(/prev-month/) != -1) {\r
+                                                statusText = getTitleTranslation(0);\r
+                                        } else if(el.className.search(/next-year/) != -1) {\r
+                                                statusText = getTitleTranslation(3);\r
+                                        } else if(el.className.search(/next-month/) != -1) {\r
+                                                statusText = getTitleTranslation(1);\r
+                                        } else if(el.className.search(/today-but/) != -1 && el.className.search(/disabled/) == -1) {\r
+                                                statusText = getTitleTranslation(12);\r
+                                        };\r
+                                        break;\r
+                                default:\r
+                                        statusText = "";\r
+                                };\r
+                                while(el.parentNode) {\r
+                                        el = el.parentNode;\r
+                                        if(el.nodeType == 1 && el.tagName.toLowerCase() == "tr") {\r
+                                                if(el == o.currentTR) break;\r
+                                                if(o.currentTR) {\r
+                                                        o.currentTR.className = o.currentTR.className.replace('dp-row-highlight', '');\r
+                                                };\r
+                                                el.className = el.className + " dp-row-highlight";\r
+                                                o.currentTR = el;\r
+                                                break;\r
+                                        };\r
+                                };                                                          \r
+                                if(o.statusBar && statusText) { o.updateStatus(statusText); };\r
+                        },\r
+                        onclick: function(e) {                                                  \r
+                                if(o.opacity != o.opacityTo || this.className.search(/date-picker-unused|out-of-range|day-disabled|no-selection/) != -1) return false;\r
+                                e = e || document.parentWindow.event;\r
+                                var el = e.target != null ? e.target : e.srcElement;\r
+                                while (el.nodeType != 1 || (el.tagName && el.tagName != "TD")) el = el.parentNode;\r
+                                var cellDate = el.className.match(/cd-([0-9]{8})/)[1];                                                                                                                                                                           \r
+                                o.date = new Date(cellDate.substr(0,4),cellDate.substr(4,2)-1,cellDate.substr(6,2));\r
+                                o.dateSet = new Date(o.date);                                 \r
+                                o.returnFormattedDate();\r
+                                if(!o.staticPos) { o.hide(); }\r
+                                else { o.updateTable();};\r
+                                o.stopTimer();\r
+                                return stopEvent(e);\r
+                        },\r
+                        incDec: function(e) {                            \r
+                                e = e || document.parentWindow.event;\r
+                                var el = e.target != null ? e.target : e.srcElement;\r
+                                if(el && el.className && el.className.search('fd-disabled') != -1) { return false; }                                \r
+                                o.timerInc      = 800;\r
+                                o.dayInc        = arguments[1];\r
+                                o.yearInc       = arguments[2];\r
+                                o.monthInc      = arguments[3];                         \r
+                                o.timerSet      = true;                                                \r
+                       \r
+                                o.updateTable();\r
+                                return true;\r
+                        },\r
+                        clearTimer: function(e) {\r
+                                o.stopTimer();\r
+                                o.timerInc      = 800;\r
+                                o.yearInc       = 0;\r
+                                o.monthInc      = 0;\r
+                                o.dayInc        = 0;\r
+                                removeEvent(document, "mouseup", o.events.clearTimer);\r
+                        }\r
+                };\r
+        \r
+                this.setFormElementEvents = function() {\r
+                        var elem = this.getElem();\r
+                        if(elem && elem.tagName.search(/select|input/i) != -1) {                                         \r
+                                addEvent(elem, "change", o.changeHandler);\r
+                                if(this.splitDate) {                                                                         \r
+                                        addEvent(document.getElementById(this.id + splitAppend[1]), "change", o.changeHandler);\r
+                                        addEvent(document.getElementById(this.id + splitAppend[0]), "change", o.changeHandler);\r
+                                };\r
+                        };\r
+                };                 \r
+                \r
+                var o = this;\r
+                \r
+                o.setFormElementEvents();\r
+                \r
+                if(this.staticPos) { this.create(); this.setDateFromInput(); }\r
+                else { \r
+                        this.createButton();\r
+                        this.setDateFromInput();                         \r
+                };\r
+        };\r
+        datePicker.prototype.createButton = function() {\r
+                \r
+                if(this.staticPos || document.getElementById("fd-but-" + this.id)) { return; };\r
+\r
+                var inp         = this.getElem(),\r
+                    span        = document.createElement('span'),\r
+                    but         = document.createElement('a');\r
+\r
+                but.href        = "#";\r
+                but.className   = "date-picker-control";\r
+                but.title       = getTitleTranslation(5);\r
+                but.id          = "fd-but-" + this.id;\r
+\r
+                span.appendChild(document.createTextNode(nbsp));\r
+                but.appendChild(span);\r
+\r
+                if(this.buttonWrapper && document.getElementById(this.buttonWrapper)) {\r
+                        document.getElementById(this.buttonWrapper).appendChild(but);\r
+                } else if(inp.nextSibling) {\r
+                        inp.parentNode.insertBefore(but, inp.nextSibling);\r
+                } else {\r
+                        inp.parentNode.appendChild(but);\r
+                };                   \r
+\r
+                but.onclick = but.onpress = function(e) {\r
+                        e = e || window.event;                      \r
+                \r
+                        var inpId     = this.id.replace('fd-but-',''),\r
+                            dpVisible = isVisible(inpId);  \r
+                \r
+                        if(e.type == "press") {\r
+                                var kc = e.keyCode != null ? e.keyCode : e.charCode;\r
+                                if(kc != 13) return true; \r
+                                if(dpVisible) {\r
+                                        this.className = this.className.replace("dp-button-active", "");\r
+                                        datePickerController.hideAll();\r
+                                        return false;\r
+                                };\r
+                        };\r
+\r
+                        this.className = this.className.replace("dp-button-active", "");\r
+                        \r
+                        if(!dpVisible) {\r
+                                this.className += " dp-button-active";\r
+                                hideAll(inpId);\r
+                                showDatePicker(inpId);\r
+                        } else {\r
+                                hideAll();\r
+                        };\r
+                \r
+                        return false;\r
+                };\r
+        \r
+                but = null;\r
+        };  \r
+        datePicker.prototype.setRangeLow = function(range) {\r
+                this.low = (String(range).search(/^(\d\d\d\d)(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])$/) == -1) ? false : range;                \r
+                if(this.created) { this.updateTable(); };\r
+        };\r
+        datePicker.prototype.setRangeHigh = function(range) {\r
+                this.high = (String(range).search(/^(\d\d\d\d)(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])$/) == -1) ? false : range;                \r
+                if(this.created) { this.updateTable(); };\r
+        };\r
+        datePicker.prototype.setDisabledDays = function(dayArray) {\r
+                this.disabledDays = dayArray;\r
+                if(this.created) { this.updateTable(); };\r
+        };\r
+        datePicker.prototype.setDisabledDates = function(dateArray) {                \r
+                this.disabledDates = {};\r
+                this.addDisabledDates(dateArray);                \r
+        }; \r
+        datePicker.prototype.addDisabledDates = function(dateArray) {\r
+                var disabledDateObj = {};\r
+                if(typeof dateArray !== "object") dateArray = [dateArray];                \r
+                for(var i = dateArray.length; i-- ;) {\r
+                        if(dateArray[i].match(/^(\d\d\d\d|\*\*\*\*)(0[1-9]|1[012]|\*\*)(0[1-9]|[12][0-9]|3[01])$/) != -1) {\r
+                                this.disabledDates[dateArray[i]] = 1;\r
+                        };\r
+                }; \r
+                if(this.created) { this.updateTable(); };                                  \r
+        };\r
+        datePicker.prototype.addKeyboardEvents = function() {\r
+                addEvent(document, "keypress", this.events.onkeydown);\r
+                /*@cc_on\r
+                @if(@_win32)\r
+                removeEvent(document, "keypress", this.events.onkeydown);\r
+                addEvent(document, "keydown", this.events.onkeydown);\r
+                @end\r
+                @*/\r
+                if(window.devicePixelRatio) {\r
+                        removeEvent(document, "keypress", this.events.onkeydown);\r
+                        addEvent(document, "keydown", this.events.onkeydown);\r
+                };\r
+        };  \r
+        datePicker.prototype.removeKeyboardEvents = function() {\r
+                removeEvent(document, "keypress", this.events.onkeydown);\r
+                removeEvent(document, "keydown",  this.events.onkeydown);\r
+        };\r
+        datePicker.prototype.removeHighlight = function() {\r
+                var el = document.getElementById(this.id+"-date-picker-hover");\r
+                if(el) {\r
+                        el.className = el.className.replace("date-picker-hover", "");\r
+                        el.id = "";                                                                \r
+                };\r
+        };\r
+        datePicker.prototype.stopTimer = function() {\r
+                this.timerSet = false;\r
+                window.clearTimeout(this.timer);\r
+        };\r
+        datePicker.prototype.setOpacity = function(op) {\r
+                this.div.style.opacity = op/100;\r
+                this.div.style.filter = 'alpha(opacity=' + op + ')';\r
+                this.opacity = op;\r
+        };         \r
+        datePicker.prototype.getElem = function() {\r
+                return document.getElementById(this.id.replace(/^fd-/, '')) || false;\r
+        };\r
+        datePicker.prototype.getDisabledDates = function(y, m) {\r
+                m = pad(m);                 \r
+                \r
+                var obj = {},            \r
+                    lower  = this.firstDateShown,\r
+                    upper  = this.lastDateShown,             \r
+                    dt1, dt2, rngLower, rngUpper;  \r
+                \r
+                if(!upper || !lower) {\r
+                        lower = this.firstDateShown = y + pad(m) + "01";\r
+                        upper = this.lastDateShown  = y + pad(m) + pad(daysInMonth(m, y));                        \r
+                };\r
+                \r
+                for(var dt in this.disabledDates) {                            \r
+                        dt1 = dt.replace(/^(\*\*\*\*)/, y).replace(/^(\d\d\d\d)(\*\*)/, "$1"+m);\r
+                        dt2 = this.disabledDates[dt];\r
+\r
+                        if(dt2 == 1) {                                 \r
+                                if(+lower <= +dt1 && +upper >= +dt1) {\r
+                                        obj[dt1] = 1;                                         \r
+                                };\r
+                                continue;\r
+                        };\r
+\r
+                        // Range of disabled dates                        \r
+                        if(Number(dt1.substr(0,6)) <= +String(this.firstDateShown).substr(0,6) && Number(dt2.substr(0,6)) >= +String(this.lastDateShown).substr(0,6)) {\r
+                                // Same month\r
+                                if(Number(dt1.substr(0,6)) == Number(dt2.substr(0,6))) {\r
+                                        for(var i = dt1; i <= dt2; i++) {\r
+                                                obj[i] = 1;\r
+                                        };\r
+                                        continue;\r
+                                };\r
+\r
+                                // Different months but we only want this month\r
+                                rngLower = Number(dt1.substr(0,6)) == +String(this.firstDateShown).substr(0,6) ? dt1 : lower;\r
+                                rngUpper = Number(dt2.substr(0,6)) == +String(this.lastDateShown).substr(0,6) ? dt2 : upper;\r
+                                for(var i = +rngLower; i <= +rngUpper; i++) {\r
+                                        obj[i] = 1;                                        \r
+                                };\r
+                        };\r
+                };\r
+                \r
+                for(dt in this.enabledDates) {\r
+                        dt1 = dt.replace(/^(\*\*\*\*)/, y).replace(/^(\d\d\d\d)(\*\*)/, "$1"+m);\r
+                        dt2 = this.enabledDates[dt];\r
+\r
+                        if(dt2 == 1) {\r
+                                if(dt1 in obj) {                                          \r
+                                        obj[dt1] = null;\r
+                                        delete obj[dt1];\r
+                                };\r
+                                continue;\r
+                        };\r
+\r
+                        // Range\r
+                        if(Number(dt1.substr(0,6)) <= +String(this.firstDateShown).substr(0,6) && Number(dt2.substr(0,6)) >= +String(this.lastDateShown).substr(0,6)) {\r
+                                // Same month\r
+                                if(Number(dt1.substr(0,6)) == Number(dt2.substr(0,6))) {\r
+                                        for(var i = dt1; i <= dt2; i++) {\r
+                                                if(i in obj) {\r
+                                                        obj[i] = null;\r
+                                                        delete obj[i];\r
+                                                };\r
+                                        };\r
+                                        continue;\r
+                                };\r
+\r
+                                // Different months but we only want this month\r
+                                rngLower = Number(dt1.substr(0,6)) == +String(this.firstDateShown).substr(0,6) ? dt1 : lower;\r
+                                rngUpper = Number(dt2.substr(0,6)) == +String(this.lastDateShown).substr(0,6) ? dt2 : upper;\r
+                                for(var i = +rngLower; i <= +rngUpper; i++) {\r
+                                        if(i in obj) {\r
+                                                obj[i] = null;\r
+                                                delete obj[i];\r
+                                        };\r
+                                };\r
+                        };\r
+                };\r
+                return obj;\r
+        };\r
+        datePicker.prototype.truePosition = function(element) {\r
+                var pos = this.cumulativeOffset(element);\r
+                if(window.opera) { return pos; };\r
+                var iebody      = (document.compatMode && document.compatMode != "BackCompat")? document.documentElement : document.body,\r
+                    dsocleft    = document.all ? iebody.scrollLeft : window.pageXOffset,\r
+                    dsoctop     = document.all ? iebody.scrollTop  : window.pageYOffset,\r
+                    posReal     = this.realOffset(element);\r
+                return [pos[0] - posReal[0] + dsocleft, pos[1] - posReal[1] + dsoctop];\r
+        };\r
+        datePicker.prototype.realOffset = function(element) {\r
+                var t = 0, l = 0;\r
+                do {\r
+                        t += element.scrollTop  || 0;\r
+                        l += element.scrollLeft || 0;\r
+                        element = element.parentNode;\r
+                } while(element);\r
+                return [l, t];\r
+        };\r
+        datePicker.prototype.cumulativeOffset = function(element) {\r
+                var t = 0, l = 0;\r
+                do {\r
+                        t += element.offsetTop  || 0;\r
+                        l += element.offsetLeft || 0;\r
+                        element = element.offsetParent;\r
+                } while(element);\r
+                return [l, t];\r
+        };\r
+        datePicker.prototype.equaliseDates = function() {\r
+                var clearDayFound = false, tmpDate;\r
+                for(var i = this.low; i <= this.high; i++) {\r
+                        tmpDate = String(i);\r
+                        if(!this.disabledDays[new Date(tmpDate.substr(0,4), tmpDate.substr(6,2), tmpDate.substr(4,2)).getDay() - 1]) {\r
+                                clearDayFound = true;\r
+                                break;\r
+                        };\r
+                };\r
+                if(!clearDayFound) { this.disabledDays = [0,0,0,0,0,0,0] };\r
+        };\r
+        datePicker.prototype.outOfRange = function(tmpDate) {\r
+                if(!this.low && !this.high) { return false; };\r
+\r
+                var level = false;\r
+                if(!tmpDate) {\r
+                        level   = true;\r
+                        tmpDate = this.date;\r
+                };\r
+\r
+                var d  = pad(tmpDate.getDate()),\r
+                    m  = pad(tmpDate.getMonth() + 1),\r
+                    y  = tmpDate.getFullYear(),\r
+                    dt = String(y)+String(m)+String(d);\r
+\r
+                if(this.low && +dt < +this.low) {\r
+                        if(!level) return true;\r
+                        this.date = new Date(this.low.substr(0,4), this.low.substr(4,2)-1, this.low.substr(6,2), 5, 0, 0);\r
+                        return false;\r
+                };\r
+                if(this.high && +dt > +this.high) {\r
+                        if(!level) return true;\r
+                        this.date = new Date(this.high.substr(0,4), this.high.substr(4,2)-1, this.high.substr(6,2), 5, 0, 0);\r
+                };\r
+                return false;\r
+        };         \r
+        datePicker.prototype.updateStatus = function(msg) {\r
+                while(this.statusBar.firstChild) { this.statusBar.removeChild(this.statusBar.firstChild); };\r
+                if(msg && this.statusFormat.search(/-S|S-/) != -1) {\r
+                        msg = msg.replace(/([0-9]{1,2})(st|nd|rd|th)/, "$1<sup>$2</sup>");\r
+                        msg = msg.split(/<sup>|<\/sup>/);\r
+                        var dc = document.createDocumentFragment();\r
+                        for(var i = 0, nd; nd = msg[i]; i++) {\r
+                                if(/^(st|nd|rd|th)$/.test(nd)) {\r
+                                        var sup = document.createElement("sup");\r
+                                        sup.appendChild(document.createTextNode(nd));\r
+                                        dc.appendChild(sup);\r
+                                } else {\r
+                                        dc.appendChild(document.createTextNode(nd));\r
+                                };\r
+                        };\r
+                        this.statusBar.appendChild(dc);\r
+                } else {\r
+                        this.statusBar.appendChild(document.createTextNode(msg ? msg : getTitleTranslation(9)));\r
+                };\r
+        };\r
+        datePicker.prototype.setDateFromInput = function() {\r
+                this.dateSet = null;\r
+\r
+                var elem = this.getElem(), \r
+                    upd  = false, \r
+                    dt;\r
+                    \r
+                if(!elem || elem.tagName.search(/select|input/i) == -1) return; \r
+\r
+                if(!this.splitDate && elem.value.replace(/\s/g, "") !== "") {\r
+                        var dynFormatMasks = formatMasks.concat([this.format]).reverse();                                                \r
+                        for(var i = 0, fmt; fmt = dynFormatMasks[i]; i++) {\r
+                                dt = parseDateString(elem.value, fmt);                                                              \r
+                                if(dt) {                                    \r
+                                        upd = true;                                       \r
+                                        break;\r
+                                };\r
+                        };                                                                        \r
+                } else if(this.splitDate) {\r
+                        var mmN  = document.getElementById(this.id + splitAppend[1]),\r
+                            ddN  = document.getElementById(this.id + splitAppend[0]),\r
+                            tm   = parseInt(mmN.tagName.toLowerCase() == "input"  ? mmN.value  : mmN.options[mmN.selectedIndex || 0].value, 10),\r
+                            td   = parseInt(ddN.tagName.toLowerCase() == "input"  ? ddN.value  : ddN.options[ddN.selectedIndex || 0].value, 10),\r
+                            ty   = parseInt(elem.tagName.toLowerCase() == "input" ? elem.value : elem.options[elem.selectedIndex || 0].value, 10);\r
+                                             \r
+                        if(!(/\d\d\d\d/.test(ty)) || !(/^(0?[1-9]|1[012])$/.test(tm)) || !(/^(0?[1-9]|[12][0-9]|3[01])$/.test(td))) {\r
+                                dt = false;\r
+                        } else {\r
+                                if(+td > daysInMonth(+tm - 1, +ty)) {                                         \r
+                                        upd = true;\r
+                                        td  = daysInMonth(+tm - 1, +ty); \r
+                                        dt  = new Date(ty,tm-1,td);\r
+                                } else {\r
+                                        dt = new Date(ty,tm-1,td);\r
+                                };\r
+                        };                        \r
+                };\r
+\r
+                if(!dt || isNaN(dt)) {                                                              \r
+                        this.date = new Date();\r
+                        this.date.setHours(5);\r
+                        this.outOfRange();\r
+                        return;\r
+                };\r
+\r
+                dt.setHours(5);\r
+                this.date = new Date(dt);                            \r
+                this.outOfRange();                 \r
+                \r
+                var dtYYYYMMDD = dt.getFullYear() + pad(dt.getMonth() + 1) + pad(dt.getDate()),\r
+                    weekDay    = ( dt.getDay() + 6 ) % 7;\r
+                \r
+                if(dt.getTime() == this.date.getTime() && !(dtYYYYMMDD in this.dynDisabledDates || this.disabledDays[weekDay])) {                        \r
+                        this.dateSet = new Date(this.date);\r
+                };\r
+                \r
+                if(upd) { this.returnFormattedDate(); };\r
+        };\r
+        datePicker.prototype.setSelectIndex = function(elem, indx) {\r
+                for(var opt = elem.options.length-1; opt >= 0; opt--) {\r
+                        if(elem.options[opt].value == +indx) {\r
+                                elem.selectedIndex = opt;\r
+                                return;\r
+                        };\r
+                };\r
+        };\r
+        datePicker.prototype.returnFormattedDate = function() {\r
+                \r
+                var elem = this.getElem();\r
+                if(!elem) return;\r
+\r
+                var d                   = pad(this.date.getDate()),\r
+                    m                   = pad(this.date.getMonth() + 1),\r
+                    yyyy                = this.date.getFullYear(),\r
+                    disabledDates       = this.getDisabledDates(+yyyy, +m),\r
+                    weekDay             = (this.date.getDay() + 6) % 7;\r
+                \r
+                if(!(this.disabledDays[weekDay] || String(yyyy)+m+d in this.disabledDates)) {\r
+                        if(this.splitDate) {\r
+                                var ddE = document.getElementById(this.id+splitAppend[0]),\r
+                                    mmE = document.getElementById(this.id+splitAppend[1]);\r
+                                    \r
+                                if(ddE.tagName.toLowerCase() == "input") { ddE.value = d; }\r
+                                else { this.setSelectIndex(ddE, d); };\r
+                                if(mmE.tagName.toLowerCase() == "input") { mmE.value = m; }\r
+                                else { this.setSelectIndex(mmE, m); };\r
+                                if(elem.tagName.toLowerCase() == "input") elem.value = yyyy;\r
+                                else { this.setSelectIndex(elem, yyyy); };\r
+                                \r
+                        } else if(elem.tagName.toLowerCase() == "input") {                                                                \r
+                                elem.value = printFormattedDate(this.date, this.format);                                \r
+                        };\r
+                        \r
+                        if(elem.type && elem.type != "hidden") { elem.focus(); }                         \r
+                                                                  \r
+                        this.callback("dateselect", { "id":this.id, "date":this.dateSet, "dd":d, "mm":m, "yyyy":yyyy });                        \r
+                        \r
+                        if(this.staticPos) { this.updateTable(); };                                 \r
+                };                        \r
+        };\r
+        datePicker.prototype.disableTodayButton = function() {\r
+                var today = new Date();                     \r
+                this.butToday.className = this.butToday.className.replace("fd-disabled", "");\r
+                if(this.outOfRange(today) || (this.date.getDate() == today.getDate() && this.date.getMonth() == today.getMonth() && this.date.getFullYear() == today.getFullYear())) {\r
+                        this.butToday.className += " fd-disabled";\r
+                        this.butToday.onclick = null;\r
+                } else {\r
+                        this.butToday.onclick = this.events.gotoToday;\r
+                };\r
+        };\r
+        datePicker.prototype.updateTableHeaders = function() {\r
+                var colspanTotal = this.showWeeks ? 8 : 7,\r
+                    colOffset    = this.showWeeks ? 1 : 0,\r
+                    d, but;\r
+\r
+                for(var col = colOffset; col < colspanTotal; col++ ) {\r
+                        d = (this.firstDayOfWeek + (col - colOffset)) % 7;\r
+                        this.ths[col].title = getDayTranslation(d, false);\r
+\r
+                        if(col > colOffset) {\r
+                                but = this.ths[col].getElementsByTagName("span")[0];\r
+                                while(but.firstChild) { but.removeChild(but.firstChild); };\r
+                                but.appendChild(document.createTextNode(getDayTranslation(d, true)));\r
+                                but.title = this.ths[col].title;\r
+                                but.className = but.className.replace(/day-([0-6])/, "") + " day-" + d;\r
+                                but = null;\r
+                        } else {\r
+                                while(this.ths[col].firstChild) { this.ths[col].removeChild(this.ths[col].firstChild); };\r
+                                this.ths[col].appendChild(document.createTextNode(getDayTranslation(d, true)));\r
+                        };\r
+\r
+                        this.ths[col].className = this.ths[col].className.replace(/date-picker-highlight/g, "");\r
+                        if(this.highlightDays[d]) {\r
+                                this.ths[col].className += " date-picker-highlight";\r
+                        };\r
+                };\r
+                \r
+                if(this.created) { this.updateTable(); }\r
+        };\r
+\r
+        datePicker.prototype.callback = function(type, args) {                                                     \r
+                if(!type || !(type in this.callbacks)) return false;\r
+                \r
+                var ret = false;                   \r
+                for(var func = 0; func < this.callbacks[type].length; func++) {                         \r
+                        ret = this.callbacks[type][func](args || this.id);\r
+                        if(!ret) return false;\r
+                };                      \r
+                return ret;\r
+        };\r
+        \r
+        datePicker.prototype.showHideButtons = function(tmpDate) {\r
+                var tdm = tmpDate.getMonth(),\r
+                    tdy = tmpDate.getFullYear();\r
+\r
+                this.butPrevYear.className = this.butPrevYear.className.replace("fd-disabled", "");\r
+                if(this.outOfRange(new Date((tdy - 1), tdm, daysInMonth(+tdm, tdy-1)))) {\r
+                        this.butPrevYear.className += " fd-disabled";\r
+                        if(this.yearInc == -1) this.stopTimer();\r
+                };    \r
+                \r
+                this.butPrevMonth.className = this.butPrevMonth.className.replace("fd-disabled", "");\r
+                if(this.outOfRange(new Date(tdy, (+tdm - 1), daysInMonth(+tdm-1, tdy)))) {\r
+                        this.butPrevMonth.className += " fd-disabled";\r
+                        if(this.monthInc == -1) this.stopTimer();\r
+                };\r
+         \r
+                this.butNextYear.className = this.butNextYear.className.replace("fd-disabled", "");\r
+                if(this.outOfRange(new Date((tdy + 1), +tdm, 1))) {\r
+                        this.butNextYear.className += " fd-disabled";\r
+                        if(this.yearInc == 1) this.stopTimer();\r
+                };\r
+                \r
+                this.butNextMonth.className = this.butNextMonth.className.replace("fd-disabled", "");\r
+                if(this.outOfRange(new Date(tdy, +tdm + 1, 1))) {\r
+                        this.butNextMonth.className += " fd-disabled";\r
+                        if(this.monthInc == 1) this.stopTimer();\r
+                };\r
+        };        \r
+        var localeDefaults = {\r
+                fullMonths:["January","February","March","April","May","June","July","August","September","October","November","December"],\r
+                monthAbbrs:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],\r
+                fullDays:  ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],\r
+                dayAbbrs:  ["Mon","Tue","Wed","Thu","Fri","Sat","Sun"],\r
+                titles:    ["Previous month","Next month","Previous year","Next year", "Today", "Show Calendar", "wk", "Week [[%0%]] of [[%1%]]", "Week", "Select a date", "Click \u0026 Drag to move", "Display \u201C[[%0%]]\u201D first", "Go to Today\u2019s date"],\r
+                imported:  false\r
+        };        \r
+        var grepRangeLimits = function(sel) {\r
+                var range = [];\r
+                for(var i = 0; i < sel.options.length; i++) {\r
+                        if(sel.options[i].value.search(/^\d\d\d\d$/) == -1) { continue; };\r
+                        if(!range[0] || Number(sel.options[i].value) < range[0]) { range[0] = Number(sel.options[i].value); };\r
+                        if(!range[1] || Number(sel.options[i].value) > range[1]) { range[1] = Number(sel.options[i].value); };\r
+                };\r
+                return range;\r
+        };\r
+        var joinNodeLists = function() {\r
+                if(!arguments.length) { return []; }\r
+                var nodeList = [];\r
+                for (var i = 0; i < arguments.length; i++) {\r
+                        for (var j = 0, item; item = arguments[i][j]; j++) {\r
+                                nodeList[nodeList.length] = item;\r
+                        };\r
+                };\r
+                return nodeList;\r
+        };\r
+        var cleanUp = function() {\r
+                var dp;\r
+                for(dp in datePickers) {\r
+                        if(!document.getElementById(datePickers[dp].id)) {\r
+                                if(datePickers[dp].created) datePickers[dp].destroy();\r
+                                datePickers[dp] = null;\r
+                                delete datePickers[dp];\r
+                        };\r
+                };\r
+        };         \r
+        var hideAll = function(exception) {\r
+                var dp;\r
+                for(dp in datePickers) {\r
+                        if(!datePickers[dp].created || datePickers[dp].staticPos || (exception && exception == datePickers[dp].id)) continue;\r
+                        datePickers[dp].hide();\r
+                };\r
+        };\r
+        var showDatePicker = function(inpID) {\r
+                if(!(inpID in datePickers)) return false;                 \r
+                datePickers[inpID].show();\r
+                return true;        \r
+        };\r
+        var destroy = function() {\r
+                for(dp in datePickers) {\r
+                        if(datePickers[dp].created) datePickers[dp].destroy();\r
+                        datePickers[dp] = null;\r
+                        delete datePickers[dp];\r
+                };\r
+                datePickers = null;\r
+                removeEvent(window, 'load',   datePickerController.create);\r
+                removeEvent(window, 'unload', datePickerController.destroy);\r
+        }; \r
+        var getTitleTranslation = function(num, replacements) {\r
+                replacements = replacements || [];\r
+                if(localeImport.titles.length > num) {\r
+                         var txt = localeImport.titles[num];\r
+                         if(replacements && replacements.length) {\r
+                                for(var i = 0; i < replacements.length; i++) {\r
+                                        txt = txt.replace("[[%" + i + "%]]", replacements[i]);\r
+                                };\r
+                         };\r
+                         return txt.replace(/[[%(\d)%]]/g,"");\r
+                };\r
+                return "";\r
+        };\r
+        var getDayTranslation = function(day, abbreviation) {\r
+                var titles = localeImport[abbreviation ? "dayAbbrs" : "fullDays"];\r
+                return titles.length && titles.length > day ? titles[day] : "";\r
+        };\r
+        var getMonthTranslation = function(month, abbreviation) {\r
+                var titles = localeImport[abbreviation ? "monthAbbrs" : "fullMonths"];\r
+                return titles.length && titles.length > month ? titles[month] : "";\r
+        };\r
+        var daysInMonth = function(nMonth, nYear) {\r
+                nMonth = (nMonth + 12) % 12;\r
+                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];\r
+        };\r
+        var getWeeksInYear = function(Y) {\r
+                if(Y in weeksInYearCache) {\r
+                        return weeksInYearCache[Y];\r
+                };\r
+                var X1, X2, NW;\r
+                with (X1 = new Date(Y, 0, 4)) {\r
+                        setDate(getDate() - (6 + getDay()) % 7);\r
+                };\r
+                with (X2 = new Date(Y, 11, 28)) {\r
+                        setDate(getDate() + (7 - getDay()) % 7);\r
+                };\r
+                weeksInYearCache[Y] = Math.round((X2 - X1) / 604800000);\r
+                return weeksInYearCache[Y];\r
+        };\r
+        var parseRangeFromString = function(str) {\r
+                if(!str) return "";\r
+                \r
+                var low = str.search(/^range-low-/) != -1;\r
+                str = str.replace(/range-(low|high)-/, "");\r
+\r
+                if(str.search(/^(\d\d\d\d)(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])$/) != -1) { return str; };\r
+\r
+                var tmpDate = new Date();\r
+                \r
+                if(str.search(/^today$/) != -1) { return tmpDate.getFullYear() + pad(tmpDate.getMonth() + 1) + pad(tmpDate.getDate()); };\r
+                \r
+                var regExp = /^(\d)-(day|week|month|year)$/;\r
+                \r
+                if(str.search(regExp) != -1) {\r
+                        var parts       = str.match(regExp),\r
+                            acc         = { day:0,week:0,month:0,year:0 };\r
+                            \r
+                        acc[parts[2]]   = low ? -(+parts[1]) : +parts[1];\r
+                        tmpDate.setFullYear(tmpDate.getFullYear() + +acc.year);\r
+                        tmpDate.setMonth(tmpDate.getMonth() + +acc.month);\r
+                        tmpDate.setDate(tmpDate.getDate() + +acc.day + (7 * +acc.week));\r
+                        return !tmpDate || isNaN(tmpDate) ? "" : tmpDate.getFullYear() + pad(tmpDate.getMonth() + 1) + pad(tmpDate.getDate());\r
+                };\r
+                \r
+                return "";\r
+        };\r
+        var getWeekNumber = function(y,m,d) {\r
+                var d = new Date(y, m, d, 0, 0, 0);\r
+                var DoW = d.getDay();\r
+                d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu\r
+                var ms = d.valueOf(); // GMT\r
+                d.setMonth(0);\r
+                d.setDate(4); // Thu in Week 1\r
+                return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1;\r
+        };\r
+        var printFormattedDate = function(date, fmt, useImportedLocale) {\r
+                if(!date || isNaN(date)) { return ""; };\r
+                \r
+                var parts = fmt.split("-"),\r
+                      str = [],\r
+                        d = date.getDate(),\r
+                        D = date.getDay(),\r
+                        m = date.getMonth(),\r
+                        y = date.getFullYear(),\r
+                    flags = {\r
+                                "sp":" ",\r
+                                "dt":".",\r
+                                "sl":"/",\r
+                                "ds":"-",\r
+                                "cc":",",\r
+                                "d":pad(d),\r
+                                "D":useImportedLocale ? localeImport.dayAbbrs[D == 0 ? 6 : D - 1] : localeDefaults.dayAbbrs[D == 0 ? 6 : D - 1],\r
+                                "l":useImportedLocale ? localeImport.fullDays[D == 0 ? 6 : D - 1] : localeDefaults.fullDays[D == 0 ? 6 : D - 1],\r
+                                "j":d,\r
+                                "N":D == 0 ? 7 : D,\r
+                                "w":D,\r
+                                /*"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)],*/\r
+                                "z":"?",\r
+                                "W":getWeekNumber(date),\r
+                                "M":useImportedLocale ? localeImport.monthAbbrs[m] : localeDefaults.monthAbbrs[m],\r
+                                "F":useImportedLocale ? localeImport.fullMonths[m] : localeDefaults.fullMonths[m],\r
+                                "m":pad(++m),\r
+                                "n":++m,\r
+                                "t":daysInMonth(++m, y),\r
+                                "Y":y,\r
+                                "o":y,\r
+                                "y":String(y).substr(2,2),\r
+                                "S":["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]\r
+                            };\r
+\r
+                for(var pt = 0, part; part = parts[pt]; pt++) {                        \r
+                        str.push(!(part in flags) ? "" : flags[part]);\r
+                };\r
+\r
+                return str.join("");\r
+        };\r
+        var parseDateString = function(str, fmt) {\r
+                var d     = false,\r
+                    m     = false,\r
+                    y     = false,\r
+                    now   = new Date(),\r
+                    parts = fmt.replace(/-sp(-sp)+/g, "-sp").split("-"),\r
+                    divds = { "dt":".","sl":"/","ds":"-","cc":"," };                    \r
+\r
+                loopLabel:\r
+                for(var pt = 0, part; part = parts[pt]; pt++) {                        \r
+                        if(str.length == 0) { return false; };\r
+                                \r
+                        switch(part) {\r
+                                // Dividers\r
+                                case "sp": // Space " "\r
+                                                if(str.charAt(0).search(/\s/) != -1) {\r
+                                                        // Be easy on multiple spaces...\r
+                                                        while(str.charAt(0).search(/\s/) != -1) { str = str.substr(1); };\r
+                                                        break;\r
+                                                } else return "";\r
+                                case "dt":\r
+                                case "sl":\r
+                                case "ds":\r
+                                case "cc":\r
+                                                if(str.charAt(0) == divds[part]) {\r
+                                                        str = str.substr(1);\r
+                                                        break;\r
+                                                } else return "";\r
+                                // DAY\r
+                                case "d": // Day of the month, 2 digits with leading zeros (01 - 31)\r
+                                case "j": // Day of the month without leading zeros (1 - 31)  \r
+                                          // Accept both when parsing                                                          \r
+                                                if(str.search(/^(3[01]|[12][0-9]|0?[1-9])/) != -1) {\r
+                                                        d = +str.match(/^(3[01]|[12][0-9]|0?[1-9])/)[0];\r
+                                                        str = str.substr(str.match(/^(3[01]|[12][0-9]|0?[1-9])/)[0].length);                                                        \r
+                                                        break;\r
+                                                } else return "";\r
+                                                \r
+                                case "D": // A textual representation of a day, three letters (Mon - Sun)\r
+                                case "l": // A full textual representation of the day of the week (Monday - Sunday)\r
+                                                l = part == "D" ? localeDefaults.dayAbbrs : localeDefaults.fullDays;\r
+                                                for(var i = 0; i < 7; i++) {\r
+                                                        if(new RegExp("^" + l[i], "i").test(str)) {\r
+                                                                str = str.substr(l[i].length);\r
+                                                                continue loopLabel;\r
+                                                        };\r
+                                                };\r
+                                                return "";\r
+                                /*\r
+                                case "j": // Day of the month without leading zeros (1 - 31)\r
+                                                if(str.search(/^([1-9]|[12][0-9]|3[01])/) != -1) {\r
+                                                        d = +str.match(/^([1-9]|[12][0-9]|3[01])/)[0];\r
+                                                        str = str.substr(str.match(/^(\s?[1-9]|[12][0-9]|3[01])/)[0].length);\r
+                                                        break;\r
+                                                } else return "";\r
+                                */\r
+                                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)\r
+                                case "w": // Numeric representation of the day of the week 0 (for Sunday) through 6 (for Saturday)\r
+                                                if(str.search(part == "N" ? /^([1-7])/ : /^([0-6])/) != -1) {\r
+                                                        str = str.substr(1);\r
+                                                        break;\r
+                                                } else return "";\r
+                                case "S": // English ordinal suffix for the day of the month, 2 characters: st, nd, rd or th\r
+                                                if(str.search(/^(st|nd|rd|th)/i) != -1) {\r
+                                                        str = str.substr(2);\r
+                                                        break;\r
+                                                } else return "";\r
+                                case "z": // The day of the year (starting from 0): 0 - 365\r
+                                                if(str.search(/^([0-9]|[1-9][0-9]|[12][0-9]{2}|3[0-5][0-9]|36[0-5])/) != -1) {\r
+                                                        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);\r
+                                                        break;\r
+                                                } else return "";\r
+                                // WEEK\r
+                                case "W": // ISO-8601 week number of year, weeks starting on Monday (added in PHP 4.1.0): 1 - 53\r
+                                                if(str.search(/^([1-9]|[1234[0-9]|5[0-3])/) != -1) {\r
+                                                        str = str.substr(str.match(/^([1-9]|[1234[0-9]|5[0-3])/)[0].length);\r
+                                                        break;\r
+                                                } else return "";\r
+                                // MONTH\r
+                                case "M": // A short textual representation of a month, three letters\r
+                                case "F": // A full textual representation of a month, such as January or March\r
+                                                l = localeDefaults.fullMonths.concat(localeDefaults.monthAbbrs); // : localeDefaults.fullMonths;\r
+                                                for(var i = 0; i < 24; i++) {\r
+                                                        if(str.search(new RegExp("^" + l[i],"i")) != -1) {\r
+                                                                str = str.substr(l[i].length);\r
+                                                                m = ((i + 12) % 12);                                                                 \r
+                                                                continue loopLabel;\r
+                                                        };\r
+                                                };\r
+                                                return "";\r
+                                case "m": // Numeric representation of a month, with leading zeros\r
+                                case "n": // Numeric representation of a month, without leading zeros\r
+                                                //l = part == "m" ? /^(0[1-9]|1[012])/ : /^([1-9]|1[012])/;\r
+                                                // Accept either when parsing\r
+                                                l = /^(1[012]|0?[1-9])/;\r
+                                                if(str.search(l) != -1) {\r
+                                                        m = +str.match(l)[0] - 1;\r
+                                                        str = str.substr(str.match(l)[0].length);\r
+                                                        break;\r
+                                                } else return "";\r
+                                case "t": // Number of days in the given month: 28 through 31\r
+                                                if(str.search(/2[89]|3[01]/) != -1) {\r
+                                                        str = str.substr(2);\r
+                                                        break;\r
+                                                } else return "";\r
+                                // YEAR\r
+                                case "Y": // A full numeric representation of a year, 4 digits\r
+                                case "o": // ISO-8601 year number. This has the same value as Y\r
+                                                if(str.search(/^(\d{4})/) != -1) {\r
+                                                        y = str.substr(0,4);\r
+                                                        str = str.substr(4);\r
+                                                        break;\r
+                                                } else return "";\r
+                                case "y": // A two digit representation of a year\r
+                                                if(str.search(/^(0[0-9]|[1-9][0-9])/) != -1) {\r
+                                                        y = +str.substr(0,2);\r
+                                                        y = +y < 50 ? '20' + y : '19' + y;\r
+                                                        str = str.substr(2);\r
+                                                        break;\r
+                                                } else return "";\r
+                                default:\r
+                                                return "";\r
+                        };\r
+                };   \r
+                \r
+                d = d === false ? now.getDate() : d;\r
+                m = m === false ? now.getMonth() - 1 : m;\r
+                y = y === false ? now.getFullYear() : y;\r
+                   \r
+                var tmpDate = new Date(y,m,d);\r
+                return isNaN(tmpDate) ? "" : tmpDate;\r
+        };\r
+        var repositionDatePickers = function(e) {\r
+                for(dp in datePickers) {\r
+                        if(!datePickers[dp].created || datePickers[dp].staticPos || (!datePickers[dp].staticPos && !datePickers[dp].dragDisabled)) continue;\r
+                        datePickers[dp].reposition();\r
+                };\r
+        };\r
+        var addDatePicker = function(options) {\r
+                if(!options.id) { throw "A datePicker requires an associated element with an id attribute"; };\r
+                if(options.id in datePickers) { return; };\r
+                var elem = document.getElementById(options.id);\r
+                if(!elem) throw "Cannot locate a datePicker's associated element with an id of:" + options.id;\r
+                if(elem.tagName.search(/select|input/i) == -1) {\r
+                        if(!("callbacks" in options) || !("dateselect" in options.callbacks)) {\r
+                                throw "A 'dateselect' callback function is required for datePickers not associated with a form element";\r
+                        };\r
+                        options.staticPos       = true;\r
+                        options.splitDate       = false;\r
+                        options.hideInput       = false;\r
+                        options.noFadeEffect    = true;\r
+                        options.dragDisabled    = true;\r
+                        options.positioned      = false;\r
+                } else if(!options.staticPos) {\r
+                        options.hideInput       = false;                                                 \r
+                } else {\r
+                        options.noFadeEffect    = true;\r
+                        options.dragDisabled    = true;\r
+                };\r
+\r
+                datePickers[options.id] = new datePicker(options);\r
+        };\r
+        var parseCallbacks = function(cbs) {\r
+                if(cbs == null) { return {}; };\r
+                var func,\r
+                    type,\r
+                    cbObj = {},\r
+                    parts,\r
+                    obj;\r
+                for(var i = 0, fn; fn = cbs[i]; i++) {\r
+                        type = fn.match(/(cb_(dateselect|redraw|create)_)([^\s|$]+)/i)[1].replace(/^cb_/i, "").replace(/_$/, "");\r
+                        fn   = fn.replace(/cb_(dateselect|redraw|create)_/i, "").replace(/-/g, ".");\r
+                        \r
+                        try {\r
+                                if(fn.indexOf(".") != -1) {\r
+                                        parts = fn.split('.');\r
+                                        obj   = window;\r
+                                        for (var x = 0, part; part = obj[parts[x]]; x++) {\r
+                                                if(part instanceof Function) {\r
+                                                        (function() {\r
+                                                                var method = part;\r
+                                                                func = function (data) { method.apply(obj, [data]) };\r
+                                                        })();\r
+                                                } else {\r
+                                                obj = part;\r
+                                                };\r
+                                        };\r
+                                } else {\r
+                                        func = window[fn];\r
+                                };\r
+\r
+                                if(!(func instanceof Function)) continue;\r
+                                if(!(type in cbObj)) { cbObj[type] = []; };\r
+                                cbObj[type][cbObj[type].length] = func;\r
+                        } catch (err) {};\r
+                };\r
+                return cbObj;\r
+        };\r
+        // Used by the button to dictate whether to open or close the datePicker\r
+        var isVisible = function(id) {\r
+                return (!id || !(id in datePickers)) ? false : datePickers[id].visible;\r
+        };                \r
+        var create = function(inp) {\r
+                if(!(typeof document.createElement != "undefined" && typeof document.documentElement != "undefined" && typeof document.documentElement.offsetWidth == "number")) { return; };\r
+\r
+                // Has the locale file loaded?\r
+                if(typeof(fdLocale) == "object" && !localeImport) {\r
+                        localeImport = {\r
+                                titles          : fdLocale.titles,\r
+                                fullMonths      : fdLocale.fullMonths,\r
+                                monthAbbrs      : fdLocale.monthAbbrs,\r
+                                fullDays        : fdLocale.fullDays,\r
+                                dayAbbrs        : fdLocale.dayAbbrs,\r
+                                firstDayOfWeek  : ("firstDayOfWeek" in fdLocale) ? fdLocale.firstDayOfWeek : 0,\r
+                                imported        : true\r
+                        };\r
+                } else if(!localeImport) {\r
+                        localeImport = localeDefaults;\r
+                };  \r
+                \r
+                var formElements = (inp && inp.tagName) ? [inp] : joinNodeLists(document.getElementsByTagName('input'), document.getElementsByTagName('select')),\r
+                    disableDays  = /disable-days-([1-7]){1,6}/g,\r
+                    highlight    = /highlight-days-([1-7]{1,7})/,\r
+                    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))/,\r
+                    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))/,\r
+                    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])))+/,\r
+                    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])))+/,                    \r
+                    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,\r
+                    enableDates  = /enable((-(\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,\r
+                    callbacks    = /((cb_(dateselect|redraw|create)_)([^\s|$]+))/ig,\r
+                    positioned   = /display-inline-([^\s|$]+)/i,\r
+                    bPositioned  = /button-([^\s|$]+)/i,\r
+                    range,tmp,j,t,options,dts,parts;                  \r
+                    \r
+                for(var i = 0, elem; elem = formElements[i]; i++) {  \r
+                        if(elem.className && (elem.className.search(dateFormat) != -1 || elem.className.search(/split-date/) != -1) && ((elem.tagName.toLowerCase() == "input" && (elem.type == "text" || elem.type == "hidden")) || elem.tagName.toLowerCase() == "select")) {\r
+                                \r
+                                if(elem.id && elem.id in datePickers) {                                                                                                                        \r
+                                        if(!datePickers[elem.id].staticPos) { datePickers[elem.id].createButton(); }\r
+                                        else { \r
+                                                if(!document.getElementById("fd-" + elem.id)) {\r
+                                                        datePickers[elem.id].created = false;                                                         \r
+                                                        datePickers[elem.id].create();                                                     \r
+                                                } else if(inp) {    \r
+                                                        // Only do this if called from an ajax update etc                                                    \r
+                                                        datePickers[elem.id].setDateFromInput();  \r
+                                                        datePickers[elem.id].updateTable();      \r
+                                                };                                        \r
+                                        };                                          \r
+                                        continue;\r
+                                };\r
+                                \r
+                                if(!elem.id) { elem.id = "fdDatePickerInput-" + uniqueId++; };\r
+                                \r
+                                options = {\r
+                                        id:elem.id,\r
+                                        low:"",\r
+                                        high:"",\r
+                                        format:"d-sl-m-sl-Y",\r
+                                        statusFormat:"",\r
+                                        highlightDays:[0,0,0,0,0,1,1],\r
+                                        disabledDays:[0,0,0,0,0,0,0],\r
+                                        disabledDates:{},\r
+                                        enabledDates:{},\r
+                                        noFadeEffect:elem.className.search(/no-animation/i) != -1,\r
+                                        staticPos:elem.className.search(/display-inline/i) != -1,\r
+                                        hideInput:elem.className.search(/hide-input/i) != -1,\r
+                                        noToday:elem.className.search(/no-today-button/i) != -1,\r
+                                        showWeeks:elem.className.search(/show-week/i) != -1,\r
+                                        dragDisabled:nodrag ? true : elem.className.search(/disable-drag/i) != -1,\r
+                                        positioned:false,\r
+                                        firstDayOfWeek:localeImport.firstDayOfWeek,\r
+                                        fillGrid:elem.className.search(/fill-grid/i) != -1,\r
+                                        constrainSelection:elem.className.search(/fill-grid-no-select/i) != -1,\r
+                                        callbacks:parseCallbacks(elem.className.match(callbacks)),\r
+                                        buttonWrapper:""\r
+                                };                            \r
+                                \r
+                                // Positioning of static dp's\r
+                                if(options.staticPos && elem.className.search(positioned) != -1) {\r
+                                        options.positioned = elem.className.match(positioned)[1];                                        \r
+                                };\r
+                                \r
+                                // Positioning of non-static dp's button\r
+                                if(!options.staticPos && elem.className.search(bPositioned) != -1) {\r
+                                        options.buttonWrapper = elem.className.match(bPositioned)[1];                                        \r
+                                };\r
+                                \r
+                                // Opacity of non-static datePickers\r
+                                if(!options.staticPos) {\r
+                                        options.finalOpacity = elem.className.search(/opacity-([1-9]{1}[0-9]{1})/i) != -1 ? elem.className.match(/opacity-([1-9]{1}[0-9]{1})/i)[1] : 90                              \r
+                                };\r
+                                \r
+                                // Dates to disable\r
+                                dts = elem.className.match(disableDates);\r
+                                if(dts) {\r
+                                        for(t = 0; t < dts.length; t++) {\r
+                                                parts = dts[t].replace(/xxxx/, "****").replace(/xx/, "**").replace("disable-", "").split("-");\r
+                                                options.disabledDates[parts[0]] = (parts.length && parts.length == 2) ? parts[1] : 1;                                                \r
+                                        };\r
+                                };\r
+\r
+                                // Dates to enable\r
+                                dts = elem.className.match(enableDates);\r
+                                if(dts) {\r
+                                        for(t = 0; t < dts.length; t++) {\r
+                                                parts = dts[t].replace(/xxxx/, "****").replace(/xx/, "**").replace("enable-", "").split("-");\r
+                                                options.enabledDates[parts[0]] = (parts.length && parts.length == 2) ? parts[1] : 1;                                                \r
+                                        };\r
+                                };\r
+                                             \r
+                                // Split the date into three parts ?                                \r
+                                options.splitDate = (elem.className.search(/split-date/) != -1 && document.getElementById(elem.id+splitAppend[0]) && document.getElementById(elem.id+splitAppend[1]) && document.getElementById(elem.id+splitAppend[0]).tagName.search(/input|select/i) != -1 && document.getElementById(elem.id+splitAppend[1]).tagName.search(/input|select/i) != -1);                              \r
+                                \r
+                                // Date format\r
+                                if(!options.splitDate && elem.className.search(dateFormat) != -1) {\r
+                                        options.format = elem.className.match(dateFormat)[0].replace('dateformat-','');\r
+                                };\r
+\r
+                                // Status bar date format\r
+                                if(elem.className.search(statusFormat) != -1) {\r
+                                        options.statusFormat = elem.className.match(statusFormat)[0].replace('statusformat-','');\r
+                                };\r
+                                \r
+                                // The days of the week to highlight\r
+                                if(elem.className.search(highlight) != -1) {\r
+                                        tmp = elem.className.match(highlight)[0].replace(/highlight-days-/, '');\r
+                                        options.highlightDays = [0,0,0,0,0,0,0];\r
+                                        for(j = 0; j < tmp.length; j++) {\r
+                                                options.highlightDays[tmp.charAt(j) - 1] = 1;\r
+                                        };\r
+                                };\r
+                                \r
+                                // The days of the week to disable\r
+                                if(elem.className.search(disableDays) != -1) {\r
+                                        tmp = elem.className.match(disableDays)[0].replace(/disable-days-/, '');\r
+                                        options.disabledDays = [0,0,0,0,0,0,0];                                         \r
+                                        for(j = 0; j < tmp.length; j++) {\r
+                                                options.disabledDays[tmp.charAt(j) - 1] = 1;\r
+                                        };\r
+                                };\r
+\r
+                                // The lower limit\r
+                                if(elem.className.search(rangeLow) != -1) {\r
+                                        options.low = parseRangeFromString(elem.className.match(rangeLow)[0]);\r
+                                };\r
+\r
+                                // The higher limit\r
+                                if(elem.className.search(rangeHigh) != -1) {\r
+                                        options.high = parseRangeFromString(elem.className.match(rangeHigh)[0]);\r
+                                };\r
+\r
+                                // Always round lower & higher limits if a selectList involved\r
+                                if(elem.tagName.search(/select/i) != -1) {\r
+                                        range        = grepRangeLimits(elem);\r
+                                        options.low  = options.low  ? range[0] + String(options.low).substr(4,4)  : range[0] + "0101";\r
+                                        options.high = options.high ? range[1] + String(options.high).substr(4,4) : range[1] + "1231";\r
+                                };\r
+\r
+                                addDatePicker(options);\r
+                        };\r
+                };\r
+        };\r
+\r
+        addEvent(window, 'load',   create);\r
+        addEvent(window, 'unload', destroy);\r
+        addEvent(window, 'resize', repositionDatePickers);\r
+\r
+        return {\r
+                addEvent:               function(obj, type, fn) { return addEvent(obj, type, fn); },\r
+                removeEvent:            function(obj, type, fn) { return removeEvent(obj, type, fn); },\r
+                stopEvent:              function(e) { return stopEvent(e); },\r
+                show:                   function(inpID) { return showDatePicker(inpID); },\r
+                create:                 function(inp) { create(inp); },                 \r
+                repositionDatePickers:  function() { repositionDatePickers(); },\r
+                newDatePicker:          function(opts) { addDatePicker(opts); },\r
+                overrideAppendID:       function(arr) { splitAppend = (arr && arr.length && arr.length == 2) ? arr : splitAppend },\r
+                printFormattedDate:     function(dt, fmt, useImportedLocale) { return printFormattedDate(dt, fmt, useImportedLocale); },\r
+                setDateFromInput:       function(inpID) { if(!inpID || !(inpID in datePickers) || !datePickers[inpID].created) return false; datePickers[inpID].setDateFromInput(); },\r
+                setRangeLow:            function(inpID, yyyymmdd) { if(!inpID || !(inpID in datePickers)) return false; datePickers[inpID].setRangeLow(yyyymmdd); },\r
+                setRangeHigh:           function(inpID, yyyymmdd) { if(!inpID || !(inpID in datePickers)) return false; datePickers[inpID].setRangeHigh(yyyymmdd); },\r
+                parseDateString:        function(str, format) { return parseDateString(str, format); },\r
+                disableDrag:            function() { noDrag = true; },\r
+                setGlobalVars:          function(json) { affectJSON(json); },\r
+                addDisabledDates:       function(inpID, dts) { if(!inpID || !(inpID in datePickers)) return false; datePickers[inpID].addDisabledDates(dts); },\r
+                setDisabledDates:       function(inpID, dts) { if(!inpID || !(inpID in datePickers)) return false; datePickers[inpID].setDisabledDates(dts); }                                              \r
+        }; \r
+})();\r
+\r
+// Change this to use your own month & day id appendages\r
+// It can also be passed using JSON within the script tag \r
+// datePickerController.overrideAppendID(["Day", "Month"]);\r
index f5c66c0..a132504 100644 (file)
@@ -16,6 +16,7 @@ include 'plc_header.php';
 require_once 'plc_functions.php';
 require_once 'plc_tables.php';
 require_once 'plc_minitabs.php';
+require_once 'plc_datepicker.php';
   
 // needs much memory
 ini_set("memory_limit","256M");
@@ -37,40 +38,19 @@ function the_date ($key,$dateformat) {
 }
 
 // fill out dates from now if not specified
-$from_d = the_date('from_d','j');
-$from_m = the_date('from_m','M');
-$from_y = the_date('from_y','Y');
-$until_d = the_date('until_d','j');
-$until_m = the_date('until_m','M');
-$until_y = the_date('until_y','Y');
-
-// create the options area from a list and the selected entry
-function dropdown_options ($array,$selected) {
-  $result="";
-  foreach ($array as $item) {
-    $result.= "<option value=" . $item;
-    if ($item == $selected) $result .= ' selected=selected';
-    $result .= '>' . $item . '</option>';
-  }
-  return $result;
-}
+$from_picker = new PlcDatepicker ('from_date','From (inclusive)');
+$from_picker->today();
+$from_html=$from_picker->html();
+$until_picker = new PlcDatepicker ('until_date','Until (inclusive)');
+$until_picker->today();
+$until_html=$until_picker->html();
+
+$action=l_events();
 
-$days=range(1,31);
-$from_d_dropdown_options=dropdown_options($days,$from_d);
-$until_d_dropdown_options=dropdown_options($days,$until_d);
-$months=array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
-$from_m_dropdown_options=dropdown_options($months,$from_m);
-$until_m_dropdown_options=dropdown_options($months,$until_m);
-// only propose years ranging from now + 3 full years back
-$this_year=date('Y');
-$years=range($this_year-3,$this_year);
-$from_y_dropdown_options=dropdown_options($years,$from_y);
-$until_y_dropdown_options=dropdown_options($years,$until_y);
 $event_form = <<< EOF
-<form method=get name='F' action='/db/events/index.php' >
+<form method=get name='events' action='$action' >
 
-<table align='bottom'>
+<table class='plc_details'>
 <tr><td colspan=2>
 <table> <TR><TD>
 <input type='radio' name='type' id='events' value='Event' checked='checked'>&nbsp;Events: 
@@ -95,35 +75,9 @@ $event_form = <<< EOF
 </TD></TR></table>
 </td></tr>
 
-
-<tr><th>FROM (inclusive)</th> <th>UNTIL (inclusive)</th> </tr>
-
-<tr>
-      <td>    
-        <SELECT NAME='from_d'>
-$from_d_dropdown_options                                                                
-        </SELECT>
-        <SELECT NAME='from_m' >
-$from_m_dropdown_options
-        </SELECT>
-        <SELECT NAME='from_y' >
-$from_y_dropdown_options
-        </SELECT>
-</td>
-
-<TD>
-   <SELECT NAME=' until_d' >
-$until_d_dropdown_options
-    </SELECT>
-    <SELECT NAME=' until_m' >
-$until_m_dropdown_options
-   </SELECT>
-    <SELECT NAME=' until_y' >
-$until_y_dropdown_options
-    </SELECT>
-</td></tr>
-
-<TR><TD colspan=2>
+<tr><td> $from_html </td><td>$until_html</td></tr>
+<tr><td colspan=2>&nbsp </td></tr>
+<TR><TD colspan=2 style='text-align:center'>
 <input type='submit' align='middle' value='Show Events'>
 </TD></TR>
 </table>
@@ -132,24 +86,21 @@ $until_y_dropdown_options
 EOF;
 
 //////////////////////////////////////////////////////////// dates
-function parse_date ($day,$month,$year) {
-  // if everything empty -> unspecified date, return 0
-  if ( empty($day) && empty($month) && empty($year)) {
-    return array ("xxx",0);
+// our format is yyyy/MMM/dd
+function parse_date ($datestring) {
+  if (empty ($datestring)) {
+    $year="2008"; $month="Jan"; $day="01";
   } else {
-    // fill missing fields with current value
-    if (empty($day)) $day=date('d');
-    if (empty($month)) $month=date('M');
-    if (empty($year)) $year=date('Y');
-    $date=sprintf("%s %s %s",$day,$month,$year);
-    $time=strtotime($date);
-    return array($date,$time);
+    list ($year,$month,$day) = split ('[/.-]',$datestring);
   }
+  $date=sprintf("%s %s %s",$day,$month,$year);
+  $time=strtotime($date);
+  return array($date,$time);
 }
 
 function parse_dates () {
-  list($from_date,$from_time) = parse_date($_GET['from_d'],$_GET['from_m'],$_GET['from_y']);
-  list($until_date,$until_time) = parse_date($_GET['until_d'],$_GET['until_m'],$_GET['until_y']);
+  list($from_date,$from_time) = parse_date($_GET['from_date']);
+  list($until_date,$until_time) = parse_date($_GET['until_date']);
   return array($from_date,$from_time,$until_date,$until_time);
 }
 
diff --git a/planetlab/includes/plc_datepicker.php b/planetlab/includes/plc_datepicker.php
new file mode 100644 (file)
index 0000000..229793b
--- /dev/null
@@ -0,0 +1,53 @@
+<?php
+
+  // $Id$
+
+  // see the demo at http://www.frequency-decoder.com/demo/date-picker-v4/
+
+drupal_set_html_head('
+<script type="text/javascript" src="/planetlab/datepicker/datepicker.js"></script>
+<link href="/planetlab/datepicker/datepicker.css" rel="stylesheet" type="text/css" />
+');
+
+// supported options
+// (*) inline (default=true)
+// (*) format (default 2010/Jan/01), php-equiv. Y/M/d, which in this paradigm translates into Y-sl-m-sl-d
+// (*) value : the value to display initially - default ''
+
+class PlcDatepicker {
+
+  var $id;
+
+  function PlcDatepicker ($id,$display,$options=NULL) {
+    $datepicker_default_options = 
+      array ('inline'=>true,
+            'format'=>'Y-sl-M-sl-d',
+            'value'=>'');
+    if (!$options) $options=array();
+    $this->id=$id;
+    $this->display=$display;
+    $this->options=array_merge($datepicker_default_options,$options);
+    
+  }
+
+  function html () {
+    $inline=$this->options['inline'];
+    $format=$this->options['format'];
+    $value=$this->options['value'];
+
+    $html="";
+    $html .= "<label for='$this->id'>$this->display</label>";
+    $html .= "<div><input type='text' class='";
+    $html .= " dateformat-$format";
+    $html .= " opacity-60";
+    if ($inline) $html .= " display-inline";
+    $html .= "' id='$this->id' name='$this->id' value='$value' /></div>";
+    return $html;
+  }
+
+  function today () {
+    // works for default format only for now
+    $this->options['value']=date('Y/M/d');
+  }
+
+}
index 1d3b7eb..e34bf12 100644 (file)
@@ -1,6 +1,7 @@
-
 <?php
 
+  // $Id$
+
 function timeDiff ($timestamp,$detailed=false,$n = 0) {
   $now = time();
 
index 0cfeba4..5d7f379 100644 (file)
@@ -1,5 +1,7 @@
 <?php
 
+  // $Id$
+
 drupal_set_html_head('
 <script type="text/javascript" src="/planetlab/tablesort/tablesort.js"></script>
 <script type="text/javascript" src="/planetlab/tablesort/customsort.js"></script>
diff --git a/planetlab/tablesort/URL b/planetlab/tablesort/URL
new file mode 100644 (file)
index 0000000..6a63884
--- /dev/null
@@ -0,0 +1 @@
+http://www.frequency-decoder.com/