dos2unix
authorThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Thu, 28 May 2009 08:44:42 +0000 (08:44 +0000)
committerThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Thu, 28 May 2009 08:44:42 +0000 (08:44 +0000)
plekit/datepicker/datepicker.css
plekit/datepicker/datepicker.js
plekit/niftycorner/niftyCorners.css
plekit/niftycorner/niftycube.js
plekit/tablesort/customsort.js
plekit/tablesort/paginate.js
plekit/tablesort/tablesort.js

index c3d0f0b..c03362b 100644 (file)
-/* 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
+/* This is a very basic stylesheet for the date-picker. Feel free to create your own. */
+
+/* The wrapper div */
+div.datePicker
+        {
+        position:absolute;        
+        z-index:9999;
+        text-align:center;
+
+        /* 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 */
+        font:900 0.8em/1em Verdana, Sans-Serif;
+
+        /* For Example: If using the YUI font CSS, uncomment the following line to get a 10px font-size within the datePicker */
+        /* font:900 77%/77% Verdana, sans-serif; */
+        
+        /* Or, if you prefer a pixel precision */
+        /* font:900 12px/12px Verdana, sans-serif; */
+        
+        background:transparent;
+
+        /* Mozilla & Webkit extensions to stop text-selection. Remove if you wish to validate the CSS */
+        -moz-user-select:none;
+        -khtml-user-select:none;                 
+        }    
+/* You can add focus effects (for everything but IE6) like so: */
+div.datePicker:focus
+        {
+        /* Naughty, naughty - but we add a highlight using the table's border colour */
+        outline:none;
+        }
+div.datePicker:focus table
+        {
+        border-color:#aaa;
+        }
+/* Make the wrapper div larger if weeks are to be displayed */
+div.weeks-displayed
+        {
+        /* min-width:28em; 
+        width:28em; */
+        }
+/* Styles for the static datePickers */
+div.static-datepicker
+        {
+        position:relative;        
+        top:5px;
+        left:0;
+        }
+div.datePicker table
+        {
+        width:auto;
+        height:auto;
+        }
+/* Draggable datepickers */
+div.datePicker tfoot th.drag-enabled,
+div.datePicker thead th.drag-enabled,
+div.datePicker thead th.drag-enabled span
+        {
+        cursor:move;
+        }
+/* The iframe hack to cover selectlists in Internet Explorer <= v6 */
+iframe.iehack
+        {
+        position:absolute;
+        background:#fff;
+        z-index:9998;
+        padding:0;
+        border:0;
+        display:none;
+        margin:0;
+        }
+/* The "button" created beside each input for non-static datePickers */
+a.date-picker-control:link,
+a.date-picker-control:visited
+        {
+        position:relative;
+        /* Moz & FF */
+        display: -moz-inline-stack;
+        border:0 none;
+        padding:0;
+        margin:0 0 0 4px;
+        background:transparent url(../media/cal-grey.gif) no-repeat 50% 50%;
+        min-width:16px;
+        line-height:1;
+        cursor:pointer;
+        visibility:visible;
+        text-decoration:none;
+        vertical-align:top;
+        }
+a.date-picker-control:hover,
+a.date-picker-control:active,
+a.date-picker-control:focus,
+a.dp-button-active:link,
+a.dp-button-active:visited,
+a.dp-button-active:hover,
+a.dp-button-active:active,
+a.dp-button-active:focus
+        {
+        background:transparent url(../media/cal.gif) no-repeat 50% 50% !important;
+        }
+/* Feed IE6 the following rule, IE7 should handle the min-width declared above */
+* html a.date-picker-control
+        {
+        width:16px;
+        }
+/* IE, Safari & Opera. Seperate CSS rule seems to be required. */
+a.date-picker-control
+        {
+        display:inline-block;
+        }
+a.date-picker-control span
+        {
+        display:block;
+        width:16px;
+        height:16px;
+        margin:auto 0;
+        }
+/* Default "button" styles */
+div.datePicker thead th span
+        {
+        display:block;
+        padding:0;
+        margin:0;
+        text-align:center;
+        line-height:1em;
+        border:0 none;
+        background:transparent;
+        font-weight:bold;
+        cursor:pointer;
+        }
+/* The "month, year" display */
+div.datePicker th span.month-display,
+div.datePicker th span.year-display
+        {
+        display:inline;
+        text-transform:uppercase;
+        letter-spacing:1px;
+        font:normal 1.2em Verdana, Sans-Serif;
+        cursor:default;          
+        }
+/* Next & Previous (month, year) buttons */
+div.datePicker th span.prev-but,
+div.datePicker th span.next-but
+        {
+        font-weight:lighter;
+        font-size:2.4em;
+        font-family: georgia, times new roman, palatino, times, bookman, serif;
+        cursor:pointer !important;
+        }
+/* Hover effect for Next & Previous (month, year) buttons */
+div.datePicker th span.prev-but:hover,
+div.datePicker th span.next-but:hover,
+div.datePicker th span.today-but:hover
+        {
+        color:#a84444;
+        }
+/* Today button */
+div.datePicker th span.today-but
+        {
+        text-align:center;
+        margin:0 auto;
+        font:normal 1em Verdana, Sans-Serif;
+        width:100%;
+        text-decoration:none;
+        padding-top:0.3em;
+        text-transform:uppercase;
+        vertical-align:middle;
+        cursor:pointer !important          
+        }
+/* Disabled Today button - IE6 will not see this rule as it should */
+div.datePicker th span.today-but.fd-disabled
+        {
+        display:none;
+        }
+/* Disabled buttons */
+div.datePicker th span.prev-but.fd-disabled:hover,
+div.datePicker th span.next-but.fd-disabled:hover,
+div.datePicker thead th span.fd-disabled
+        {
+        color:#aaa;
+        cursor:default !important; 
+        display:block; /* required to get IE6 to play ball */
+        }
+
+/* The mon, tue, wed etc day buttons */
+div.datePicker th span.fd-day-header
+        {
+        text-align:center;
+        margin:0 auto;
+        font:900 1em Verdana, Sans-Serif;
+        text-decoration:none;
+        text-transform:lowercase;
+        cursor:pointer;          
+        }
+/* The table */
+div.datePicker table
+        {               
+        margin:0;
+        padding:0px;
+        border:1px solid #ccc;        
+        background:#fff url(../media/gradient-e5e5e5-ffffff.gif) repeat-x 0 -20px;
+        text-align:center;
+        border-spacing:2px;
+        padding:0.3em; 
+        width:auto;             
+        empty-cells:show;               
+        -moz-border-radius:0.8em;        
+        }
+/* Common TD & TH styling */
+div.datePicker table td,
+div.datePicker table tbody th
+        {                 
+        border:0 none;
+        padding:0;
+        text-align:center;
+        vertical-align:middle;               
+        cursor:pointer;
+        background:#fff url(../media/gradient-e5e5e5-ffffff.gif) repeat-x 0 -40px;
+        width:3em;
+        height:3em;         
+        outline:none;        
+        border:1px solid #ccc;
+        text-transform:none;
+        -moz-border-radius:2px;
+        -webkit-border-radius:2px;
+        border-radius:2px;
+        }
+div.datePicker table th
+        {
+        border:0 none;
+        padding:0;        
+        font-weight:bold;
+        color:#222;
+        text-align:center;
+        vertical-align:middle; 
+        text-transform:none;        
+        }
+div.datePicker table thead th
+        {
+        height:auto !important;
+        }
+div.datePicker table tbody th
+        {                          
+        border:1px solid #dcdcdc;        
+        }
+/* Week number display */
+div.datePicker table thead th.date-picker-week-header,
+div.datePicker table tbody th.date-picker-week-header
+        {
+        font-style:oblique;  
+        background:transparent;
+        cursor:default;         
+        }
+div.datePicker table thead th.date-picker-week-header
+        {
+        cursor:help;
+        border:0 none;
+        padding:0 0 0.2em 0;
+        }
+/* tfoot status bar */
+div.datePicker tfoot th
+        {
+        cursor:default;
+        font-weight:normal;
+        text-transform:uppercase;
+        letter-spacing:0.1em;
+        border:0 none;
+        background:transparent;
+        height:2.8em;
+        }
+/* TD cell that is _not_ used to display a day of the month */
+div.datePicker table tbody td.date-picker-unused
+        {
+        background:#fff url(../media/backstripes.gif);
+        border-color:#dcdcdc;          
+        cursor:default !important;
+        }
+
+/* The TH cell used to display the "month, year" title */
+div.datePicker table thead th.date-picker-title
+        {
+        width:auto;
+        height:auto;
+        padding:0.4em 0;
+        }
+/* The "mon tue wed etc" day header styles */
+div.datePicker table thead th.date-picker-day-header
+        {
+        text-transform:lowercase;
+        cursor:help;
+        height:auto;
+        }
+/* The "todays date" style */
+div.datePicker table tbody td.date-picker-today
+        {
+        background:#fff url(../media/bullet2.gif) no-repeat 0 0;
+        color:rgb(100,100,100) !important;
+        }
+
+div.datePicker table tbody td.month-out.date-picker-highlight 
+        {
+        color:#aa8866 !important;
+        }
+/* The "highlight days" style */
+div.datePicker table tbody td.date-picker-highlight,
+div.datePicker table thead th.date-picker-highlight
+        {
+        color:#a86666 !important;
+        }
+/* The "active cursor" style */
+div.datePicker table tbody td.date-picker-hover
+        {
+        background:#fff url(../media/bg_header.jpg) no-repeat 0 0;
+        cursor:pointer;
+        border-color:rgb(100,130,170) !important;
+        color:rgb(100,130,170);                 
+        }
+/* The "disabled days" style */
+div.datePicker table tbody td.day-disabled
+        {          
+        background:#fff url(../media/backstripes.gif) no-repeat 0 0;
+        color:#aaa !important;
+        cursor:default;
+        text-decoration:line-through;
+        } 
+div.datePicker table tbody td.month-out 
+        {
+        border-color:#ddd;
+        color:#aaa !important;
+        background:#fff url(../media/gradient-e5e5e5-ffffff.gif) repeat-x 0 -40px;                       
+        } 
+/* The "selected date" style */
+div.datePicker table tbody td.date-picker-selected-date
+        {
+        color:#333 !important;
+        border-color:#333 !important;
+        }
+/* The date "out of range" style */
+div.datePicker table tbody td.out-of-range,
+div.datePicker table tbody td.not-selectable
+        {
+        color:#ccc !important;
+        font-style:oblique;
+        background:#fcfcfc !important;
+        cursor:default !important;
+        opacity:0.6;
+        } 
+/* Week number "out of range" && "month-out" styles */
+div.datePicker table tbody th.month-out,
+div.datePicker table tbody th.out-of-range
+        {
+        color:#aaa !important;
+        font-style:oblique;
+        background:#fcfcfc !important;          
+        }
+div.datePicker table tbody th.out-of-range
+        {
+        opacity:0.6;
+        }  
+/* Used when the entire grid is full but next/prev months cannot be selected */
+div.datePicker table tbody td.not-selectable
+        {
+        opacity:0.8;
+        }
+div.datePicker table tbody tr
+        {
+        display:table-row;
+        }
+div.datePicker table tfoot sup
+        {
+        font-size:0.8em;
+        letter-spacing:normal;
+        text-transform:none;
+        height: 0;
+       line-height: 1;
+       position: relative;
+       top: -0.2em;    
+       vertical-align: baseline !important;
+       vertical-align: bottom;  
+        }
+/* INTERNET EXPLORER WOES
+   ======================
+   
+   Hover Effects
+   -------------
+   
+   Cannot deal with :focus and so the datePicker script adds the class "dp-row-highlight" to the
+   row currently being hovered over. This should enable you to add hover effects if desired.
+   
+   e.g. the following rule will highlight the cell borders in another colour when a row is moused over,
+   it looks like crap though so I didn't include the rule within the demo:
+   
+div.datePicker table tbody tr.dp-row-highlight td
+        {
+        border-color:#aaa;
+        }
+*/
+
+/* Remove the images for Internet Explorer <= v6 using the "* html" hack - (NTS: move this to it's own file) 
+   This is a workaround for a nasty IE6 bug that never caches background images on dynamically created DOM nodes
+   which means that they are downloaded for every cell for every table - nasty shit indeed! */    
+* html div.datePicker table td
+        {
+        background-image:none;
+        }
+* html div.datePicker table td.date-picker-unused
+        {
+        background:#f2f2f2;
+        }        
+@media screen and (-webkit-min-device-pixel-ratio:0) {
+        div.datePicker table
+                {
+                border-spacing:0.3em;
+                /* Naughty, naughty */
+                -webkit-box-shadow:0px 0px 5px #aaa;
+                -webkit-border-radius:0.8em;
+                }
+        div.static-datepicker table
+                {
+                -webkit-box-shadow:0 0 0 transparent;
+                }
+        div.static-datepicker:focus table
+                {
+                -webkit-box-shadow:0px 0px 5px #aaa;
+                }
+        div.datePicker table td,
+        div.datePicker table tbody th
+                {
+                padding:0.1em;
+                -webkit-border-radius:2px;
+                }
+        div.datePicker table tbody td.date-picker-hover
+                {
+                text-shadow:0px 0px 1px #fff;
+                -webkit-box-shadow:0px 0px 1px rgb(100,130,170);
+                }
+
+}
+
index 16b099f..586f52f 100644 (file)
-/*\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
+/*
+        DatePicker v4b rc1 by frequency-decoder.com
+
+        Released under a creative commons Attribution-ShareAlike 2.5 license (http://creativecommons.org/licenses/by-sa/2.5/)
+
+        Please credit frequency-decoder in any derivative work - thanks.
+        
+        You are free:
+
+        * to copy, distribute, display, and perform the work
+        * to make derivative works
+        * to make commercial use of the work
+
+        Under the following conditions:
+
+                by Attribution.
+                --------------
+                You must attribute the work in the manner specified by the author or licensor.
+
+                sa
+                --
+                Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license identical to this one.
+
+        * For any reuse or distribution, you must make clear to others the license terms of this work.
+        * Any of these conditions can be waived if you get permission from the copyright holder.
+*/
+
+var datePickerController = (function datePickerController() {
+        var languageInfo        = navigator.language ? navigator.language.toLowerCase().replace(/-[a-z]+$/, "") : navigator.userLanguage ? navigator.userLanguage.toLowerCase().replace(/-[a-z]+$/, "") : "en",
+            datePickers         = {},
+            uniqueId            = 0,
+            weeksInYearCache    = {},
+            localeImport        = false,
+            nbsp                = String.fromCharCode(160),
+            nodrag              = false,
+            splitAppend         = ["-dd","-mm"],
+            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"];                
+        
+        void function() {
+                var scriptFiles = document.getElementsByTagName('head')[0].getElementsByTagName('script'),                    
+                    scriptInner = scriptFiles[scriptFiles.length - 1].innerHTML.replace(/[\n\r\s\t]+/g, " ").replace(/^\s+/, "").replace(/\s+$/, ""),                    
+                    json        = parseJSON(scriptInner);                
+               
+                if(typeof json === "object" && !("err" in json)) {                          
+                        affectJSON(json);
+                };
+       
+                if(typeof(fdLocale) != "object" && languageInfo != "en") {
+                        var loc    = scriptFiles[scriptFiles.length - 1].src.substr(0, scriptFiles[scriptFiles.length - 1].src.lastIndexOf("/")) + "/lang/" + languageInfo + ".js",
+                            script = document.createElement('script');
+                                                          
+                        script.type = "text/javascript";                         
+                        script.src  = loc;
+                        script.setAttribute("charset", "utf-8");
+                        /*@cc_on
+                        /*@if(@_win32)
+                        var bases = document.getElementsByTagName('base');
+                        if (bases.length && bases[0].childNodes.length) {
+                                bases[0].appendChild(script);
+                        } else {
+                                document.getElementsByTagName('head')[0].appendChild(script);
+                        };
+                        bases = null;
+                        @else @*/
+                        document.getElementsByTagName('head')[0].appendChild(script);
+                        /*@end
+                        @*/    
+                        
+                        script = null;                      
+                };                              
+        }();
+        
+        function affectJSON(json) {
+                if(typeof json !== "object") { return; };
+                for(key in json) {
+                        value = json[key];                                                                
+                        switch(key.toLower()) { 
+                                case "lang":
+                                        if(value.search(/^[a-z]{2}$/i) != -1) {
+                                                languageInfo = value;
+                                        };
+                                        break;
+                                case "split":                                                 
+                                        if(typeof value === 'object') {
+                                                if(value.length && value.length == 2) {                                                        
+                                                        splitAppend = value;
+                                                };
+                                        }; 
+                                case "formats":                                                 
+                                        if(typeof value === 'object') {
+                                                if(value.length) {
+                                                        formatMasks = value;
+                                                };
+                                        };
+                                        break;
+                                case "nodrag":
+                                        nodrag = !!value;                                                                                                                                         
+                        };          
+                };        
+        };
+                
+        // Functions shared between the datePickerController object & the datePicker objects    
+        function pad(value, length) { 
+                length = length || 2; 
+                return "0000".substr(0,length - Math.min(String(value).length, length)) + value; 
+        };
+        
+        function addEvent(obj, type, fn) {
+                if( obj.attachEvent ) {
+                        obj["e"+type+fn] = fn;
+                        obj[type+fn] = function(){obj["e"+type+fn]( window.event );};
+                        obj.attachEvent( "on"+type, obj[type+fn] );
+                } else {
+                        obj.addEventListener( type, fn, true );
+                };
+        };
+        
+        function removeEvent(obj, type, fn) {
+                try {
+                        if( obj.detachEvent ) {
+                                obj.detachEvent( "on"+type, obj[type+fn] );
+                                obj[type+fn] = null;
+                        } else {
+                                obj.removeEventListener( type, fn, true );
+                        };
+                } catch(err) {};
+        };   
+
+        function stopEvent(e) {
+                e = e || document.parentWindow.event;
+                if(e.stopPropagation) {
+                        e.stopPropagation();
+                        e.preventDefault();
+                };
+                /*@cc_on
+                @if(@_win32)
+                e.cancelBubble = true;
+                e.returnValue = false;
+                @end
+                @*/
+                return false;
+        };
+        
+        function parseJSON(str) {
+                // Check we have a String
+                if(typeof str !== 'string' || str == "") { return {}; };                 
+                try {
+                        // Does the Douglas Crockford JSON parser exist in the global scope?
+                        if("JSON" in window && "parse" in window.JSON && typeof window.JSON.parse == "function") {                                               
+                                return window.JSON.parse(str);  
+                        // Genious code taken from: http://kentbrewster.com/badges/                                                      
+                        } else if(/lang|split|formats|nodrag/.test(str.toLower())) {                                               
+                                var f = Function(['var document,top,self,window,parent,Number,Date,Object,Function,',
+                                        'Array,String,Math,RegExp,Image,ActiveXObject;',
+                                        'return (' , str.replace(/<\!--.+-->/gim,'').replace(/\bfunction\b/g,'function­') , ');'].join(''));
+                                return f();                          
+                        };
+                } catch (e) {                                 
+                        return {"err":"Trouble parsing JSON object"};
+                };
+                return {};                                            
+        };        
+
+        // The datePicker object itself 
+        function datePicker(options) {                                      
+                this.dateSet             = null;                 
+                this.timerSet            = false;
+                this.visible             = false;
+                this.fadeTimer           = null;
+                this.timer               = null;
+                this.yearInc             = 0;
+                this.monthInc            = 0;
+                this.dayInc              = 0;
+                this.mx                  = 0;
+                this.my                  = 0;
+                this.x                   = 0;
+                this.y                   = 0;                  
+                this.date                = new Date();
+                this.defaults            = {};
+                this.created             = false;
+                this.id                  = options.id;
+                this.opacity             = 0;          
+                this.firstDayOfWeek      = 0; 
+                this.buttonWrapper       = "buttonWrapper" in options ? options.buttonWrapper : false;                
+                this.staticPos           = "staticPos" in options ? !!options.staticPos : false;
+                this.disabledDays        = "disabledDays" in options && options.disabledDays.length ? options.disabledDays : [0,0,0,0,0,0,0];
+                this.disabledDates       = "disabledDates" in options ? options.disabledDates : {};
+                this.enabledDates        = "enabledDates" in options ? options.enabledDates : {};
+                this.showWeeks           = "showWeeks" in options ? !!options.showWeeks : false;
+                this.low                 = options.low || "";
+                this.high                = options.high || "";
+                this.dragDisabled        = nodrag ? true : ("dragDisabled" in options ? !!options.dragDisabled : false);
+                this.positioned          = "positioned" in options ? options.positioned : false;
+                this.hideInput           = this.staticPos ? false : "hideInput" in options ? !!options.hideInput : false;
+                this.splitDate           = "splitDate" in options ? !!options.splitDate : false;
+                this.format              = options.format || "d-sl-m-sl-Y";
+                this.statusFormat        = options.statusFormat || "";
+                this.highlightDays       = options.highlightDays && options.highlightDays.length ? options.highlightDays : [0,0,0,0,0,1,1];
+                this.noFadeEffect        = "noFadeEffect" in options ? !!options.noFadeEffect : false;
+                this.opacityTo           = this.noFadeEffect || this.staticPos ? 99 : 90;
+                this.callbacks           = {};
+                this.fillGrid            = !!options.fillGrid;
+                this.noToday             = !!options.noToday;
+                this.constrainSelection  = this.fillGrid && !!options.constrainSelection;
+                this.finalOpacity        = !this.staticPos && "finalOpacity" in options ? +options.finalOpacity : 90;                
+                this.dynDisabledDates    = {};
+                this.inUpdate            = false;
+                /*@cc_on
+                /*@if(@_win32)
+                this.interval            = new Date();
+                this.iePopUp             = null;
+                /*@end@*/
+                
+                for(var thing in options.callbacks) {
+                        this.callbacks[thing] = options.callbacks[thing];                 
+                };
+                
+                // Adjust time to stop daylight savings madness on windows
+                this.date.setHours(12);              
+          
+                this.startDrag = function(e) {
+                        e = e || document.parentWindow.event;
+                        o.mx = e.pageX?e.pageX:e.clientX?e.clientX:e.x;
+                        o.my = e.pageY?e.pageY:e.clientY?e.clientY:e.Y;
+                        o.x = parseInt(o.div.style.left);
+                        o.y = parseInt(o.div.style.top);
+                        addEvent(document,'mousemove',o.trackDrag, false);
+                        addEvent(document,'mouseup',o.stopDrag, false);
+                        o.div.style.zIndex = 10000;
+                        return stopEvent(e);
+                };
+                this.trackDrag = function(e) {
+                        e = e || window.event;
+                        var diffx = (e.pageX?e.pageX:e.clientX?e.clientX:e.x) - o.mx;
+                        var diffy = (e.pageY?e.pageY:e.clientY?e.clientY:e.Y) - o.my;
+                        o.div.style.left = Math.round(o.x + diffx) > 0 ? Math.round(o.x + diffx) + 'px' : "0px";
+                        o.div.style.top  = Math.round(o.y + diffy) > 0 ? Math.round(o.y + diffy) + 'px' : "0px";
+                        /*@cc_on
+                        @if(@_jscript_version <= 5.6)
+                        if(o.staticPos) return;
+                        o.iePopUp.style.top    = o.div.style.top;
+                        o.iePopUp.style.left   = o.div.style.left;
+                        @end
+                        @*/
+                };
+                this.stopDrag = function(e) {
+                        removeEvent(document,'mousemove',o.trackDrag, false);
+                        removeEvent(document,'mouseup',o.stopDrag, false);
+                        o.div.style.zIndex = 9999;
+                };
+                this.changeHandler = function() {                        
+                        o.setDateFromInput();                        
+                        if(o.created) o.updateTable();
+                };
+                this.reposition = function() {
+                        if(!o.created || !o.getElem() || o.staticPos) { return; };
+
+                        o.div.style.visibility = "hidden";
+                        o.div.style.left = o.div.style.top = "0px";                           
+                        o.div.style.display = "block";
+
+                        var osh         = o.div.offsetHeight,
+                            osw         = o.div.offsetWidth,
+                            elem        = document.getElementById('fd-but-' + o.id),
+                            pos         = o.truePosition(elem),
+                            trueBody    = (document.compatMode && document.compatMode!="BackCompat") ? document.documentElement : document.body,
+                            scrollTop   = window.devicePixelRatio || window.opera ? 0 : trueBody.scrollTop,
+                            scrollLeft  = window.devicePixelRatio || window.opera ? 0 : trueBody.scrollLeft;
+
+                        o.div.style.visibility = "visible";
+
+                        o.div.style.left  = Number(parseInt(trueBody.clientWidth+scrollLeft) < parseInt(osw+pos[0]) ? Math.abs(parseInt((trueBody.clientWidth+scrollLeft) - osw)) : pos[0]) + "px";
+                        o.div.style.top   = 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";
+
+                        /*@cc_on
+                        @if(@_jscript_version <= 5.6)
+                        o.iePopUp.style.top    = o.div.style.top;
+                        o.iePopUp.style.left   = o.div.style.left;
+                        o.iePopUp.style.width  = osw + "px";
+                        o.iePopUp.style.height = (osh - 2) + "px";
+                        @end
+                        @*/
+                }; 
+                this.updateTable = function(noCallback) {  
+                        if(o.inUpdate) return;
+                         
+                        o.inUpdate = true;
+                        o.removeHighlight();
+                                             
+                        if(o.timerSet) {
+                                o.date.setDate(Math.min(o.date.getDate()+o.dayInc, daysInMonth(o.date.getMonth()+o.monthInc,o.date.getFullYear()+o.yearInc)) );
+                                o.date.setMonth(o.date.getMonth() + o.monthInc);
+                                o.date.setFullYear(o.date.getFullYear() + o.yearInc);
+                        }; 
+        
+                        o.outOfRange();
+                        if(!o.noToday) { o.disableTodayButton(); };
+                        o.showHideButtons(o.date);
+                
+                        var cd = o.date.getDate(),
+                            cm = o.date.getMonth(),
+                            cy = o.date.getFullYear(),
+                            cursorDate = (String(cy) + pad(cm+1) + pad(cd)),
+                            tmpDate    = new Date(cy, cm, 1);                      
+                
+                        tmpDate.setHours(5);
+                        
+                        var dt, cName, td, i, currentDate, cellAdded, col, currentStub, abbr, bespokeRenderClass,
+                        weekDayC            = ( tmpDate.getDay() + 6 ) % 7,                
+                        firstColIndex       = (((weekDayC - o.firstDayOfWeek) + 7 ) % 7) - 1,
+                        dpm                 = daysInMonth(cm, cy),
+                        today               = new Date(),
+                        dateSetD            = (o.dateSet != null) ? o.dateSet.getFullYear() + pad(o.dateSet.getMonth()+1) + pad(o.dateSet.getDate()) : false,
+                        stub                = String(tmpDate.getFullYear()) + pad(tmpDate.getMonth()+1),
+                        cellAdded           = [4,4,4,4,4,4],                                                                   
+                        lm                  = new Date(cy, cm-1, 1),
+                        nm                  = new Date(cy, cm+1, 1),                          
+                        daySub              = daysInMonth(lm.getMonth(), lm.getFullYear()),                
+                        stubN               = String(nm.getFullYear()) + pad(nm.getMonth()+1),
+                        stubP               = String(lm.getFullYear()) + pad(lm.getMonth()+1),                
+                        weekDayN            = (nm.getDay() + 6) % 7,
+                        weekDayP            = (lm.getDay() + 6) % 7,                                       
+                        today               = today.getFullYear() + pad(today.getMonth()+1) + pad(today.getDate());
+                        
+                        o.firstDateShown    = !o.constrainSelection && o.fillGrid && (0 - firstColIndex < 1) ? String(stubP) + (daySub + (0 - firstColIndex)) : stub + "01";            
+                        o.lastDateShown     = !o.constrainSelection && o.fillGrid ? stubN + pad(41 - firstColIndex - dpm) : stub + String(dpm);
+                        o.currentYYYYMM     = stub;                    
+                
+                        bespokeRenderClass  = o.callback("redraw", {id:o.id, dd:pad(cd), mm:pad(cm+1), yyyy:cy, firstDateDisplayed:o.firstDateShown, lastDateDisplayed:o.lastDateShown}) || {};                    
+                        o.dynDisabledDates  = o.getDisabledDates(cy, cm + 1);
+                       
+                        for(var curr = 0; curr < 42; curr++) {
+                                row  = Math.floor(curr / 7);                         
+                                td   = o.tds[curr];
+                                
+                                while(td.firstChild) td.removeChild(td.firstChild);
+                                if((curr > firstColIndex && curr <= (firstColIndex + dpm)) || o.fillGrid) {
+                                        currentStub     = stub;
+                                        weekDay         = weekDayC;                                
+                                        dt              = curr - firstColIndex;
+                                        cName           = [];                                         
+                                        selectable      = true;
+                                
+                                        if(dt < 1) {
+                                                dt              = daySub + dt;
+                                                currentStub     = stubP;
+                                                weekDay         = weekDayP;                                        
+                                                selectable      = !o.constrainSelection;
+                                                cName.push("month-out");                                                  
+                                        } else if(dt > dpm) {
+                                                dt -= dpm;
+                                                currentStub     = stubN;
+                                                weekDay         = weekDayN;                                        
+                                                selectable      = !o.constrainSelection; 
+                                                cName.push("month-out");                                                                                           
+                                        }; 
+                                                                                                   
+                                        td.appendChild(document.createTextNode(dt));
+                                        currentDate = currentStub + String(dt < 10 ? "0" : "") + dt;                            
+                                        
+                                        if(o.low && +currentDate < +o.low || o.high && +currentDate > +o.high) {                                          
+                                                td.className = "out-of-range";                                                
+                                                if(o.showWeeks) { cellAdded[row] = Math.min(cellAdded[row], 2); };                                                  
+                                        
+                                        } else {                               
+                                                if(selectable) {                                                 
+                                                        cName.push("cd-" + currentDate + " yyyymm-" + currentStub + " mmdd-" + currentStub.substr(4,2) + pad(dt));
+                                                } else {                                                    
+                                                        cName.push("not-selectable yyyymm-" + currentStub + " mmdd-" + currentStub.substr(4,2) + pad(dt));
+                                                };                                                                                                      
+                                        
+                                                weekDay = ( weekDay + dt + 6 ) % 7;
+
+                                                if(currentDate == today) { cName.push("date-picker-today"); };
+
+                                                if(dateSetD == currentDate) { cName.push("date-picker-selected-date"); };
+
+                                                if(o.disabledDays[weekDay] || currentDate in o.dynDisabledDates) { cName.push("day-disabled"); }
+                                        
+                                                if(currentDate in bespokeRenderClass) { cName.push(bespokeRenderClass[currentDate]); }
+                                        
+                                                if(o.highlightDays[weekDay]) { cName.push("date-picker-highlight"); };
+
+                                                if(cursorDate == currentDate) { td.id = o.id + "-date-picker-hover"; cName.push("date-picker-hover"); }
+                                                else { td.id = ""; };
+                                        
+                                                td.className = cName.join(" ");
+
+                                                if(o.showWeeks) {                                                         
+                                                        cellAdded[row] = Math.min(cName[0] == "month-out" ? 3 : 1, cellAdded[row]);                                                          
+                                                }; 
+                                        };                       
+                                } else {
+                                        td.className = "date-picker-unused";
+                                        td.id = "";                                         
+                                        td.appendChild(document.createTextNode(nbsp));                                        
+                                };                                 
+                                
+                                if(o.showWeeks && curr - (row * 7) == 6) { 
+                                        while(o.wkThs[row].firstChild) o.wkThs[row].removeChild(o.wkThs[row].firstChild);                                         
+                                        o.wkThs[row].appendChild(document.createTextNode(cellAdded[row] == 4 && !o.fillGrid ? nbsp : getWeekNumber(cy, cm, curr - firstColIndex - 6)));
+                                        o.wkThs[row].className = "date-picker-week-header" + (["",""," out-of-range"," month-out",""][cellAdded[row]]);                                          
+                                };                                
+                        };
+
+                        // Title Bar
+                        var span = o.titleBar.getElementsByTagName("span");
+                        while(span[0].firstChild) span[0].removeChild(span[0].firstChild);
+                        while(span[1].firstChild) span[1].removeChild(span[1].firstChild);
+                        span[0].appendChild(document.createTextNode(getMonthTranslation(cm, false) + nbsp));
+                        span[1].appendChild(document.createTextNode(cy));
+                        
+                        if(o.timerSet) {
+                                o.timerInc = 50 + Math.round(((o.timerInc - 50) / 1.8));
+                                o.timer = window.setTimeout(o.updateTable, o.timerInc);
+                        };
+                        
+                        o.inUpdate = false;                          
+                };
+                
+                this.show = function() {
+                        var elem = this.getElem();
+                        if(!elem || this.visible || elem && elem.disabled) { return; };
+
+                        if(!document.getElementById('fd-' + this.id)) {
+                                this.created = false;
+                                this.create();
+                        } else {                           
+                                this.setDateFromInput();
+                                this.outOfRange();
+                                this.updateTable();
+                        };                         
+                        
+                        if(!this.staticPos) this.reposition();                        
+
+                        addEvent(this.staticPos ? this.table : document, "mousedown", this.events.onmousedown);
+                        this.opacityTo = this.finalOpacity;
+                        this.div.style.display = "block";
+                        if(!this.staticPos) {
+                                /*@cc_on
+                                @if(@_jscript_version <= 5.6)
+                                this.iePopUp.style.width = this.div.offsetWidth + "px";
+                                this.iePopUp.style.height = this.div.offsetHeight + "px";
+                                this.iePopUp.style.display = "block";
+                                @end
+                                @*/
+                                this.addKeyboardEvents();
+                                this.fade();
+                                var butt = document.getElementById('fd-but-' + this.id);
+                                if(butt) butt.className = butt.className.replace("dp-button-active", "") + " dp-button-active";
+
+                        } else {
+                                this.opacity = this.opacityTo;
+                        };
+                };
+                this.hide = function() {
+                        if(!this.visible) return;
+                        this.stopTimer();
+                        if(this.staticPos) return;
+
+                        var butt = document.getElementById('fd-but-' + this.id);
+                        if(butt) butt.className = butt.className.replace("dp-button-active", "");
+                
+                        removeEvent(document, "mousedown", this.events.onmousedown);
+                        removeEvent(document, "mouseup",  this.events.clearTimer);
+                        this.removeKeyboardEvents();
+
+                        /*@cc_on
+                        @if(@_jscript_version <= 5.6)
+                        this.iePopUp.style.display = "none";
+                        @end
+                        @*/
+
+                        this.opacityTo = 0;
+                        this.fade();
+                        
+                        //var elem = this.getElem();
+                        //if(!elem.type || elem.type && elem.type != "hidden") { elem.focus(); };
+                };
+                this.destroy = function() {
+                        // Cleanup for Internet Explorer
+                        removeEvent(this.staticPos ? this.table : document, "mousedown", o.events.onmousedown);
+                        removeEvent(document, "mouseup",   o.events.clearTimer);
+                        o.removeKeyboardEvents();
+                        clearTimeout(o.fadeTimer);
+                        clearTimeout(o.timer);
+
+                        /*@cc_on
+                        @if(@_jscript_version <= 5.6)
+                        if(!o.staticPos) {
+                                o.iePopUp.parentNode.removeChild(o.iePopUp);
+                                o.iePopUp = null;
+                        };
+                        @end
+                        @*/
+
+                        if(!this.staticPos && document.getElementById(this.id.replace(/^fd-/, 'fd-but-'))) {
+                                var butt = document.getElementById(this.id.replace(/^fd-/, 'fd-but-'));
+                                butt.onclick = butt.onpress = null;
+                        };
+
+                        if(this.div && this.div.parentNode) {
+                                this.div.parentNode.removeChild(this.div);
+                        };
+
+                        o = null;
+                };
+                this.resizeInlineDiv = function()  {                        
+                        o.div.style.width = o.table.offsetWidth + "px";
+                };
+                this.create = function() {
+                        if(this.created) { return; };
+
+                        function createTH(details) {
+                                var th = document.createElement('th');
+                                if(details.thClassName) th.className = details.thClassName;
+                                if(details.colspan) {
+                                        /*@cc_on
+                                        /*@if (@_win32)
+                                        th.setAttribute('colSpan',details.colspan);
+                                        @else @*/
+                                        th.setAttribute('colspan',details.colspan);
+                                        /*@end
+                                        @*/
+                                };
+                                /*@cc_on
+                                /*@if (@_win32)
+                                th.unselectable = "on";
+                                /*@end@*/
+                                return th;
+                        };
+                        function createThAndButton(tr, obj) {
+                                for(var i = 0, details; details = obj[i]; i++) {
+                                        var th = createTH(details);
+                                        tr.appendChild(th);
+                                        var but = document.createElement('span');
+                                        but.className = details.className;
+                                        but.id = o.id + details.id;
+                                        but.appendChild(document.createTextNode(details.text || o.nbsp));
+                                        but.title = details.title || "";
+                                        if(details.onmousedown) but.onmousedown = details.onmousedown;
+                                        if(details.onclick)     but.onclick     = details.onclick;
+                                        if(details.onmouseout)  but.onmouseout  = details.onmouseout;
+                                        /*@cc_on
+                                        /*@if(@_win32)
+                                        th.unselectable = but.unselectable = "on";
+                                        /*@end@*/
+                                        th.appendChild(but);
+                                };
+                        };  
+                        
+                        this.div                     = document.createElement('div');
+                        this.div.id                  = "fd-" + this.id;
+                        this.div.className           = "datePicker";                   
+                        
+                        var tr, row, col, tableHead, tableBody, tableFoot;
+
+                        this.table             = document.createElement('table');
+                        this.table.className   = "datePickerTable";                         
+                        this.table.onmouseover = this.events.ontablemouseover;
+                        this.table.onmouseout  = this.events.ontablemouseout;
+
+                        this.div.appendChild(this.table);   
+                                
+                        if(!this.staticPos) {
+                                this.div.style.visibility = "hidden";
+                                if(!this.dragDisabled) { this.div.className += " drag-enabled"; };
+                                document.getElementsByTagName('body')[0].appendChild(this.div);
+                                                                
+                                /*@cc_on
+                                @if(@_jscript_version <= 5.6)                                            
+                                this.iePopUp = document.createElement('iframe');
+                                this.iePopUp.src = "javascript:'<html></html>';";
+                                this.iePopUp.setAttribute('className','iehack');
+                                this.iePopUp.scrolling="no";
+                                this.iePopUp.frameBorder="0";
+                                this.iePopUp.name = this.iePopUp.id = this.id + "-iePopUpHack";
+                                document.body.appendChild(this.iePopUp);
+                                @end
+                                @*/
+                        } else {
+                                elem = this.positioned ? document.getElementById(this.positioned) : this.getElem();
+                                if(!elem) {
+                                        this.div = null;
+                                        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;
+                                };
+
+                                this.div.className += " static-datepicker";                               
+                                                               
+                                // tabIndex
+                                this.div.setAttribute(!/*@cc_on!@*/false ? "tabIndex" : "tabindex", "0");
+                                this.div.tabIndex = 0;
+
+                                this.div.onfocus = this.events.onfocus;
+                                this.div.onblur  = this.events.onblur;                                                                                                                         
+                                
+                                if(this.positioned) {
+                                        elem.appendChild(this.div);
+                                } else {
+                                        elem.parentNode.insertBefore(this.div, elem.nextSibling);
+                                };
+                                
+                                if(this.hideInput) {
+                                        var elemList = [elem];                                        
+                                        if(this.splitDate) {
+                                                elemList[elemList.length] = document.getElementById(this.id + splitAppend[1]);
+                                                elemList[elemList.length] = document.getElementById(this.id + splitAppend[0]);                                         
+                                        };
+                                        for(var i = 0; i < elemList.length; i++) {
+                                                if(elemList[i].tagName) elemList[i].className += " fd-hidden-input";        
+                                        };
+                                };                                                                  
+                                                                          
+                                setTimeout(this.resizeInlineDiv, 300);                               
+                        };
+
+                        
+                        if(this.statusFormat) {
+                                tableFoot = document.createElement('tfoot');
+                                this.table.appendChild(tableFoot);
+                                tr = document.createElement('tr');
+                                tr.className = "date-picker-tfoot";
+                                tableFoot.appendChild(tr);
+                                this.statusBar = createTH({thClassName:"date-picker-statusbar", colspan:this.showWeeks ? 8 : 7});
+                                tr.appendChild(this.statusBar);
+                                this.updateStatus();
+                                if(!this.dragDisabled) {
+                                        this.statusBar.className += " drag-enabled";
+                                        addEvent(this.statusBar,'mousedown',this.startDrag,false);
+                                };
+                        };
+
+                        tableHead = document.createElement('thead');
+                        this.table.appendChild(tableHead);
+
+                        tr  = document.createElement('tr');
+                        tableHead.appendChild(tr);
+
+                        // Title Bar
+                        this.titleBar = createTH({thClassName:!this.dragDisabled ? "date-picker-title drag-enabled" : "date-picker-title", colspan:this.showWeeks ? 8 : 7});
+                        if(!this.dragDisabled) {
+                                addEvent(this.titleBar,'mousedown',o.startDrag,false);
+                        };
+
+                        tr.appendChild(this.titleBar);
+                        tr = null;
+
+                        var span = document.createElement('span');
+                        span.appendChild(document.createTextNode(nbsp));
+                        span.className = !this.dragDisabled ? "month-display drag-enabled" : "month-display";
+                        this.titleBar.appendChild(span);
+
+                        span = document.createElement('span');
+                        span.appendChild(document.createTextNode(nbsp));
+                        span.className = !this.dragDisabled ? "year-display drag-enabled" : "year-display";
+                        this.titleBar.appendChild(span);
+
+                        span = null;
+
+                        tr  = document.createElement('tr');
+                        tableHead.appendChild(tr);
+
+                        createThAndButton(tr, [
+                        {className:"prev-but prev-year", id:"-prev-year-but", text:"\u00AB", title:getTitleTranslation(2), onmousedown:function(e) { addEvent(document, "mouseup", o.events.clearTimer);  o.events.incDec(e,0,-1,0); }, onmouseout:this.events.clearTimer },
+                        {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 },
+                        {colspan:this.showWeeks ? 4 : 3, className:"today-but", id:"-today-but", text:getTitleTranslation(4), onclick:this.events.gotoToday},
+                        {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 },
+                        {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 }]);
+
+                        tableBody = document.createElement('tbody');
+                        this.table.appendChild(tableBody);
+
+                        var colspanTotal = this.showWeeks ? 8 : 7,
+                            colOffset    = this.showWeeks ? 0 : -1,
+                            but, abbr;   
+                
+                        for(var rows = 0; rows < 7; rows++) {
+                                row = document.createElement('tr');
+
+                                if(rows != 0) {
+                                        tableBody.appendChild(row);   
+                                } else {
+                                        tableHead.appendChild(row);
+                                };
+
+                                for(var cols = 0; cols < colspanTotal; cols++) {
+                                                                                
+                                        if(rows === 0 || (this.showWeeks && cols === 0)) {
+                                                col = document.createElement('th');
+                                        } else {
+                                                col = document.createElement('td');
+                                        };
+                                        
+                                        /*@cc_on@*/
+                                        /*@if(@_win32)
+                                        col.unselectable = "on";
+                                        /*@end@*/  
+                                        
+                                        row.appendChild(col);
+                                        if((this.showWeeks && cols > 0 && rows > 0) || (!this.showWeeks && rows > 0)) {
+                                                col.onclick = this.events.onclick;
+                                        } else {
+                                                if(rows === 0 && cols > colOffset) {
+                                                        col.className = "date-picker-day-header";
+                                                        col.scope = "col";                                           
+                                                } else {
+                                                        col.className = "date-picker-week-header";
+                                                        col.scope = "row";
+                                                };
+                                        };
+                                };
+                        };
+
+                        col = row = null; 
+                
+                        this.ths = this.table.getElementsByTagName('thead')[0].getElementsByTagName('tr')[2].getElementsByTagName('th');
+                        for (var y = 0; y < colspanTotal; y++) {
+                                if(y == 0 && this.showWeeks) {
+                                        this.ths[y].appendChild(document.createTextNode(getTitleTranslation(6)));
+                                        this.ths[y].title = getTitleTranslation(8);
+                                        continue;
+                                };
+
+                                if(y > (this.showWeeks ? 0 : -1)) {
+                                        but = document.createElement("span");
+                                        but.className = "fd-day-header";
+                                        but.onclick = this.ths[y].onclick = this.setFirstDayOfWeek;
+                                        /*@cc_on@*/
+                                        /*@if(@_win32)
+                                        but.unselectable = "on";
+                                        /*@end@*/
+                                        this.ths[y].appendChild(but);
+                                };
+                        };
+                
+                        but = null; 
+                                        
+                        this.trs             = this.table.getElementsByTagName('tbody')[0].getElementsByTagName('tr');
+                        this.tds             = this.table.getElementsByTagName('tbody')[0].getElementsByTagName('td');
+                        this.butPrevYear     = document.getElementById(this.id + "-prev-year-but");
+                        this.butPrevMonth    = document.getElementById(this.id + "-prev-month-but");
+                        this.butToday        = document.getElementById(this.id + "-today-but");
+                        this.butNextYear     = document.getElementById(this.id + "-next-year-but"); 
+                        this.butNextMonth    = document.getElementById(this.id + "-next-month-but");
+        
+                        if(this.noToday) {
+                                this.butToday.style.display = "none";        
+                        };
+                        
+                        if(this.showWeeks) {
+                                this.wkThs = this.table.getElementsByTagName('tbody')[0].getElementsByTagName('th');
+                                this.div.className += " weeks-displayed";
+                        };
+
+                        tableBody = tableHead = tr = createThAndButton = createTH = null;
+
+                        if(this.low && this.high && (this.high - this.low < 7)) { this.equaliseDates(); }; 
+                        
+                        this.setDateFromInput();                                       
+                        this.updateTableHeaders();
+                        this.created = true;                         
+                        this.callback("create", {id:this.id});                        
+                        this.updateTable();                         
+                        
+                        if(this.staticPos) {                                 
+                                this.visible = true;
+                                this.show();
+                                this.div.style.visibility = "visible";
+                                this.opacity = this.opacityTo;
+                        } else {                                     
+                                this.reposition();
+                                this.div.style.visibility = "visible";
+                                this.fade();
+                        };                                               
+                };
+                this.setFirstDayOfWeek = function(e) {
+                        e = e || document.parentWindow.event;
+                        var elem = e.target != null ? e.target : e.srcElement;
+                        while(elem.tagName.toLowerCase() != "th") elem = elem.parentNode;                         
+                        var cnt = o.showWeeks ? -1 : 0;
+                        while(elem.previousSibling) {
+                                elem = elem.previousSibling;
+                                if(elem.tagName.toLowerCase() == "th") cnt++;
+                        };
+                        o.firstDayOfWeek = (o.firstDayOfWeek + cnt) % 7;
+                        o.updateTableHeaders();
+                        return stopEvent(e);
+                };
+                this.fade = function() {
+                        window.clearTimeout(o.fadeTimer);
+                        o.fadeTimer = null;   
+                        var diff = Math.round(o.opacity + ((o.opacityTo - o.opacity) / 4)); 
+                        o.setOpacity(diff);  
+                        if(Math.abs(o.opacityTo - diff) > 3 && !o.noFadeEffect) {
+                                o.fadeTimer = window.setTimeout(o.fade, 50);
+                        } else {
+                                o.setOpacity(o.opacityTo);
+                                if(o.opacityTo == 0) {
+                                        o.div.style.display = "none";
+                                        o.visible = false;
+                                } else {
+                                        o.visible = true;
+                                };
+                        };
+                };          
+                this.events = {
+                        onblur:function(e) {                                    
+                                o.removeKeyboardEvents();                                 
+                                if(o.statusBar) { o.updateStatus(getTitleTranslation(9)); };
+                        },
+                        onfocus:function(e) {                                 
+                                o.addKeyboardEvents();                                 
+                                if(o.statusBar) { o.updateStatus(printFormattedDate(o.date, o.statusFormat, true)); };
+                        },
+                        onkeydown: function (e) {
+                                o.stopTimer();
+                                if(!o.visible) return false;
+
+                                if(e == null) e = document.parentWindow.event;
+                                var kc = e.keyCode ? e.keyCode : e.charCode;
+                                
+                                if( kc == 13 ) {
+                                        // RETURN/ENTER: close & select the date
+                                        var td = document.getElementById(o.id + "-date-picker-hover");                                         
+                                        if(!td || td.className.search(/cd-([0-9]{8})/) == -1 || td.className.search(/no-selection|out-of-range|day-disabled/) != -1) return stopEvent(e);
+                                        o.dateSet = new Date(o.date);
+                                        o.returnFormattedDate();
+                                        o.hide();
+                                        return stopEvent(e);
+                                } else if(kc == 27) {
+                                        // ESC: close, no date selection 
+                                        o.hide();
+                                        return stopEvent(e);
+                                } else if(kc == 32 || kc == 0) {
+                                        // SPACE: goto today's date 
+                                        o.date = new Date();
+                                        o.updateTable();
+                                        return stopEvent(e);
+                                };    
+                                 
+                                // Internet Explorer fires the keydown event faster than the JavaScript engine can
+                                // update the interface. The following attempts to fix this.
+                                /*@cc_on
+                                @if(@_win32)
+                                if(new Date().getTime() - o.interval.getTime() < 50) return stopEvent(e);
+                                o.interval = new Date();
+                                @end
+                                @*/
+                        
+                                if ((kc > 49 && kc < 56) || (kc > 97 && kc < 104)) {
+                                        if (kc > 96) kc -= (96-48);
+                                        kc -= 49;
+                                        o.firstDayOfWeek = (o.firstDayOfWeek + kc) % 7;
+                                        o.updateTableHeaders();
+                                        return stopEvent(e);
+                                };
+
+                                if ( kc < 33 || kc > 40 ) return true;
+
+                                var d = new Date(o.date), tmp, cursorYYYYMM = o.date.getFullYear() + pad(o.date.getMonth()+1); 
+
+                                // HOME: Set date to first day of current month
+                                if(kc == 36) {
+                                        d.setDate(1); 
+                                // END: Set date to last day of current month                                 
+                                } else if(kc == 35) {
+                                        d.setDate(daysInMonth(d.getMonth(),d.getFullYear())); 
+                                // PAGE UP & DOWN                                   
+                                } else if ( kc == 33 || kc == 34) {
+                                        var add = (kc == 34) ? 1 : -1; 
+                                        // CTRL + PAGE UP/DOWN: Moves to the same date in the previous/next year
+                                        if(e.ctrlKey) {                                                                                                               
+                                                d.setFullYear(d.getFullYear() + add);
+                                        // PAGE UP/DOWN: Moves to the same date in the previous/next month                                            
+                                        } else {                                                     
+                                                if(!((kc == 33 && o.currentYYYYMM > cursorYYYYMM) || (kc == 34 && o.currentYYYYMM < cursorYYYYMM))) {                                                    
+                                                        tmp = new Date(d);
+                                                        tmp.setDate(2);
+                                                        tmp.setMonth(d.getMonth() + add);                                         
+                                                        d.setDate(Math.min(d.getDate(), daysInMonth(tmp.getMonth(),tmp.getFullYear())));                                        
+                                                        d.setMonth(d.getMonth() + add);
+                                                };      
+                                        };                                 
+                                // LEFT ARROW                                    
+                                } else if ( kc == 37 ) {                                         
+                                        d = new Date(o.date.getFullYear(), o.date.getMonth(), o.date.getDate() - 1);                                       
+                                // RIGHT ARROW
+                                } else if ( kc == 39 || kc == 34) {                                         
+                                        d = new Date(o.date.getFullYear(), o.date.getMonth(), o.date.getDate() + 1 ); 
+                                // UP ARROW                                        
+                                } else if ( kc == 38 ) {                                          
+                                        d = new Date(o.date.getFullYear(), o.date.getMonth(), o.date.getDate() - 7);  
+                                // DOWN ARROW                                        
+                                } else if ( kc == 40 ) {                                          
+                                        d = new Date(o.date.getFullYear(), o.date.getMonth(), o.date.getDate() + 7);                                         
+                                };
+
+                                if(o.outOfRange(d)) return stopEvent(e);
+                                o.date = d;
+                        
+                                if(o.statusBar) { o.updateStatus(printFormattedDate(o.date, o.statusFormat, true)); };
+                                var t = String(o.date.getFullYear()) + pad(o.date.getMonth()+1) + pad(o.date.getDate())
+
+                                if(e.ctrlKey || (kc == 33 || kc == 34) || t < o.firstDateShown || t > o.lastDateShown) {                                         
+                                        o.updateTable(); 
+                                        o.interval = new Date();                                        
+                                } else {                                    
+                                        if(!o.noToday) { o.disableTodayButton(); }
+                                        o.removeHighlight();
+                                
+                                        var dt = "cd-" + o.date.getFullYear() + pad(o.date.getMonth()+1) + pad(o.date.getDate());
+                                            
+                                        for(var i = 0, td; td = o.tds[i]; i++) {  
+                                                td.className = td.className.replace(/date-picker-hover/g, "");                                               
+                                                if(td.className.search(dt) == -1) continue;                                                 
+                                                o.showHideButtons(o.date);
+                                                td.id = o.id + "-date-picker-hover";
+                                                td.className = td.className.replace(/date-picker-hover/g, "") + " date-picker-hover";
+                                                break;
+                                        };
+                                };
+
+                                return stopEvent(e);
+                        },
+                        gotoToday: function(e) {
+                                o.date = new Date();
+                                o.updateTable();
+                                return stopEvent(e);
+                        },
+                        onmousedown: function(e) {
+                                e = e || document.parentWindow.event;
+                                var el = e.target != null ? e.target : e.srcElement;
+                                while(el.parentNode) {
+                                        if(el.id && (el.id == "fd-" + o.id || el.id == "fd-but-" + o.id)) {
+                                                return true;
+                                        };
+                                        try { el = el.parentNode; } catch(err) { break; };
+                                };
+                                o.stopTimer();
+                                hideAll();
+                        },
+                        ontablemouseout:function(e) {
+                                e = e || document.parentWindow.event;
+                                var p = e.toElement || e.relatedTarget;
+                                while (p && p != this) try { p = p.parentNode } catch(e) { p = this; };
+                                if (p == this) return false;
+                                if(o.currentTR) {
+                                        o.currentTR.className = o.currentTR.className.replace('dp-row-highlight', '');
+                                        o.currentTR = null;
+                                };
+                                if(o.statusBar) { o.updateStatus(printFormattedDate(o.date, o.statusFormat, true)); };
+                        },
+                        ontablemouseover: function(e) {
+                                e = e || document.parentWindow.event;
+                                var el = e.target != null ? e.target : e.srcElement;
+                                while ( el.nodeType != 1 ) el = el.parentNode;
+
+                                if(!el || ! el.tagName) { return; };
+                                var statusText = getTitleTranslation(9);
+                                switch (el.tagName.toLowerCase()) {
+                                case "td":    
+                                        if(el.className.search(/date-picker-unused|out-of-range/) != -1) {
+                                                statusText = getTitleTranslation(9);
+                                        } else if(el.className.search(/cd-([0-9]{8})/) == -1) {
+                                                break;
+                                        } else {                                                
+                                                o.stopTimer();
+                                                var cellDate = el.className.match(/cd-([0-9]{8})/)[1];                                                                              
+                                                o.removeHighlight();
+                                                el.id = o.id+"-date-picker-hover";
+                                                el.className = el.className.replace(/date-picker-hover/g, "") + " date-picker-hover";                                                 
+                                                o.date = new Date(cellDate.substr(0,4),cellDate.substr(4,2)-1,cellDate.substr(6,2));                                                
+                                                if(!o.noToday) { o.disableTodayButton(); };
+                                                statusText = printFormattedDate(o.date, o.statusFormat, true);
+
+                                        };
+                                        break;
+                                case "th":
+                                        if(!o.statusBar) { break; };
+                                        if(el.className.search(/drag-enabled/) != -1) {
+                                                statusText = getTitleTranslation(10);
+                                        } else if(el.className.search(/date-picker-week-header/) != -1) {
+                                                var txt = el.firstChild ? el.firstChild.nodeValue : "";
+                                                statusText = txt.search(/^(\d+)$/) != -1 ? getTitleTranslation(7, [txt, txt < 3 && o.date.getMonth() == 11 ? getWeeksInYear(o.date.getFullYear()) + 1 : getWeeksInYear(o.date.getFullYear())]) : getTitleTranslation(9);
+                                        };
+                                        break;
+                                case "span":
+                                        if(!o.statusBar) { break; };
+                                        if(el.className.search(/drag-enabled/) != -1) {
+                                                statusText = getTitleTranslation(10);
+                                        } else if(el.className.search(/day-([0-6])/) != -1) {
+                                                var day = el.className.match(/day-([0-6])/)[1];
+                                                statusText = getTitleTranslation(11, [getDayTranslation(day, false)]);
+                                        } else if(el.className.search(/prev-year/) != -1) {
+                                                statusText = getTitleTranslation(2);
+                                        } else if(el.className.search(/prev-month/) != -1) {
+                                                statusText = getTitleTranslation(0);
+                                        } else if(el.className.search(/next-year/) != -1) {
+                                                statusText = getTitleTranslation(3);
+                                        } else if(el.className.search(/next-month/) != -1) {
+                                                statusText = getTitleTranslation(1);
+                                        } else if(el.className.search(/today-but/) != -1 && el.className.search(/disabled/) == -1) {
+                                                statusText = getTitleTranslation(12);
+                                        };
+                                        break;
+                                default:
+                                        statusText = "";
+                                };
+                                while(el.parentNode) {
+                                        el = el.parentNode;
+                                        if(el.nodeType == 1 && el.tagName.toLowerCase() == "tr") {
+                                                if(el == o.currentTR) break;
+                                                if(o.currentTR) {
+                                                        o.currentTR.className = o.currentTR.className.replace('dp-row-highlight', '');
+                                                };
+                                                el.className = el.className + " dp-row-highlight";
+                                                o.currentTR = el;
+                                                break;
+                                        };
+                                };                                                          
+                                if(o.statusBar && statusText) { o.updateStatus(statusText); };
+                        },
+                        onclick: function(e) {                                                  
+                                if(o.opacity != o.opacityTo || this.className.search(/date-picker-unused|out-of-range|day-disabled|no-selection/) != -1) return false;
+                                e = e || document.parentWindow.event;
+                                var el = e.target != null ? e.target : e.srcElement;
+                                while (el.nodeType != 1 || (el.tagName && el.tagName != "TD")) el = el.parentNode;
+                                var cellDate = el.className.match(/cd-([0-9]{8})/)[1];                                                                                                                                                                           
+                                o.date = new Date(cellDate.substr(0,4),cellDate.substr(4,2)-1,cellDate.substr(6,2));
+                                o.dateSet = new Date(o.date);                                 
+                                o.returnFormattedDate();
+                                if(!o.staticPos) { o.hide(); }
+                                else { o.updateTable();};
+                                o.stopTimer();
+                                return stopEvent(e);
+                        },
+                        incDec: function(e) {                            
+                                e = e || document.parentWindow.event;
+                                var el = e.target != null ? e.target : e.srcElement;
+                                if(el && el.className && el.className.search('fd-disabled') != -1) { return false; }                                
+                                o.timerInc      = 800;
+                                o.dayInc        = arguments[1];
+                                o.yearInc       = arguments[2];
+                                o.monthInc      = arguments[3];                         
+                                o.timerSet      = true;                                                
+                       
+                                o.updateTable();
+                                return true;
+                        },
+                        clearTimer: function(e) {
+                                o.stopTimer();
+                                o.timerInc      = 800;
+                                o.yearInc       = 0;
+                                o.monthInc      = 0;
+                                o.dayInc        = 0;
+                                removeEvent(document, "mouseup", o.events.clearTimer);
+                        }
+                };
+        
+                this.setFormElementEvents = function() {
+                        var elem = this.getElem();
+                        if(elem && elem.tagName.search(/select|input/i) != -1) {                                         
+                                addEvent(elem, "change", o.changeHandler);
+                                if(this.splitDate) {                                                                         
+                                        addEvent(document.getElementById(this.id + splitAppend[1]), "change", o.changeHandler);
+                                        addEvent(document.getElementById(this.id + splitAppend[0]), "change", o.changeHandler);
+                                };
+                        };
+                };                 
+                
+                var o = this;
+                
+                o.setFormElementEvents();
+                
+                if(this.staticPos) { this.create(); this.setDateFromInput(); }
+                else { 
+                        this.createButton();
+                        this.setDateFromInput();                         
+                };
+        };
+        datePicker.prototype.createButton = function() {
+                
+                if(this.staticPos || document.getElementById("fd-but-" + this.id)) { return; };
+
+                var inp         = this.getElem(),
+                    span        = document.createElement('span'),
+                    but         = document.createElement('a');
+
+                but.href        = "#";
+                but.className   = "date-picker-control";
+                but.title       = getTitleTranslation(5);
+                but.id          = "fd-but-" + this.id;
+
+                span.appendChild(document.createTextNode(nbsp));
+                but.appendChild(span);
+
+                if(this.buttonWrapper && document.getElementById(this.buttonWrapper)) {
+                        document.getElementById(this.buttonWrapper).appendChild(but);
+                } else if(inp.nextSibling) {
+                        inp.parentNode.insertBefore(but, inp.nextSibling);
+                } else {
+                        inp.parentNode.appendChild(but);
+                };                   
+
+                but.onclick = but.onpress = function(e) {
+                        e = e || window.event;                      
+                
+                        var inpId     = this.id.replace('fd-but-',''),
+                            dpVisible = isVisible(inpId);  
+                
+                        if(e.type == "press") {
+                                var kc = e.keyCode != null ? e.keyCode : e.charCode;
+                                if(kc != 13) return true; 
+                                if(dpVisible) {
+                                        this.className = this.className.replace("dp-button-active", "");
+                                        datePickerController.hideAll();
+                                        return false;
+                                };
+                        };
+
+                        this.className = this.className.replace("dp-button-active", "");
+                        
+                        if(!dpVisible) {
+                                this.className += " dp-button-active";
+                                hideAll(inpId);
+                                showDatePicker(inpId);
+                        } else {
+                                hideAll();
+                        };
+                
+                        return false;
+                };
+        
+                but = null;
+        };  
+        datePicker.prototype.setRangeLow = function(range) {
+                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;                
+                if(this.created) { this.updateTable(); };
+        };
+        datePicker.prototype.setRangeHigh = function(range) {
+                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;                
+                if(this.created) { this.updateTable(); };
+        };
+        datePicker.prototype.setDisabledDays = function(dayArray) {
+                this.disabledDays = dayArray;
+                if(this.created) { this.updateTable(); };
+        };
+        datePicker.prototype.setDisabledDates = function(dateArray) {                
+                this.disabledDates = {};
+                this.addDisabledDates(dateArray);                
+        }; 
+        datePicker.prototype.addDisabledDates = function(dateArray) {
+                var disabledDateObj = {};
+                if(typeof dateArray !== "object") dateArray = [dateArray];                
+                for(var i = dateArray.length; i-- ;) {
+                        if(dateArray[i].match(/^(\d\d\d\d|\*\*\*\*)(0[1-9]|1[012]|\*\*)(0[1-9]|[12][0-9]|3[01])$/) != -1) {
+                                this.disabledDates[dateArray[i]] = 1;
+                        };
+                }; 
+                if(this.created) { this.updateTable(); };                                  
+        };
+        datePicker.prototype.addKeyboardEvents = function() {
+                addEvent(document, "keypress", this.events.onkeydown);
+                /*@cc_on
+                @if(@_win32)
+                removeEvent(document, "keypress", this.events.onkeydown);
+                addEvent(document, "keydown", this.events.onkeydown);
+                @end
+                @*/
+                if(window.devicePixelRatio) {
+                        removeEvent(document, "keypress", this.events.onkeydown);
+                        addEvent(document, "keydown", this.events.onkeydown);
+                };
+        };  
+        datePicker.prototype.removeKeyboardEvents = function() {
+                removeEvent(document, "keypress", this.events.onkeydown);
+                removeEvent(document, "keydown",  this.events.onkeydown);
+        };
+        datePicker.prototype.removeHighlight = function() {
+                var el = document.getElementById(this.id+"-date-picker-hover");
+                if(el) {
+                        el.className = el.className.replace("date-picker-hover", "");
+                        el.id = "";                                                                
+                };
+        };
+        datePicker.prototype.stopTimer = function() {
+                this.timerSet = false;
+                window.clearTimeout(this.timer);
+        };
+        datePicker.prototype.setOpacity = function(op) {
+                this.div.style.opacity = op/100;
+                this.div.style.filter = 'alpha(opacity=' + op + ')';
+                this.opacity = op;
+        };         
+        datePicker.prototype.getElem = function() {
+                return document.getElementById(this.id.replace(/^fd-/, '')) || false;
+        };
+        datePicker.prototype.getDisabledDates = function(y, m) {
+                m = pad(m);                 
+                
+                var obj = {},            
+                    lower  = this.firstDateShown,
+                    upper  = this.lastDateShown,             
+                    dt1, dt2, rngLower, rngUpper;  
+                
+                if(!upper || !lower) {
+                        lower = this.firstDateShown = y + pad(m) + "01";
+                        upper = this.lastDateShown  = y + pad(m) + pad(daysInMonth(m, y));                        
+                };
+                
+                for(var dt in this.disabledDates) {                            
+                        dt1 = dt.replace(/^(\*\*\*\*)/, y).replace(/^(\d\d\d\d)(\*\*)/, "$1"+m);
+                        dt2 = this.disabledDates[dt];
+
+                        if(dt2 == 1) {                                 
+                                if(+lower <= +dt1 && +upper >= +dt1) {
+                                        obj[dt1] = 1;                                         
+                                };
+                                continue;
+                        };
+
+                        // Range of disabled dates                        
+                        if(Number(dt1.substr(0,6)) <= +String(this.firstDateShown).substr(0,6) && Number(dt2.substr(0,6)) >= +String(this.lastDateShown).substr(0,6)) {
+                                // Same month
+                                if(Number(dt1.substr(0,6)) == Number(dt2.substr(0,6))) {
+                                        for(var i = dt1; i <= dt2; i++) {
+                                                obj[i] = 1;
+                                        };
+                                        continue;
+                                };
+
+                                // Different months but we only want this month
+                                rngLower = Number(dt1.substr(0,6)) == +String(this.firstDateShown).substr(0,6) ? dt1 : lower;
+                                rngUpper = Number(dt2.substr(0,6)) == +String(this.lastDateShown).substr(0,6) ? dt2 : upper;
+                                for(var i = +rngLower; i <= +rngUpper; i++) {
+                                        obj[i] = 1;                                        
+                                };
+                        };
+                };
+                
+                for(dt in this.enabledDates) {
+                        dt1 = dt.replace(/^(\*\*\*\*)/, y).replace(/^(\d\d\d\d)(\*\*)/, "$1"+m);
+                        dt2 = this.enabledDates[dt];
+
+                        if(dt2 == 1) {
+                                if(dt1 in obj) {                                          
+                                        obj[dt1] = null;
+                                        delete obj[dt1];
+                                };
+                                continue;
+                        };
+
+                        // Range
+                        if(Number(dt1.substr(0,6)) <= +String(this.firstDateShown).substr(0,6) && Number(dt2.substr(0,6)) >= +String(this.lastDateShown).substr(0,6)) {
+                                // Same month
+                                if(Number(dt1.substr(0,6)) == Number(dt2.substr(0,6))) {
+                                        for(var i = dt1; i <= dt2; i++) {
+                                                if(i in obj) {
+                                                        obj[i] = null;
+                                                        delete obj[i];
+                                                };
+                                        };
+                                        continue;
+                                };
+
+                                // Different months but we only want this month
+                                rngLower = Number(dt1.substr(0,6)) == +String(this.firstDateShown).substr(0,6) ? dt1 : lower;
+                                rngUpper = Number(dt2.substr(0,6)) == +String(this.lastDateShown).substr(0,6) ? dt2 : upper;
+                                for(var i = +rngLower; i <= +rngUpper; i++) {
+                                        if(i in obj) {
+                                                obj[i] = null;
+                                                delete obj[i];
+                                        };
+                                };
+                        };
+                };
+                return obj;
+        };
+        datePicker.prototype.truePosition = function(element) {
+                var pos = this.cumulativeOffset(element);
+                if(window.opera) { return pos; };
+                var iebody      = (document.compatMode && document.compatMode != "BackCompat")? document.documentElement : document.body,
+                    dsocleft    = document.all ? iebody.scrollLeft : window.pageXOffset,
+                    dsoctop     = document.all ? iebody.scrollTop  : window.pageYOffset,
+                    posReal     = this.realOffset(element);
+                return [pos[0] - posReal[0] + dsocleft, pos[1] - posReal[1] + dsoctop];
+        };
+        datePicker.prototype.realOffset = function(element) {
+                var t = 0, l = 0;
+                do {
+                        t += element.scrollTop  || 0;
+                        l += element.scrollLeft || 0;
+                        element = element.parentNode;
+                } while(element);
+                return [l, t];
+        };
+        datePicker.prototype.cumulativeOffset = function(element) {
+                var t = 0, l = 0;
+                do {
+                        t += element.offsetTop  || 0;
+                        l += element.offsetLeft || 0;
+                        element = element.offsetParent;
+                } while(element);
+                return [l, t];
+        };
+        datePicker.prototype.equaliseDates = function() {
+                var clearDayFound = false, tmpDate;
+                for(var i = this.low; i <= this.high; i++) {
+                        tmpDate = String(i);
+                        if(!this.disabledDays[new Date(tmpDate.substr(0,4), tmpDate.substr(6,2), tmpDate.substr(4,2)).getDay() - 1]) {
+                                clearDayFound = true;
+                                break;
+                        };
+                };
+                if(!clearDayFound) { this.disabledDays = [0,0,0,0,0,0,0] };
+        };
+        datePicker.prototype.outOfRange = function(tmpDate) {
+                if(!this.low && !this.high) { return false; };
+
+                var level = false;
+                if(!tmpDate) {
+                        level   = true;
+                        tmpDate = this.date;
+                };
+
+                var d  = pad(tmpDate.getDate()),
+                    m  = pad(tmpDate.getMonth() + 1),
+                    y  = tmpDate.getFullYear(),
+                    dt = String(y)+String(m)+String(d);
+
+                if(this.low && +dt < +this.low) {
+                        if(!level) return true;
+                        this.date = new Date(this.low.substr(0,4), this.low.substr(4,2)-1, this.low.substr(6,2), 5, 0, 0);
+                        return false;
+                };
+                if(this.high && +dt > +this.high) {
+                        if(!level) return true;
+                        this.date = new Date(this.high.substr(0,4), this.high.substr(4,2)-1, this.high.substr(6,2), 5, 0, 0);
+                };
+                return false;
+        };         
+        datePicker.prototype.updateStatus = function(msg) {
+                while(this.statusBar.firstChild) { this.statusBar.removeChild(this.statusBar.firstChild); };
+                if(msg && this.statusFormat.search(/-S|S-/) != -1) {
+                        msg = msg.replace(/([0-9]{1,2})(st|nd|rd|th)/, "$1<sup>$2</sup>");
+                        msg = msg.split(/<sup>|<\/sup>/);
+                        var dc = document.createDocumentFragment();
+                        for(var i = 0, nd; nd = msg[i]; i++) {
+                                if(/^(st|nd|rd|th)$/.test(nd)) {
+                                        var sup = document.createElement("sup");
+                                        sup.appendChild(document.createTextNode(nd));
+                                        dc.appendChild(sup);
+                                } else {
+                                        dc.appendChild(document.createTextNode(nd));
+                                };
+                        };
+                        this.statusBar.appendChild(dc);
+                } else {
+                        this.statusBar.appendChild(document.createTextNode(msg ? msg : getTitleTranslation(9)));
+                };
+        };
+        datePicker.prototype.setDateFromInput = function() {
+                this.dateSet = null;
+
+                var elem = this.getElem(), 
+                    upd  = false, 
+                    dt;
+                    
+                if(!elem || elem.tagName.search(/select|input/i) == -1) return; 
+
+                if(!this.splitDate && elem.value.replace(/\s/g, "") !== "") {
+                        var dynFormatMasks = formatMasks.concat([this.format]).reverse();                                                
+                        for(var i = 0, fmt; fmt = dynFormatMasks[i]; i++) {
+                                dt = parseDateString(elem.value, fmt);                                                              
+                                if(dt) {                                    
+                                        upd = true;                                       
+                                        break;
+                                };
+                        };                                                                        
+                } else if(this.splitDate) {
+                        var mmN  = document.getElementById(this.id + splitAppend[1]),
+                            ddN  = document.getElementById(this.id + splitAppend[0]),
+                            tm   = parseInt(mmN.tagName.toLowerCase() == "input"  ? mmN.value  : mmN.options[mmN.selectedIndex || 0].value, 10),
+                            td   = parseInt(ddN.tagName.toLowerCase() == "input"  ? ddN.value  : ddN.options[ddN.selectedIndex || 0].value, 10),
+                            ty   = parseInt(elem.tagName.toLowerCase() == "input" ? elem.value : elem.options[elem.selectedIndex || 0].value, 10);
+                                             
+                        if(!(/\d\d\d\d/.test(ty)) || !(/^(0?[1-9]|1[012])$/.test(tm)) || !(/^(0?[1-9]|[12][0-9]|3[01])$/.test(td))) {
+                                dt = false;
+                        } else {
+                                if(+td > daysInMonth(+tm - 1, +ty)) {                                         
+                                        upd = true;
+                                        td  = daysInMonth(+tm - 1, +ty); 
+                                        dt  = new Date(ty,tm-1,td);
+                                } else {
+                                        dt = new Date(ty,tm-1,td);
+                                };
+                        };                        
+                };
+
+                if(!dt || isNaN(dt)) {                                                              
+                        this.date = new Date();
+                        this.date.setHours(5);
+                        this.outOfRange();
+                        return;
+                };
+
+                dt.setHours(5);
+                this.date = new Date(dt);                            
+                this.outOfRange();                 
+                
+                var dtYYYYMMDD = dt.getFullYear() + pad(dt.getMonth() + 1) + pad(dt.getDate()),
+                    weekDay    = ( dt.getDay() + 6 ) % 7;
+                
+                if(dt.getTime() == this.date.getTime() && !(dtYYYYMMDD in this.dynDisabledDates || this.disabledDays[weekDay])) {                        
+                        this.dateSet = new Date(this.date);
+                };
+                
+                if(upd) { this.returnFormattedDate(); };
+        };
+        datePicker.prototype.setSelectIndex = function(elem, indx) {
+                for(var opt = elem.options.length-1; opt >= 0; opt--) {
+                        if(elem.options[opt].value == +indx) {
+                                elem.selectedIndex = opt;
+                                return;
+                        };
+                };
+        };
+        datePicker.prototype.returnFormattedDate = function() {
+                
+                var elem = this.getElem();
+                if(!elem) return;
+
+                var d                   = pad(this.date.getDate()),
+                    m                   = pad(this.date.getMonth() + 1),
+                    yyyy                = this.date.getFullYear(),
+                    disabledDates       = this.getDisabledDates(+yyyy, +m),
+                    weekDay             = (this.date.getDay() + 6) % 7;
+                
+                if(!(this.disabledDays[weekDay] || String(yyyy)+m+d in this.disabledDates)) {
+                        if(this.splitDate) {
+                                var ddE = document.getElementById(this.id+splitAppend[0]),
+                                    mmE = document.getElementById(this.id+splitAppend[1]);
+                                    
+                                if(ddE.tagName.toLowerCase() == "input") { ddE.value = d; }
+                                else { this.setSelectIndex(ddE, d); };
+                                if(mmE.tagName.toLowerCase() == "input") { mmE.value = m; }
+                                else { this.setSelectIndex(mmE, m); };
+                                if(elem.tagName.toLowerCase() == "input") elem.value = yyyy;
+                                else { this.setSelectIndex(elem, yyyy); };
+                                
+                        } else if(elem.tagName.toLowerCase() == "input") {                                                                
+                                elem.value = printFormattedDate(this.date, this.format);                                
+                        };
+                        
+                        if(elem.type && elem.type != "hidden") { elem.focus(); }                         
+                                                                  
+                        this.callback("dateselect", { "id":this.id, "date":this.dateSet, "dd":d, "mm":m, "yyyy":yyyy });                        
+                        
+                        if(this.staticPos) { this.updateTable(); };                                 
+                };                        
+        };
+        datePicker.prototype.disableTodayButton = function() {
+                var today = new Date();                     
+                this.butToday.className = this.butToday.className.replace("fd-disabled", "");
+                if(this.outOfRange(today) || (this.date.getDate() == today.getDate() && this.date.getMonth() == today.getMonth() && this.date.getFullYear() == today.getFullYear())) {
+                        this.butToday.className += " fd-disabled";
+                        this.butToday.onclick = null;
+                } else {
+                        this.butToday.onclick = this.events.gotoToday;
+                };
+        };
+        datePicker.prototype.updateTableHeaders = function() {
+                var colspanTotal = this.showWeeks ? 8 : 7,
+                    colOffset    = this.showWeeks ? 1 : 0,
+                    d, but;
+
+                for(var col = colOffset; col < colspanTotal; col++ ) {
+                        d = (this.firstDayOfWeek + (col - colOffset)) % 7;
+                        this.ths[col].title = getDayTranslation(d, false);
+
+                        if(col > colOffset) {
+                                but = this.ths[col].getElementsByTagName("span")[0];
+                                while(but.firstChild) { but.removeChild(but.firstChild); };
+                                but.appendChild(document.createTextNode(getDayTranslation(d, true)));
+                                but.title = this.ths[col].title;
+                                but.className = but.className.replace(/day-([0-6])/, "") + " day-" + d;
+                                but = null;
+                        } else {
+                                while(this.ths[col].firstChild) { this.ths[col].removeChild(this.ths[col].firstChild); };
+                                this.ths[col].appendChild(document.createTextNode(getDayTranslation(d, true)));
+                        };
+
+                        this.ths[col].className = this.ths[col].className.replace(/date-picker-highlight/g, "");
+                        if(this.highlightDays[d]) {
+                                this.ths[col].className += " date-picker-highlight";
+                        };
+                };
+                
+                if(this.created) { this.updateTable(); }
+        };
+
+        datePicker.prototype.callback = function(type, args) {                                                     
+                if(!type || !(type in this.callbacks)) return false;
+                
+                var ret = false;                   
+                for(var func = 0; func < this.callbacks[type].length; func++) {                         
+                        ret = this.callbacks[type][func](args || this.id);
+                        if(!ret) return false;
+                };                      
+                return ret;
+        };
+        
+        datePicker.prototype.showHideButtons = function(tmpDate) {
+                var tdm = tmpDate.getMonth(),
+                    tdy = tmpDate.getFullYear();
+
+                this.butPrevYear.className = this.butPrevYear.className.replace("fd-disabled", "");
+                if(this.outOfRange(new Date((tdy - 1), tdm, daysInMonth(+tdm, tdy-1)))) {
+                        this.butPrevYear.className += " fd-disabled";
+                        if(this.yearInc == -1) this.stopTimer();
+                };    
+                
+                this.butPrevMonth.className = this.butPrevMonth.className.replace("fd-disabled", "");
+                if(this.outOfRange(new Date(tdy, (+tdm - 1), daysInMonth(+tdm-1, tdy)))) {
+                        this.butPrevMonth.className += " fd-disabled";
+                        if(this.monthInc == -1) this.stopTimer();
+                };
+         
+                this.butNextYear.className = this.butNextYear.className.replace("fd-disabled", "");
+                if(this.outOfRange(new Date((tdy + 1), +tdm, 1))) {
+                        this.butNextYear.className += " fd-disabled";
+                        if(this.yearInc == 1) this.stopTimer();
+                };
+                
+                this.butNextMonth.className = this.butNextMonth.className.replace("fd-disabled", "");
+                if(this.outOfRange(new Date(tdy, +tdm + 1, 1))) {
+                        this.butNextMonth.className += " fd-disabled";
+                        if(this.monthInc == 1) this.stopTimer();
+                };
+        };        
+        var localeDefaults = {
+                fullMonths:["January","February","March","April","May","June","July","August","September","October","November","December"],
+                monthAbbrs:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],
+                fullDays:  ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],
+                dayAbbrs:  ["Mon","Tue","Wed","Thu","Fri","Sat","Sun"],
+                titles:    ["Previous month","Next month","Previous year","Next year", "Today", "Show Calendar", "wk", "Week [[%0%]] of [[%1%]]", "Week", "Select a date", "Click \u0026 Drag to move", "Display \u201C[[%0%]]\u201D first", "Go to Today\u2019s date"],
+                imported:  false
+        };        
+        var grepRangeLimits = function(sel) {
+                var range = [];
+                for(var i = 0; i < sel.options.length; i++) {
+                        if(sel.options[i].value.search(/^\d\d\d\d$/) == -1) { continue; };
+                        if(!range[0] || Number(sel.options[i].value) < range[0]) { range[0] = Number(sel.options[i].value); };
+                        if(!range[1] || Number(sel.options[i].value) > range[1]) { range[1] = Number(sel.options[i].value); };
+                };
+                return range;
+        };
+        var joinNodeLists = function() {
+                if(!arguments.length) { return []; }
+                var nodeList = [];
+                for (var i = 0; i < arguments.length; i++) {
+                        for (var j = 0, item; item = arguments[i][j]; j++) {
+                                nodeList[nodeList.length] = item;
+                        };
+                };
+                return nodeList;
+        };
+        var cleanUp = function() {
+                var dp;
+                for(dp in datePickers) {
+                        if(!document.getElementById(datePickers[dp].id)) {
+                                if(datePickers[dp].created) datePickers[dp].destroy();
+                                datePickers[dp] = null;
+                                delete datePickers[dp];
+                        };
+                };
+        };         
+        var hideAll = function(exception) {
+                var dp;
+                for(dp in datePickers) {
+                        if(!datePickers[dp].created || datePickers[dp].staticPos || (exception && exception == datePickers[dp].id)) continue;
+                        datePickers[dp].hide();
+                };
+        };
+        var showDatePicker = function(inpID) {
+                if(!(inpID in datePickers)) return false;                 
+                datePickers[inpID].show();
+                return true;        
+        };
+        var destroy = function() {
+                for(dp in datePickers) {
+                        if(datePickers[dp].created) datePickers[dp].destroy();
+                        datePickers[dp] = null;
+                        delete datePickers[dp];
+                };
+                datePickers = null;
+                removeEvent(window, 'load',   datePickerController.create);
+                removeEvent(window, 'unload', datePickerController.destroy);
+        }; 
+        var getTitleTranslation = function(num, replacements) {
+                replacements = replacements || [];
+                if(localeImport.titles.length > num) {
+                         var txt = localeImport.titles[num];
+                         if(replacements && replacements.length) {
+                                for(var i = 0; i < replacements.length; i++) {
+                                        txt = txt.replace("[[%" + i + "%]]", replacements[i]);
+                                };
+                         };
+                         return txt.replace(/[[%(\d)%]]/g,"");
+                };
+                return "";
+        };
+        var getDayTranslation = function(day, abbreviation) {
+                var titles = localeImport[abbreviation ? "dayAbbrs" : "fullDays"];
+                return titles.length && titles.length > day ? titles[day] : "";
+        };
+        var getMonthTranslation = function(month, abbreviation) {
+                var titles = localeImport[abbreviation ? "monthAbbrs" : "fullMonths"];
+                return titles.length && titles.length > month ? titles[month] : "";
+        };
+        var daysInMonth = function(nMonth, nYear) {
+                nMonth = (nMonth + 12) % 12;
+                return (((0 == (nYear%4)) && ((0 != (nYear%100)) || (0 == (nYear%400)))) && nMonth == 1) ? 29: [31,28,31,30,31,30,31,31,30,31,30,31][nMonth];
+        };
+        var getWeeksInYear = function(Y) {
+                if(Y in weeksInYearCache) {
+                        return weeksInYearCache[Y];
+                };
+                var X1, X2, NW;
+                with (X1 = new Date(Y, 0, 4)) {
+                        setDate(getDate() - (6 + getDay()) % 7);
+                };
+                with (X2 = new Date(Y, 11, 28)) {
+                        setDate(getDate() + (7 - getDay()) % 7);
+                };
+                weeksInYearCache[Y] = Math.round((X2 - X1) / 604800000);
+                return weeksInYearCache[Y];
+        };
+        var parseRangeFromString = function(str) {
+                if(!str) return "";
+                
+                var low = str.search(/^range-low-/) != -1;
+                str = str.replace(/range-(low|high)-/, "");
+
+                if(str.search(/^(\d\d\d\d)(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])$/) != -1) { return str; };
+
+                var tmpDate = new Date();
+                
+                if(str.search(/^today$/) != -1) { return tmpDate.getFullYear() + pad(tmpDate.getMonth() + 1) + pad(tmpDate.getDate()); };
+                
+                var regExp = /^(\d)-(day|week|month|year)$/;
+                
+                if(str.search(regExp) != -1) {
+                        var parts       = str.match(regExp),
+                            acc         = { day:0,week:0,month:0,year:0 };
+                            
+                        acc[parts[2]]   = low ? -(+parts[1]) : +parts[1];
+                        tmpDate.setFullYear(tmpDate.getFullYear() + +acc.year);
+                        tmpDate.setMonth(tmpDate.getMonth() + +acc.month);
+                        tmpDate.setDate(tmpDate.getDate() + +acc.day + (7 * +acc.week));
+                        return !tmpDate || isNaN(tmpDate) ? "" : tmpDate.getFullYear() + pad(tmpDate.getMonth() + 1) + pad(tmpDate.getDate());
+                };
+                
+                return "";
+        };
+        var getWeekNumber = function(y,m,d) {
+                var d = new Date(y, m, d, 0, 0, 0);
+                var DoW = d.getDay();
+                d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu
+                var ms = d.valueOf(); // GMT
+                d.setMonth(0);
+                d.setDate(4); // Thu in Week 1
+                return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1;
+        };
+        var printFormattedDate = function(date, fmt, useImportedLocale) {
+                if(!date || isNaN(date)) { return ""; };
+                
+                var parts = fmt.split("-"),
+                      str = [],
+                        d = date.getDate(),
+                        D = date.getDay(),
+                        m = date.getMonth(),
+                        y = date.getFullYear(),
+                    flags = {
+                                "sp":" ",
+                                "dt":".",
+                                "sl":"/",
+                                "ds":"-",
+                                "cc":",",
+                                "d":pad(d),
+                                "D":useImportedLocale ? localeImport.dayAbbrs[D == 0 ? 6 : D - 1] : localeDefaults.dayAbbrs[D == 0 ? 6 : D - 1],
+                                "l":useImportedLocale ? localeImport.fullDays[D == 0 ? 6 : D - 1] : localeDefaults.fullDays[D == 0 ? 6 : D - 1],
+                                "j":d,
+                                "N":D == 0 ? 7 : D,
+                                "w":D,
+                                /*"S":String(d).substr(-(Math.min(String(d).length, 2))) > 3 && String(d).substr(-(Math.min(String(d).length, 2))) < 21 ? "th" : ["th", "st", "nd", "rd", "th"][Math.min(+d%10, 4)],*/
+                                "z":"?",
+                                "W":getWeekNumber(date),
+                                "M":useImportedLocale ? localeImport.monthAbbrs[m] : localeDefaults.monthAbbrs[m],
+                                "F":useImportedLocale ? localeImport.fullMonths[m] : localeDefaults.fullMonths[m],
+                                "m":pad(++m),
+                                "n":++m,
+                                "t":daysInMonth(++m, y),
+                                "Y":y,
+                                "o":y,
+                                "y":String(y).substr(2,2),
+                                "S":["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
+                            };
+
+                for(var pt = 0, part; part = parts[pt]; pt++) {                        
+                        str.push(!(part in flags) ? "" : flags[part]);
+                };
+
+                return str.join("");
+        };
+        var parseDateString = function(str, fmt) {
+                var d     = false,
+                    m     = false,
+                    y     = false,
+                    now   = new Date(),
+                    parts = fmt.replace(/-sp(-sp)+/g, "-sp").split("-"),
+                    divds = { "dt":".","sl":"/","ds":"-","cc":"," };                    
+
+                loopLabel:
+                for(var pt = 0, part; part = parts[pt]; pt++) {                        
+                        if(str.length == 0) { return false; };
+                                
+                        switch(part) {
+                                // Dividers
+                                case "sp": // Space " "
+                                                if(str.charAt(0).search(/\s/) != -1) {
+                                                        // Be easy on multiple spaces...
+                                                        while(str.charAt(0).search(/\s/) != -1) { str = str.substr(1); };
+                                                        break;
+                                                } else return "";
+                                case "dt":
+                                case "sl":
+                                case "ds":
+                                case "cc":
+                                                if(str.charAt(0) == divds[part]) {
+                                                        str = str.substr(1);
+                                                        break;
+                                                } else return "";
+                                // DAY
+                                case "d": // Day of the month, 2 digits with leading zeros (01 - 31)
+                                case "j": // Day of the month without leading zeros (1 - 31)  
+                                          // Accept both when parsing                                                          
+                                                if(str.search(/^(3[01]|[12][0-9]|0?[1-9])/) != -1) {
+                                                        d = +str.match(/^(3[01]|[12][0-9]|0?[1-9])/)[0];
+                                                        str = str.substr(str.match(/^(3[01]|[12][0-9]|0?[1-9])/)[0].length);                                                        
+                                                        break;
+                                                } else return "";
+                                                
+                                case "D": // A textual representation of a day, three letters (Mon - Sun)
+                                case "l": // A full textual representation of the day of the week (Monday - Sunday)
+                                                l = part == "D" ? localeDefaults.dayAbbrs : localeDefaults.fullDays;
+                                                for(var i = 0; i < 7; i++) {
+                                                        if(new RegExp("^" + l[i], "i").test(str)) {
+                                                                str = str.substr(l[i].length);
+                                                                continue loopLabel;
+                                                        };
+                                                };
+                                                return "";
+                                /*
+                                case "j": // Day of the month without leading zeros (1 - 31)
+                                                if(str.search(/^([1-9]|[12][0-9]|3[01])/) != -1) {
+                                                        d = +str.match(/^([1-9]|[12][0-9]|3[01])/)[0];
+                                                        str = str.substr(str.match(/^(\s?[1-9]|[12][0-9]|3[01])/)[0].length);
+                                                        break;
+                                                } else return "";
+                                */
+                                case "N": // ISO-8601 numeric representation of the day of the week (added in PHP 5.1.0) 1 (for Monday) through 7 (for Sunday)
+                                case "w": // Numeric representation of the day of the week 0 (for Sunday) through 6 (for Saturday)
+                                                if(str.search(part == "N" ? /^([1-7])/ : /^([0-6])/) != -1) {
+                                                        str = str.substr(1);
+                                                        break;
+                                                } else return "";
+                                case "S": // English ordinal suffix for the day of the month, 2 characters: st, nd, rd or th
+                                                if(str.search(/^(st|nd|rd|th)/i) != -1) {
+                                                        str = str.substr(2);
+                                                        break;
+                                                } else return "";
+                                case "z": // The day of the year (starting from 0): 0 - 365
+                                                if(str.search(/^([0-9]|[1-9][0-9]|[12][0-9]{2}|3[0-5][0-9]|36[0-5])/) != -1) {
+                                                        str = str.substr(str.match(/^([0-9]|[1-9][0-9]|[12][0-9]{2}|3[0-5][0-9]|36[0-5])/)[0].length);
+                                                        break;
+                                                } else return "";
+                                // WEEK
+                                case "W": // ISO-8601 week number of year, weeks starting on Monday (added in PHP 4.1.0): 1 - 53
+                                                if(str.search(/^([1-9]|[1234[0-9]|5[0-3])/) != -1) {
+                                                        str = str.substr(str.match(/^([1-9]|[1234[0-9]|5[0-3])/)[0].length);
+                                                        break;
+                                                } else return "";
+                                // MONTH
+                                case "M": // A short textual representation of a month, three letters
+                                case "F": // A full textual representation of a month, such as January or March
+                                                l = localeDefaults.fullMonths.concat(localeDefaults.monthAbbrs); // : localeDefaults.fullMonths;
+                                                for(var i = 0; i < 24; i++) {
+                                                        if(str.search(new RegExp("^" + l[i],"i")) != -1) {
+                                                                str = str.substr(l[i].length);
+                                                                m = ((i + 12) % 12);                                                                 
+                                                                continue loopLabel;
+                                                        };
+                                                };
+                                                return "";
+                                case "m": // Numeric representation of a month, with leading zeros
+                                case "n": // Numeric representation of a month, without leading zeros
+                                                //l = part == "m" ? /^(0[1-9]|1[012])/ : /^([1-9]|1[012])/;
+                                                // Accept either when parsing
+                                                l = /^(1[012]|0?[1-9])/;
+                                                if(str.search(l) != -1) {
+                                                        m = +str.match(l)[0] - 1;
+                                                        str = str.substr(str.match(l)[0].length);
+                                                        break;
+                                                } else return "";
+                                case "t": // Number of days in the given month: 28 through 31
+                                                if(str.search(/2[89]|3[01]/) != -1) {
+                                                        str = str.substr(2);
+                                                        break;
+                                                } else return "";
+                                // YEAR
+                                case "Y": // A full numeric representation of a year, 4 digits
+                                case "o": // ISO-8601 year number. This has the same value as Y
+                                                if(str.search(/^(\d{4})/) != -1) {
+                                                        y = str.substr(0,4);
+                                                        str = str.substr(4);
+                                                        break;
+                                                } else return "";
+                                case "y": // A two digit representation of a year
+                                                if(str.search(/^(0[0-9]|[1-9][0-9])/) != -1) {
+                                                        y = +str.substr(0,2);
+                                                        y = +y < 50 ? '20' + y : '19' + y;
+                                                        str = str.substr(2);
+                                                        break;
+                                                } else return "";
+                                default:
+                                                return "";
+                        };
+                };   
+                
+                d = d === false ? now.getDate() : d;
+                m = m === false ? now.getMonth() - 1 : m;
+                y = y === false ? now.getFullYear() : y;
+                   
+                var tmpDate = new Date(y,m,d);
+                return isNaN(tmpDate) ? "" : tmpDate;
+        };
+        var repositionDatePickers = function(e) {
+                for(dp in datePickers) {
+                        if(!datePickers[dp].created || datePickers[dp].staticPos || (!datePickers[dp].staticPos && !datePickers[dp].dragDisabled)) continue;
+                        datePickers[dp].reposition();
+                };
+        };
+        var addDatePicker = function(options) {
+                if(!options.id) { throw "A datePicker requires an associated element with an id attribute"; };
+                if(options.id in datePickers) { return; };
+                var elem = document.getElementById(options.id);
+                if(!elem) throw "Cannot locate a datePicker's associated element with an id of:" + options.id;
+                if(elem.tagName.search(/select|input/i) == -1) {
+                        if(!("callbacks" in options) || !("dateselect" in options.callbacks)) {
+                                throw "A 'dateselect' callback function is required for datePickers not associated with a form element";
+                        };
+                        options.staticPos       = true;
+                        options.splitDate       = false;
+                        options.hideInput       = false;
+                        options.noFadeEffect    = true;
+                        options.dragDisabled    = true;
+                        options.positioned      = false;
+                } else if(!options.staticPos) {
+                        options.hideInput       = false;                                                 
+                } else {
+                        options.noFadeEffect    = true;
+                        options.dragDisabled    = true;
+                };
+
+                datePickers[options.id] = new datePicker(options);
+        };
+        var parseCallbacks = function(cbs) {
+                if(cbs == null) { return {}; };
+                var func,
+                    type,
+                    cbObj = {},
+                    parts,
+                    obj;
+                for(var i = 0, fn; fn = cbs[i]; i++) {
+                        type = fn.match(/(cb_(dateselect|redraw|create)_)([^\s|$]+)/i)[1].replace(/^cb_/i, "").replace(/_$/, "");
+                        fn   = fn.replace(/cb_(dateselect|redraw|create)_/i, "").replace(/-/g, ".");
+                        
+                        try {
+                                if(fn.indexOf(".") != -1) {
+                                        parts = fn.split('.');
+                                        obj   = window;
+                                        for (var x = 0, part; part = obj[parts[x]]; x++) {
+                                                if(part instanceof Function) {
+                                                        (function() {
+                                                                var method = part;
+                                                                func = function (data) { method.apply(obj, [data]) };
+                                                        })();
+                                                } else {
+                                                obj = part;
+                                                };
+                                        };
+                                } else {
+                                        func = window[fn];
+                                };
+
+                                if(!(func instanceof Function)) continue;
+                                if(!(type in cbObj)) { cbObj[type] = []; };
+                                cbObj[type][cbObj[type].length] = func;
+                        } catch (err) {};
+                };
+                return cbObj;
+        };
+        // Used by the button to dictate whether to open or close the datePicker
+        var isVisible = function(id) {
+                return (!id || !(id in datePickers)) ? false : datePickers[id].visible;
+        };                
+        var create = function(inp) {
+                if(!(typeof document.createElement != "undefined" && typeof document.documentElement != "undefined" && typeof document.documentElement.offsetWidth == "number")) { return; };
+
+                // Has the locale file loaded?
+                if(typeof(fdLocale) == "object" && !localeImport) {
+                        localeImport = {
+                                titles          : fdLocale.titles,
+                                fullMonths      : fdLocale.fullMonths,
+                                monthAbbrs      : fdLocale.monthAbbrs,
+                                fullDays        : fdLocale.fullDays,
+                                dayAbbrs        : fdLocale.dayAbbrs,
+                                firstDayOfWeek  : ("firstDayOfWeek" in fdLocale) ? fdLocale.firstDayOfWeek : 0,
+                                imported        : true
+                        };
+                } else if(!localeImport) {
+                        localeImport = localeDefaults;
+                };  
+                
+                var formElements = (inp && inp.tagName) ? [inp] : joinNodeLists(document.getElementsByTagName('input'), document.getElementsByTagName('select')),
+                    disableDays  = /disable-days-([1-7]){1,6}/g,
+                    highlight    = /highlight-days-([1-7]{1,7})/,
+                    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))/,
+                    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))/,
+                    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])))+/,
+                    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])))+/,                    
+                    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,
+                    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,
+                    callbacks    = /((cb_(dateselect|redraw|create)_)([^\s|$]+))/ig,
+                    positioned   = /display-inline-([^\s|$]+)/i,
+                    bPositioned  = /button-([^\s|$]+)/i,
+                    range,tmp,j,t,options,dts,parts;                  
+                    
+                for(var i = 0, elem; elem = formElements[i]; i++) {  
+                        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")) {
+                                
+                                if(elem.id && elem.id in datePickers) {                                                                                                                        
+                                        if(!datePickers[elem.id].staticPos) { datePickers[elem.id].createButton(); }
+                                        else { 
+                                                if(!document.getElementById("fd-" + elem.id)) {
+                                                        datePickers[elem.id].created = false;                                                         
+                                                        datePickers[elem.id].create();                                                     
+                                                } else if(inp) {    
+                                                        // Only do this if called from an ajax update etc                                                    
+                                                        datePickers[elem.id].setDateFromInput();  
+                                                        datePickers[elem.id].updateTable();      
+                                                };                                        
+                                        };                                          
+                                        continue;
+                                };
+                                
+                                if(!elem.id) { elem.id = "fdDatePickerInput-" + uniqueId++; };
+                                
+                                options = {
+                                        id:elem.id,
+                                        low:"",
+                                        high:"",
+                                        format:"d-sl-m-sl-Y",
+                                        statusFormat:"",
+                                        highlightDays:[0,0,0,0,0,1,1],
+                                        disabledDays:[0,0,0,0,0,0,0],
+                                        disabledDates:{},
+                                        enabledDates:{},
+                                        noFadeEffect:elem.className.search(/no-animation/i) != -1,
+                                        staticPos:elem.className.search(/display-inline/i) != -1,
+                                        hideInput:elem.className.search(/hide-input/i) != -1,
+                                        noToday:elem.className.search(/no-today-button/i) != -1,
+                                        showWeeks:elem.className.search(/show-week/i) != -1,
+                                        dragDisabled:nodrag ? true : elem.className.search(/disable-drag/i) != -1,
+                                        positioned:false,
+                                        firstDayOfWeek:localeImport.firstDayOfWeek,
+                                        fillGrid:elem.className.search(/fill-grid/i) != -1,
+                                        constrainSelection:elem.className.search(/fill-grid-no-select/i) != -1,
+                                        callbacks:parseCallbacks(elem.className.match(callbacks)),
+                                        buttonWrapper:""
+                                };                            
+                                
+                                // Positioning of static dp's
+                                if(options.staticPos && elem.className.search(positioned) != -1) {
+                                        options.positioned = elem.className.match(positioned)[1];                                        
+                                };
+                                
+                                // Positioning of non-static dp's button
+                                if(!options.staticPos && elem.className.search(bPositioned) != -1) {
+                                        options.buttonWrapper = elem.className.match(bPositioned)[1];                                        
+                                };
+                                
+                                // Opacity of non-static datePickers
+                                if(!options.staticPos) {
+                                        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                              
+                                };
+                                
+                                // Dates to disable
+                                dts = elem.className.match(disableDates);
+                                if(dts) {
+                                        for(t = 0; t < dts.length; t++) {
+                                                parts = dts[t].replace(/xxxx/, "****").replace(/xx/, "**").replace("disable-", "").split("-");
+                                                options.disabledDates[parts[0]] = (parts.length && parts.length == 2) ? parts[1] : 1;                                                
+                                        };
+                                };
+
+                                // Dates to enable
+                                dts = elem.className.match(enableDates);
+                                if(dts) {
+                                        for(t = 0; t < dts.length; t++) {
+                                                parts = dts[t].replace(/xxxx/, "****").replace(/xx/, "**").replace("enable-", "").split("-");
+                                                options.enabledDates[parts[0]] = (parts.length && parts.length == 2) ? parts[1] : 1;                                                
+                                        };
+                                };
+                                             
+                                // Split the date into three parts ?                                
+                                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);                              
+                                
+                                // Date format
+                                if(!options.splitDate && elem.className.search(dateFormat) != -1) {
+                                        options.format = elem.className.match(dateFormat)[0].replace('dateformat-','');
+                                };
+
+                                // Status bar date format
+                                if(elem.className.search(statusFormat) != -1) {
+                                        options.statusFormat = elem.className.match(statusFormat)[0].replace('statusformat-','');
+                                };
+                                
+                                // The days of the week to highlight
+                                if(elem.className.search(highlight) != -1) {
+                                        tmp = elem.className.match(highlight)[0].replace(/highlight-days-/, '');
+                                        options.highlightDays = [0,0,0,0,0,0,0];
+                                        for(j = 0; j < tmp.length; j++) {
+                                                options.highlightDays[tmp.charAt(j) - 1] = 1;
+                                        };
+                                };
+                                
+                                // The days of the week to disable
+                                if(elem.className.search(disableDays) != -1) {
+                                        tmp = elem.className.match(disableDays)[0].replace(/disable-days-/, '');
+                                        options.disabledDays = [0,0,0,0,0,0,0];                                         
+                                        for(j = 0; j < tmp.length; j++) {
+                                                options.disabledDays[tmp.charAt(j) - 1] = 1;
+                                        };
+                                };
+
+                                // The lower limit
+                                if(elem.className.search(rangeLow) != -1) {
+                                        options.low = parseRangeFromString(elem.className.match(rangeLow)[0]);
+                                };
+
+                                // The higher limit
+                                if(elem.className.search(rangeHigh) != -1) {
+                                        options.high = parseRangeFromString(elem.className.match(rangeHigh)[0]);
+                                };
+
+                                // Always round lower & higher limits if a selectList involved
+                                if(elem.tagName.search(/select/i) != -1) {
+                                        range        = grepRangeLimits(elem);
+                                        options.low  = options.low  ? range[0] + String(options.low).substr(4,4)  : range[0] + "0101";
+                                        options.high = options.high ? range[1] + String(options.high).substr(4,4) : range[1] + "1231";
+                                };
+
+                                addDatePicker(options);
+                        };
+                };
+        };
+
+        addEvent(window, 'load',   create);
+        addEvent(window, 'unload', destroy);
+        addEvent(window, 'resize', repositionDatePickers);
+
+        return {
+                addEvent:               function(obj, type, fn) { return addEvent(obj, type, fn); },
+                removeEvent:            function(obj, type, fn) { return removeEvent(obj, type, fn); },
+                stopEvent:              function(e) { return stopEvent(e); },
+                show:                   function(inpID) { return showDatePicker(inpID); },
+                create:                 function(inp) { create(inp); },                 
+                repositionDatePickers:  function() { repositionDatePickers(); },
+                newDatePicker:          function(opts) { addDatePicker(opts); },
+                overrideAppendID:       function(arr) { splitAppend = (arr && arr.length && arr.length == 2) ? arr : splitAppend },
+                printFormattedDate:     function(dt, fmt, useImportedLocale) { return printFormattedDate(dt, fmt, useImportedLocale); },
+                setDateFromInput:       function(inpID) { if(!inpID || !(inpID in datePickers) || !datePickers[inpID].created) return false; datePickers[inpID].setDateFromInput(); },
+                setRangeLow:            function(inpID, yyyymmdd) { if(!inpID || !(inpID in datePickers)) return false; datePickers[inpID].setRangeLow(yyyymmdd); },
+                setRangeHigh:           function(inpID, yyyymmdd) { if(!inpID || !(inpID in datePickers)) return false; datePickers[inpID].setRangeHigh(yyyymmdd); },
+                parseDateString:        function(str, format) { return parseDateString(str, format); },
+                disableDrag:            function() { noDrag = true; },
+                setGlobalVars:          function(json) { affectJSON(json); },
+                addDisabledDates:       function(inpID, dts) { if(!inpID || !(inpID in datePickers)) return false; datePickers[inpID].addDisabledDates(dts); },
+                setDisabledDates:       function(inpID, dts) { if(!inpID || !(inpID in datePickers)) return false; datePickers[inpID].setDisabledDates(dts); }                                              
+        }; 
+})();
+
+// Change this to use your own month & day id appendages
+// It can also be passed using JSON within the script tag 
+// datePickerController.overrideAppendID(["Day", "Month"]);
index 9e56ec0..9c7cd64 100755 (executable)
@@ -1,35 +1,35 @@
-/*Nifty Corners Cube CSS by Alessandro Fulciniti\r
-The following classes are added dynamically by javascript,\r
-and their use should be avoided in the markup */\r
-\r
-b.niftycorners,b.niftyfill{display:block}\r
-b.niftycorners *{display:block;height: 1px;line-height:1px;font-size: 1px;\r
-    overflow:hidden;border-style:solid;border-width: 0 1px}\r
-/*normal*/\r
-b.r1{margin: 0 3px;border-width: 0 2px}\r
-b.r2{margin: 0 2px}\r
-b.r3{margin: 0 1px}\r
-b.r4{height: 2px}\r
-b.rb1{margin: 0 8px;border-width:0 2px}\r
-b.rb2{margin: 0 6px;border-width:0 2px}\r
-b.rb3{margin: 0 5px}\r
-b.rb4{margin: 0 4px}\r
-b.rb5{margin: 0 3px}\r
-b.rb6{margin: 0 2px}\r
-b.rb7{margin: 0 1px;height:2px}\r
-b.rb8{margin: 0;height:2px}\r
-b.rs1{margin: 0 1px}\r
-/*transparent inside*/\r
-b.t1{border-width: 0 5px}\r
-b.t2{border-width: 0 3px}\r
-b.t3{border-width: 0 2px}\r
-b.t4{height: 2px}\r
-b.tb1{border-width: 0 10px}\r
-b.tb2{border-width: 0 8px}\r
-b.tb3{border-width: 0 6px}\r
-b.tb4{border-width: 0 5px}\r
-b.tb5{border-width: 0 4px}\r
-b.tb6{border-width: 0 3px}\r
-b.tb7{border-width: 0 2px;height:2px}\r
-b.tb8{border-width: 0 1px;height:2px}\r
-b.ts1{border-width: 0 2px}\r
+/*Nifty Corners Cube CSS by Alessandro Fulciniti
+The following classes are added dynamically by javascript,
+and their use should be avoided in the markup */
+
+b.niftycorners,b.niftyfill{display:block}
+b.niftycorners *{display:block;height: 1px;line-height:1px;font-size: 1px;
+    overflow:hidden;border-style:solid;border-width: 0 1px}
+/*normal*/
+b.r1{margin: 0 3px;border-width: 0 2px}
+b.r2{margin: 0 2px}
+b.r3{margin: 0 1px}
+b.r4{height: 2px}
+b.rb1{margin: 0 8px;border-width:0 2px}
+b.rb2{margin: 0 6px;border-width:0 2px}
+b.rb3{margin: 0 5px}
+b.rb4{margin: 0 4px}
+b.rb5{margin: 0 3px}
+b.rb6{margin: 0 2px}
+b.rb7{margin: 0 1px;height:2px}
+b.rb8{margin: 0;height:2px}
+b.rs1{margin: 0 1px}
+/*transparent inside*/
+b.t1{border-width: 0 5px}
+b.t2{border-width: 0 3px}
+b.t3{border-width: 0 2px}
+b.t4{height: 2px}
+b.tb1{border-width: 0 10px}
+b.tb2{border-width: 0 8px}
+b.tb3{border-width: 0 6px}
+b.tb4{border-width: 0 5px}
+b.tb5{border-width: 0 4px}
+b.tb6{border-width: 0 3px}
+b.tb7{border-width: 0 2px;height:2px}
+b.tb8{border-width: 0 1px;height:2px}
+b.ts1{border-width: 0 2px}
index 14406a7..aade96f 100755 (executable)
-/* Nifty Corners Cube - rounded corners with CSS and Javascript\r
-Copyright 2006 Alessandro Fulciniti (a.fulciniti@html.it)\r
-\r
-This program is free software; you can redistribute it and/or modify\r
-it under the terms of the GNU General Public License as published by\r
-the Free Software Foundation; either version 2 of the License, or\r
-(at your option) any later version.\r
-\r
-This program is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License\r
-along with this program; if not, write to the Free Software\r
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
-*/\r
-\r
-var niftyOk=(document.getElementById && document.createElement && Array.prototype.push);\r
-var niftyCss=false;\r
-\r
-String.prototype.find=function(what){\r
-return(this.indexOf(what)>=0 ? true : false);\r
-}\r
-\r
-var oldonload=window.onload;\r
-if(typeof(NiftyLoad)!='function') NiftyLoad=function(){};\r
-if(typeof(oldonload)=='function')\r
-    window.onload=function(){oldonload();AddCss('/plekit/niftycorner');NiftyLoad()};\r
-else window.onload=function(){AddCss('/plekit/niftycorner');NiftyLoad()};\r
-\r
-/* xxx local change : pass a path as parameter */\r
-function AddCss(path){\r
-niftyCss=true;\r
-var l=CreateEl("link");\r
-l.setAttribute("type","text/css");\r
-l.setAttribute("rel","stylesheet");\r
-l.setAttribute("href",path+"/niftyCorners.css");\r
-l.setAttribute("media","screen");\r
-document.getElementsByTagName("head")[0].appendChild(l);\r
-}\r
-\r
-function Nifty(selector,options){\r
-if(niftyOk==false) return;\r
-if(niftyCss==false) AddCss('/plekit/niftycorner');\r
-var i,v=selector.split(","),h=0;\r
-if(options==null) options="";\r
-if(options.find("fixed-height"))\r
-    h=getElementsBySelector(v[0])[0].offsetHeight;\r
-for(i=0;i<v.length;i++)\r
-    Rounded(v[i],options);\r
-if(options.find("height")) SameHeight(selector,h);\r
-}\r
-\r
-function Rounded(selector,options){\r
-var i,top="",bottom="",v=new Array();\r
-if(options!=""){\r
-    options=options.replace("left","tl bl");\r
-    options=options.replace("right","tr br");\r
-    options=options.replace("top","tr tl");\r
-    options=options.replace("bottom","br bl");\r
-    options=options.replace("transparent","alias");\r
-    if(options.find("tl")){\r
-        top="both";\r
-        if(!options.find("tr")) top="left";\r
-        }\r
-    else if(options.find("tr")) top="right";\r
-    if(options.find("bl")){\r
-        bottom="both";\r
-        if(!options.find("br")) bottom="left";\r
-        }\r
-    else if(options.find("br")) bottom="right";\r
-    }\r
-if(top=="" && bottom=="" && !options.find("none")){top="both";bottom="both";}\r
-v=getElementsBySelector(selector);\r
-for(i=0;i<v.length;i++){\r
-    FixIE(v[i]);\r
-    if(top!="") AddTop(v[i],top,options);\r
-    if(bottom!="") AddBottom(v[i],bottom,options);\r
-    }\r
-}\r
-\r
-/* local addition\r
- * accept element rather than selectors */\r
-function pleRounded(element,options){\r
-var i,top="",bottom="",v=new Array();\r
-if(options!=""){\r
-    options=options.replace("left","tl bl");\r
-    options=options.replace("right","tr br");\r
-    options=options.replace("top","tr tl");\r
-    options=options.replace("bottom","br bl");\r
-    options=options.replace("transparent","alias");\r
-    if(options.find("tl")){\r
-        top="both";\r
-        if(!options.find("tr")) top="left";\r
-        }\r
-    else if(options.find("tr")) top="right";\r
-    if(options.find("bl")){\r
-        bottom="both";\r
-        if(!options.find("br")) bottom="left";\r
-        }\r
-    else if(options.find("br")) bottom="right";\r
-    }\r
-if(top=="" && bottom=="" && !options.find("none")){top="both";bottom="both";}\r
-    FixIE(element);\r
-    if(top!="") AddTop(element,top,options);\r
-    if(bottom!="") AddBottom(element,bottom,options);\r
-}\r
-\r
-\r
-function AddTop(el,side,options){\r
-var d=CreateEl("b"),lim=4,border="",p,i,btype="r",bk,color;\r
-d.style.marginLeft="-"+getPadding(el,"Left")+"px";\r
-d.style.marginRight="-"+getPadding(el,"Right")+"px";\r
-if(options.find("alias") || (color=getBk(el))=="transparent"){\r
-    color="transparent";bk="transparent"; border=getParentBk(el);btype="t";\r
-    }\r
-else{\r
-    bk=getParentBk(el); border=Mix(color,bk);\r
-    }\r
-d.style.background=bk;\r
-d.className="niftycorners";\r
-p=getPadding(el,"Top");\r
-if(options.find("small")){\r
-    d.style.marginBottom=(p-2)+"px";\r
-    btype+="s"; lim=2;\r
-    }\r
-else if(options.find("big")){\r
-    d.style.marginBottom=(p-10)+"px";\r
-    btype+="b"; lim=8;\r
-    }\r
-else d.style.marginBottom=(p-5)+"px";\r
-for(i=1;i<=lim;i++)\r
-    d.appendChild(CreateStrip(i,side,color,border,btype));\r
-el.style.paddingTop="0";\r
-el.insertBefore(d,el.firstChild);\r
-}\r
-\r
-function AddBottom(el,side,options){\r
-var d=CreateEl("b"),lim=4,border="",p,i,btype="r",bk,color;\r
-d.style.marginLeft="-"+getPadding(el,"Left")+"px";\r
-d.style.marginRight="-"+getPadding(el,"Right")+"px";\r
-if(options.find("alias") || (color=getBk(el))=="transparent"){\r
-    color="transparent";bk="transparent"; border=getParentBk(el);btype="t";\r
-    }\r
-else{\r
-    bk=getParentBk(el); border=Mix(color,bk);\r
-    }\r
-d.style.background=bk;\r
-d.className="niftycorners";\r
-p=getPadding(el,"Bottom");\r
-if(options.find("small")){\r
-    d.style.marginTop=(p-2)+"px";\r
-    btype+="s"; lim=2;\r
-    }\r
-else if(options.find("big")){\r
-    d.style.marginTop=(p-10)+"px";\r
-    btype+="b"; lim=8;\r
-    }\r
-else d.style.marginTop=(p-5)+"px";\r
-for(i=lim;i>0;i--)\r
-    d.appendChild(CreateStrip(i,side,color,border,btype));\r
-el.style.paddingBottom=0;\r
-el.appendChild(d);\r
-}\r
-\r
-function CreateStrip(index,side,color,border,btype){\r
-var x=CreateEl("b");\r
-x.className=btype+index;\r
-x.style.backgroundColor=color;\r
-x.style.borderColor=border;\r
-if(side=="left"){\r
-    x.style.borderRightWidth="0";\r
-    x.style.marginRight="0";\r
-    }\r
-else if(side=="right"){\r
-    x.style.borderLeftWidth="0";\r
-    x.style.marginLeft="0";\r
-    }\r
-return(x);\r
-}\r
-\r
-function CreateEl(x){\r
-return(document.createElement(x));\r
-}\r
-\r
-function FixIE(el){\r
-if(el.currentStyle!=null && el.currentStyle.hasLayout!=null && el.currentStyle.hasLayout==false)\r
-    el.style.display="inline-block";\r
-}\r
-\r
-function SameHeight(selector,maxh){\r
-var i,v=selector.split(","),t,j,els=[],gap;\r
-for(i=0;i<v.length;i++){\r
-    t=getElementsBySelector(v[i]);\r
-    els=els.concat(t);\r
-    }\r
-for(i=0;i<els.length;i++){\r
-    if(els[i].offsetHeight>maxh) maxh=els[i].offsetHeight;\r
-    els[i].style.height="auto";\r
-    }\r
-for(i=0;i<els.length;i++){\r
-    gap=maxh-els[i].offsetHeight;\r
-    if(gap>0){\r
-        t=CreateEl("b");t.className="niftyfill";t.style.height=gap+"px";\r
-        nc=els[i].lastChild;\r
-        if(nc.className=="niftycorners")\r
-            els[i].insertBefore(t,nc);\r
-        else els[i].appendChild(t);\r
-        }\r
-    }\r
-}\r
-\r
-function getElementsBySelector(selector){\r
-var i,j,selid="",selclass="",tag=selector,tag2="",v2,k,f,a,s=[],objlist=[],c;\r
-if(selector.find("#")){ //id selector like "tag#id"\r
-    if(selector.find(" ")){  //descendant selector like "tag#id tag"\r
-        s=selector.split(" ");\r
-        var fs=s[0].split("#");\r
-        if(fs.length==1) return(objlist);\r
-        f=document.getElementById(fs[1]);\r
-        if(f){\r
-            v=f.getElementsByTagName(s[1]);\r
-            for(i=0;i<v.length;i++) objlist.push(v[i]);\r
-            }\r
-        return(objlist);\r
-        }\r
-    else{\r
-        s=selector.split("#");\r
-        tag=s[0];\r
-        selid=s[1];\r
-        if(selid!=""){\r
-            f=document.getElementById(selid);\r
-            if(f) objlist.push(f);\r
-            return(objlist);\r
-            }\r
-        }\r
-    }\r
-if(selector.find(".")){      //class selector like "tag.class"\r
-    s=selector.split(".");\r
-    tag=s[0];\r
-    selclass=s[1];\r
-    if(selclass.find(" ")){   //descendant selector like tag1.classname tag2\r
-        s=selclass.split(" ");\r
-        selclass=s[0];\r
-        tag2=s[1];\r
-        }\r
-    }\r
-var v=document.getElementsByTagName(tag);  // tag selector like "tag"\r
-if(selclass==""){\r
-    for(i=0;i<v.length;i++) objlist.push(v[i]);\r
-    return(objlist);\r
-    }\r
-for(i=0;i<v.length;i++){\r
-    c=v[i].className.split(" ");\r
-    for(j=0;j<c.length;j++){\r
-        if(c[j]==selclass){\r
-            if(tag2=="") objlist.push(v[i]);\r
-            else{\r
-                v2=v[i].getElementsByTagName(tag2);\r
-                for(k=0;k<v2.length;k++) objlist.push(v2[k]);\r
-                }\r
-            }\r
-        }\r
-    }\r
-return(objlist);\r
-}\r
-\r
-function getParentBk(x){\r
-var el=x.parentNode,c;\r
-while(el.tagName.toUpperCase()!="HTML" && (c=getBk(el))=="transparent")\r
-    el=el.parentNode;\r
-if(c=="transparent") c="#FFFFFF";\r
-return(c);\r
-}\r
-\r
-function getBk(x){\r
-var c=getStyleProp(x,"backgroundColor");\r
-if(c==null || c=="transparent" || c.find("rgba(0, 0, 0, 0)"))\r
-    return("transparent");\r
-if(c.find("rgb")) c=rgb2hex(c);\r
-return(c);\r
-}\r
-\r
-function getPadding(x,side){\r
-var p=getStyleProp(x,"padding"+side);\r
-if(p==null || !p.find("px")) return(0);\r
-return(parseInt(p));\r
-}\r
-\r
-function getStyleProp(x,prop){\r
-if(x.currentStyle)\r
-    return(x.currentStyle[prop]);\r
-if(document.defaultView.getComputedStyle)\r
-    return(document.defaultView.getComputedStyle(x,'')[prop]);\r
-return(null);\r
-}\r
-\r
-function rgb2hex(value){\r
-var hex="",v,h,i;\r
-var regexp=/([0-9]+)[, ]+([0-9]+)[, ]+([0-9]+)/;\r
-var h=regexp.exec(value);\r
-for(i=1;i<4;i++){\r
-    v=parseInt(h[i]).toString(16);\r
-    if(v.length==1) hex+="0"+v;\r
-    else hex+=v;\r
-    }\r
-return("#"+hex);\r
-}\r
-\r
-function Mix(c1,c2){\r
-var i,step1,step2,x,y,r=new Array(3);\r
-if(c1.length==4)step1=1;\r
-else step1=2;\r
-if(c2.length==4) step2=1;\r
-else step2=2;\r
-for(i=0;i<3;i++){\r
-    x=parseInt(c1.substr(1+step1*i,step1),16);\r
-    if(step1==1) x=16*x+x;\r
-    y=parseInt(c2.substr(1+step2*i,step2),16);\r
-    if(step2==1) y=16*y+y;\r
-    r[i]=Math.floor((x*50+y*50)/100);\r
-    r[i]=r[i].toString(16);\r
-    if(r[i].length==1) r[i]="0"+r[i];\r
-    }\r
-return("#"+r[0]+r[1]+r[2]);\r
-}\r
+/* Nifty Corners Cube - rounded corners with CSS and Javascript
+Copyright 2006 Alessandro Fulciniti (a.fulciniti@html.it)
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+var niftyOk=(document.getElementById && document.createElement && Array.prototype.push);
+var niftyCss=false;
+
+String.prototype.find=function(what){
+return(this.indexOf(what)>=0 ? true : false);
+}
+
+var oldonload=window.onload;
+if(typeof(NiftyLoad)!='function') NiftyLoad=function(){};
+if(typeof(oldonload)=='function')
+    window.onload=function(){oldonload();AddCss('/plekit/niftycorner');NiftyLoad()};
+else window.onload=function(){AddCss('/plekit/niftycorner');NiftyLoad()};
+
+/* xxx local change : pass a path as parameter */
+function AddCss(path){
+niftyCss=true;
+var l=CreateEl("link");
+l.setAttribute("type","text/css");
+l.setAttribute("rel","stylesheet");
+l.setAttribute("href",path+"/niftyCorners.css");
+l.setAttribute("media","screen");
+document.getElementsByTagName("head")[0].appendChild(l);
+}
+
+function Nifty(selector,options){
+if(niftyOk==false) return;
+if(niftyCss==false) AddCss('/plekit/niftycorner');
+var i,v=selector.split(","),h=0;
+if(options==null) options="";
+if(options.find("fixed-height"))
+    h=getElementsBySelector(v[0])[0].offsetHeight;
+for(i=0;i<v.length;i++)
+    Rounded(v[i],options);
+if(options.find("height")) SameHeight(selector,h);
+}
+
+function Rounded(selector,options){
+var i,top="",bottom="",v=new Array();
+if(options!=""){
+    options=options.replace("left","tl bl");
+    options=options.replace("right","tr br");
+    options=options.replace("top","tr tl");
+    options=options.replace("bottom","br bl");
+    options=options.replace("transparent","alias");
+    if(options.find("tl")){
+        top="both";
+        if(!options.find("tr")) top="left";
+        }
+    else if(options.find("tr")) top="right";
+    if(options.find("bl")){
+        bottom="both";
+        if(!options.find("br")) bottom="left";
+        }
+    else if(options.find("br")) bottom="right";
+    }
+if(top=="" && bottom=="" && !options.find("none")){top="both";bottom="both";}
+v=getElementsBySelector(selector);
+for(i=0;i<v.length;i++){
+    FixIE(v[i]);
+    if(top!="") AddTop(v[i],top,options);
+    if(bottom!="") AddBottom(v[i],bottom,options);
+    }
+}
+
+/* local addition
+ * accept element rather than selectors */
+function pleRounded(element,options){
+var i,top="",bottom="",v=new Array();
+if(options!=""){
+    options=options.replace("left","tl bl");
+    options=options.replace("right","tr br");
+    options=options.replace("top","tr tl");
+    options=options.replace("bottom","br bl");
+    options=options.replace("transparent","alias");
+    if(options.find("tl")){
+        top="both";
+        if(!options.find("tr")) top="left";
+        }
+    else if(options.find("tr")) top="right";
+    if(options.find("bl")){
+        bottom="both";
+        if(!options.find("br")) bottom="left";
+        }
+    else if(options.find("br")) bottom="right";
+    }
+if(top=="" && bottom=="" && !options.find("none")){top="both";bottom="both";}
+    FixIE(element);
+    if(top!="") AddTop(element,top,options);
+    if(bottom!="") AddBottom(element,bottom,options);
+}
+
+
+function AddTop(el,side,options){
+var d=CreateEl("b"),lim=4,border="",p,i,btype="r",bk,color;
+d.style.marginLeft="-"+getPadding(el,"Left")+"px";
+d.style.marginRight="-"+getPadding(el,"Right")+"px";
+if(options.find("alias") || (color=getBk(el))=="transparent"){
+    color="transparent";bk="transparent"; border=getParentBk(el);btype="t";
+    }
+else{
+    bk=getParentBk(el); border=Mix(color,bk);
+    }
+d.style.background=bk;
+d.className="niftycorners";
+p=getPadding(el,"Top");
+if(options.find("small")){
+    d.style.marginBottom=(p-2)+"px";
+    btype+="s"; lim=2;
+    }
+else if(options.find("big")){
+    d.style.marginBottom=(p-10)+"px";
+    btype+="b"; lim=8;
+    }
+else d.style.marginBottom=(p-5)+"px";
+for(i=1;i<=lim;i++)
+    d.appendChild(CreateStrip(i,side,color,border,btype));
+el.style.paddingTop="0";
+el.insertBefore(d,el.firstChild);
+}
+
+function AddBottom(el,side,options){
+var d=CreateEl("b"),lim=4,border="",p,i,btype="r",bk,color;
+d.style.marginLeft="-"+getPadding(el,"Left")+"px";
+d.style.marginRight="-"+getPadding(el,"Right")+"px";
+if(options.find("alias") || (color=getBk(el))=="transparent"){
+    color="transparent";bk="transparent"; border=getParentBk(el);btype="t";
+    }
+else{
+    bk=getParentBk(el); border=Mix(color,bk);
+    }
+d.style.background=bk;
+d.className="niftycorners";
+p=getPadding(el,"Bottom");
+if(options.find("small")){
+    d.style.marginTop=(p-2)+"px";
+    btype+="s"; lim=2;
+    }
+else if(options.find("big")){
+    d.style.marginTop=(p-10)+"px";
+    btype+="b"; lim=8;
+    }
+else d.style.marginTop=(p-5)+"px";
+for(i=lim;i>0;i--)
+    d.appendChild(CreateStrip(i,side,color,border,btype));
+el.style.paddingBottom=0;
+el.appendChild(d);
+}
+
+function CreateStrip(index,side,color,border,btype){
+var x=CreateEl("b");
+x.className=btype+index;
+x.style.backgroundColor=color;
+x.style.borderColor=border;
+if(side=="left"){
+    x.style.borderRightWidth="0";
+    x.style.marginRight="0";
+    }
+else if(side=="right"){
+    x.style.borderLeftWidth="0";
+    x.style.marginLeft="0";
+    }
+return(x);
+}
+
+function CreateEl(x){
+return(document.createElement(x));
+}
+
+function FixIE(el){
+if(el.currentStyle!=null && el.currentStyle.hasLayout!=null && el.currentStyle.hasLayout==false)
+    el.style.display="inline-block";
+}
+
+function SameHeight(selector,maxh){
+var i,v=selector.split(","),t,j,els=[],gap;
+for(i=0;i<v.length;i++){
+    t=getElementsBySelector(v[i]);
+    els=els.concat(t);
+    }
+for(i=0;i<els.length;i++){
+    if(els[i].offsetHeight>maxh) maxh=els[i].offsetHeight;
+    els[i].style.height="auto";
+    }
+for(i=0;i<els.length;i++){
+    gap=maxh-els[i].offsetHeight;
+    if(gap>0){
+        t=CreateEl("b");t.className="niftyfill";t.style.height=gap+"px";
+        nc=els[i].lastChild;
+        if(nc.className=="niftycorners")
+            els[i].insertBefore(t,nc);
+        else els[i].appendChild(t);
+        }
+    }
+}
+
+function getElementsBySelector(selector){
+var i,j,selid="",selclass="",tag=selector,tag2="",v2,k,f,a,s=[],objlist=[],c;
+if(selector.find("#")){ //id selector like "tag#id"
+    if(selector.find(" ")){  //descendant selector like "tag#id tag"
+        s=selector.split(" ");
+        var fs=s[0].split("#");
+        if(fs.length==1) return(objlist);
+        f=document.getElementById(fs[1]);
+        if(f){
+            v=f.getElementsByTagName(s[1]);
+            for(i=0;i<v.length;i++) objlist.push(v[i]);
+            }
+        return(objlist);
+        }
+    else{
+        s=selector.split("#");
+        tag=s[0];
+        selid=s[1];
+        if(selid!=""){
+            f=document.getElementById(selid);
+            if(f) objlist.push(f);
+            return(objlist);
+            }
+        }
+    }
+if(selector.find(".")){      //class selector like "tag.class"
+    s=selector.split(".");
+    tag=s[0];
+    selclass=s[1];
+    if(selclass.find(" ")){   //descendant selector like tag1.classname tag2
+        s=selclass.split(" ");
+        selclass=s[0];
+        tag2=s[1];
+        }
+    }
+var v=document.getElementsByTagName(tag);  // tag selector like "tag"
+if(selclass==""){
+    for(i=0;i<v.length;i++) objlist.push(v[i]);
+    return(objlist);
+    }
+for(i=0;i<v.length;i++){
+    c=v[i].className.split(" ");
+    for(j=0;j<c.length;j++){
+        if(c[j]==selclass){
+            if(tag2=="") objlist.push(v[i]);
+            else{
+                v2=v[i].getElementsByTagName(tag2);
+                for(k=0;k<v2.length;k++) objlist.push(v2[k]);
+                }
+            }
+        }
+    }
+return(objlist);
+}
+
+function getParentBk(x){
+var el=x.parentNode,c;
+while(el.tagName.toUpperCase()!="HTML" && (c=getBk(el))=="transparent")
+    el=el.parentNode;
+if(c=="transparent") c="#FFFFFF";
+return(c);
+}
+
+function getBk(x){
+var c=getStyleProp(x,"backgroundColor");
+if(c==null || c=="transparent" || c.find("rgba(0, 0, 0, 0)"))
+    return("transparent");
+if(c.find("rgb")) c=rgb2hex(c);
+return(c);
+}
+
+function getPadding(x,side){
+var p=getStyleProp(x,"padding"+side);
+if(p==null || !p.find("px")) return(0);
+return(parseInt(p));
+}
+
+function getStyleProp(x,prop){
+if(x.currentStyle)
+    return(x.currentStyle[prop]);
+if(document.defaultView.getComputedStyle)
+    return(document.defaultView.getComputedStyle(x,'')[prop]);
+return(null);
+}
+
+function rgb2hex(value){
+var hex="",v,h,i;
+var regexp=/([0-9]+)[, ]+([0-9]+)[, ]+([0-9]+)/;
+var h=regexp.exec(value);
+for(i=1;i<4;i++){
+    v=parseInt(h[i]).toString(16);
+    if(v.length==1) hex+="0"+v;
+    else hex+=v;
+    }
+return("#"+hex);
+}
+
+function Mix(c1,c2){
+var i,step1,step2,x,y,r=new Array(3);
+if(c1.length==4)step1=1;
+else step1=2;
+if(c2.length==4) step2=1;
+else step2=2;
+for(i=0;i<3;i++){
+    x=parseInt(c1.substr(1+step1*i,step1),16);
+    if(step1==1) x=16*x+x;
+    y=parseInt(c2.substr(1+step2*i,step2),16);
+    if(step2==1) y=16*y+y;
+    r[i]=Math.floor((x*50+y*50)/100);
+    r[i]=r[i].toString(16);
+    if(r[i].length==1) r[i]="0"+r[i];
+    }
+return("#"+r[0]+r[1]+r[2]);
+}
index a766898..c91fcca 100644 (file)
-/*\r
-    sortEnglishDateTime\r
-    -----------------------\r
-\r
-    This function sorts English dateTime vaues such as:\r
-\r
-    1st January 2003, 23:32:01\r
-    23/03/1972 Ã  10:22:22\r
-    1970/13/03 at 23:22:01\r
-    \r
-    The function is "safe" i.e. non-dateTime data (like the word "Unknown") can be passed in and is sorted properly.\r
-*/\r
-var sortEnglishDateTime = fdTableSort.sortNumeric;\r
-\r
-function sortEnglishDateTimePrepareData(tdNode, innerText) {\r
-        // You can localise the function here\r
-        var months = ['january','february','march','april','may','june','july','august','september','october','november','december','jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec'];\r
-\r
-        // Lowercase the text\r
-        var aa = innerText.toLowerCase();\r
-\r
-        // Replace the longhand months with an integer equivalent\r
-        for(var i = 0; i < months.length; i++) {\r
-                aa = aa.replace(months[i], (i+13)%12);\r
-        };\r
-\r
-        // Replace multiple spaces and anything that is not valid in the parsing of the date, then trim\r
-        aa = aa.replace(/\s+/g, " ").replace(/([^\d\s\/-:.])/g, "").replace(/^\s\s*/, '').replace(/\s\s*$/, '');\r
-\r
-        // No timestamp at the end, then return -1\r
-        if(aa.search(/(\d){2}:(\d){2}(:(\d){2})?$/) == -1) { return -1; };\r
-\r
-        // Grab the timestamp\r
-        var timestamp = aa.match(/(\d){2}:(\d){2}(:(\d){2})?$/)[0].replace(/:/g, "");\r
-\r
-        // Make the timestamp 6 characters by default\r
-        if(timestamp.length == 4) { timestamp += "00"; };\r
-\r
-        // Remove it from the string to assist the date parser, then trim\r
-        aa = aa.replace(/(\d){2}:(\d){2}(:(\d){2})?$/, "").replace(/\s\s*$/, '');\r
-\r
-        // If you want the parser to favour the parsing of European dd/mm/yyyy dates then leave this set to "true"\r
-        // If you want the parser to favour the parsing of American mm/dd/yyyy dates then set to "false"\r
-        var favourDMY = true;\r
-\r
-        // If you have a regular expression you wish to add, add the Object to the end of the array\r
-        var dateTest = [\r
-                       { regExp:/^(0?[1-9]|1[012])([- \/.])(0?[1-9]|[12][0-9]|3[01])([- \/.])((\d\d)?\d\d)$/, d:3, m:1, y:5 },  // mdy\r
-                       { regExp:/^(0?[1-9]|[12][0-9]|3[01])([- \/.])(0?[1-9]|1[012])([- \/.])((\d\d)?\d\d)$/, d:1, m:3, y:5 },  // dmy\r
-                       { regExp:/^(\d\d\d\d)([- \/.])(0?[1-9]|1[012])([- \/.])(0?[1-9]|[12][0-9]|3[01])$/, d:5, m:3, y:1 }      // ymd\r
-                       ];\r
-\r
-        var start,y,m,d;\r
-        var cnt = 0;\r
-        var numFormats = dateTest.length;\r
-        while(cnt < numFormats) {\r
-               start = (cnt + (favourDMY ? numFormats + 1 : numFormats)) % numFormats;\r
-               if(aa.match(dateTest[start].regExp)) {\r
-                       res = aa.match(dateTest[start].regExp);\r
-                       y = res[dateTest[start].y];\r
-                       m = res[dateTest[start].m];\r
-                       d = res[dateTest[start].d];\r
-                       if(m.length == 1) m = "0" + String(m);\r
-                       if(d.length == 1) d = "0" + String(d);\r
-                       if(y.length != 4) y = (parseInt(y) < 50) ? "20" + String(y) : "19" + String(y);\r
-\r
-                       return y+String(m)+d+String(timestamp);\r
-               };\r
-               cnt++;\r
-        };\r
-        return -1;\r
-};\r
-\r
-/*\r
-    sortAlphaNumeric\r
-    -----------------------\r
-\r
-    This function sorts alphaNumeric values e.g. 1, e, 1a, -23c, 54z\r
-    \r
-    Notice how the prepareData function actually returns an Array i.e. you are not limited\r
-    in the type of data you return to the tableSort script.\r
-*/\r
-function sortAlphaNumericPrepareData(tdNode, innerText){\r
-        var aa = innerText.toLowerCase().replace(" ", "");\r
-        var reg = /((\-|\+)?(\s+)?[0-9]+\.([0-9]+)?|(\-|\+)?(\s+)?(\.)?[0-9]+)([a-z]+)/;\r
-\r
-        if(reg.test(aa)) {\r
-                var aaP = aa.match(reg);\r
-                return [aaP[1], aaP[8]];\r
-        };\r
-\r
-        // Return an array\r
-        return isNaN(aa) ? ["",aa] : [aa,""];\r
-}\r
-\r
-function sortAlphaNumeric(a, b){\r
-        // Get the previously prepared array\r
-        var aa = a[fdTableSort.pos];\r
-        var bb = b[fdTableSort.pos];\r
-\r
-        // If they are equal then return 0\r
-        if(aa[0] == bb[0] && aa[1] == bb[1]) { return 0; };\r
-\r
-        // Check numeric parts if not equal\r
-        if(aa[0] != bb[0]) {\r
-                if(aa[0] != "" && bb[0] != "") { return aa[0] - bb[0]; };\r
-                if(aa[0] == "" && bb[0] != "") { return -1; };\r
-                return 1;\r
-        };\r
-        \r
-        // Check alpha parts if numeric parts equal\r
-        if(aa[1] == bb[1]) return 0;\r
-        if(aa[1] < bb[1])  return -1;\r
-        return 1;\r
-}\r
-\r
-/*\r
-    sortDutchCurrencyValues\r
-    -----------------------\r
-\r
-    This function sorts Dutch currency values (of the type 100.000,00)\r
-    The function is "safe" i.e. non-currency data (like the word "Unknown") can be passed in and is sorted properly.\r
-*/\r
-var sortDutchCurrencyValues = fdTableSort.sortNumeric;\r
-\r
-function sortDutchCurrencyValuesPrepareData(tdNode, innerText) {\r
-        innerText = parseInt(innerText.replace(/[^0-9\.,]+/g, "").replace(/\./g,"").replace(",","."));\r
-        return isNaN(innerText) ? "" : innerText;\r
-}\r
-\r
-/*\r
-   sortByTwelveHourTimestamp\r
-   -------------------------\r
-\r
-   This custom sort function sorts 12 hour timestamps of an hour/minute nature.\r
-   The hour/minute dividor can be a full-stop or a colon and it correctly calculates that 12.30am is before 1am etc\r
-   The am/pm part can be written in lower or uppercase and can optionally contain full-stops e.g.\r
-\r
-   am, a.m, a.m., AM, A.M etc\r
-\r
-   Additionally, the values "12 midnight" and "12 noon" are also handled correctly.\r
-\r
-   The question remains... does "12p.m." mean "midnight" or "12 noon"? I've decided here that it's 12 noon.\r
-\r
-   The function is "safe" i.e. non-timestamp data (like the word "Unknown") can be passed in and is sorted properly.\r
-*/\r
-var sortByTwelveHourTimestamp = fdTableSort.sortNumeric;\r
-\r
-function sortByTwelveHourTimestampPrepareData(tdNode, innerText) {\r
-        tmp = innerText\r
-        innerText = innerText.replace(":",".");\r
-\r
-        // Check for the special cases of "12 noon" or "12 midnight"\r
-        if(innerText.search(/12([\s]*)?noon/i) != -1) return "12.00";\r
-        if(innerText.search(/12([\s]*)?midnight/i) != -1) return "24.00";\r
-\r
-        var regExpPM = /^([0-9]{1,2}).([0-9]{2})([\s]*)?(p[\.]?m)/i;\r
-        var regExpAM = /^([0-9]{1,2}).([0-9]{2})([\s]*)?(a[\.]?m)/i;\r
-\r
-        if(innerText.search(regExpPM) != -1) {\r
-                var bits = innerText.match(regExpPM);\r
-                if(parseInt(bits[1]) < 12) { bits[1] = parseInt(bits[1]) + 12; }\r
-        } else if(innerText.search(regExpAM) != -1) {\r
-                var bits = innerText.match(regExpAM);\r
-                if(bits[1] == "12") { bits[1] = "00"; }\r
-        } else return "";\r
-\r
-        if(bits[2].length < 2) { bits[2] = "0" + String(bits[2]); }\r
-\r
-        innerText = bits[1] + "." + String(bits[2]);\r
-\r
-        return isNaN(innerText) ? "" : innerText;\r
-}\r
-/*\r
-   sortEnglishLonghandDateFormat\r
-   -----------------------------\r
-\r
-   This custom sort function sorts dates of the format:\r
-\r
-   "12th April, 2006" or "12 April 2006" or "12-4-2006" or "12 April" or "12 4" or "12 Apr 2006" etc\r
-\r
-   The function expects dates to be in the format day/month/year. Should no year be stipulated,\r
-   the function treats the year as being the current year.\r
-\r
-   The function is "safe" i.e. non-date data (like the word "Unknown") can be passed in and is sorted properly.\r
-*/\r
-var sortEnglishLonghandDateFormat = fdTableSort.sortNumeric;\r
-\r
-function sortEnglishLonghandDateFormatPrepareData(tdNode, innerText) {\r
-        var months = ['january','february','march','april','may','june','july','august','september','october','november','december'];\r
-\r
-        var aa = innerText.toLowerCase();\r
-\r
-        // Replace the longhand months with an integer equivalent\r
-        for(var i = 0; i < 12; i++) {\r
-                aa = aa.replace(months[i], i+1).replace(months[i].substring(0,3), i+1);\r
-        }\r
-\r
-        // If there are still alpha characters then return -1\r
-        if(aa.search(/a-z/) != -1) return -1;\r
-\r
-        // Replace multiple spaces and anything that is not numeric\r
-        aa = aa.replace(/\s+/g, " ").replace(/[^\d\s]/g, "");\r
-\r
-        // If were left with nothing then return -1\r
-        if(aa.replace(" ", "") == "") return -1;\r
-\r
-        // Split on the (now) single spaces\r
-        aa = aa.split(" ");\r
-\r
-        // If something has gone terribly wrong then return -1\r
-        if(aa.length < 2) return -1;\r
-\r
-        // If no year stipulated, then add this year as default\r
-        if(aa.length == 2) {\r
-                aa[2] = String(new Date().getFullYear());\r
-        }\r
-\r
-        // Equalise the day and month\r
-        if(aa[0].length < 2) aa[0] = "0" + String(aa[0]);\r
-        if(aa[1].length < 2) aa[1] = "0" + String(aa[1]);\r
-\r
-        // Deal with Y2K issues\r
-        if(aa[2].length != 4) {\r
-                aa[2] = (parseInt(aa[2]) < 50) ? '20' + aa[2] : '19' + aa[2];\r
-        }\r
-\r
-        // YMD (can be used as integer during comparison)\r
-        return aa[2] + String(aa[1]) + aa[0];\r
-}\r
-/*\r
-   sortIPAddress\r
-   -------------\r
-\r
-   This custom sort function correctly sorts IP addresses i.e. it checks all of the address parts and not just the first.\r
-\r
-   The function is "safe" i.e. non-IP address data (like the word "Unknown") can be passed in and is sorted properly.\r
-*/\r
-var sortIPAddress = fdTableSort.sortNumeric;\r
-\r
-function sortIPAddressPrepareData(tdNode, innerText) {\r
-        // Get the innerText of the TR nodes\r
-        var aa = innerText;\r
-\r
-        // Remove spaces\r
-        aa = aa.replace(" ","");\r
-\r
-        // If not an IP address then return -1\r
-        if(aa.search(/^([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3})$/) == -1) return -1;\r
-\r
-        // Split on the "."\r
-        aa = aa.split(".");\r
-\r
-        // If we don't have 4 parts then return -1\r
-        if(aa.length != 4) return -1;\r
-\r
-        var retVal = "";\r
-\r
-        // Make all the parts an equal length and create a master integer\r
-        for(var i = 0; i < 4; i++) {\r
-                retVal += (String(aa[i]).length < 3) ? "0000".substr(0, 3 - String(aa[i]).length) + String(aa[i]) : aa[i];\r
-        }\r
-\r
-        return retVal;\r
-}\r
-/*\r
-   sortScientificNotation\r
-   ----------------------\r
-\r
-   This custom sort function sorts numbers stipulated in scientific notation\r
-\r
-   The function is "safe" i.e. data like the word "Unknown" can be passed in and is sorted properly.\r
-\r
-   N.B. The only way I can think to really sort scientific notation is to convert\r
-        it to a floating point number and then perform the sort on that. If you can think of\r
-        an easier/better way then please let me know.\r
-*/\r
-var sortScientificNotation = fdTableSort.sortNumeric;\r
-\r
-function sortScientificNotationPrepareData(tdNode, innerText) {\r
-        var aa = innerText;\r
-\r
-        var floatRegExp = /((\-|\+)?(\s+)?[0-9]+\.([0-9]+)?|(\-|\+)?(\s+)?(\.)?[0-9]+)/g;\r
-\r
-        aa = aa.match(floatRegExp);\r
-\r
-        if(!aa || aa.length != 2) return "";\r
-\r
-        var f1 = parseFloat(aa[0].replace(" ",""))*Math.pow(10,parseFloat(aa[1].replace(" ","")));\r
-        return isNaN(f1) ? "" : f1;\r
-}\r
-\r
-/*\r
-        sortImage\r
-        ---------\r
-\r
-        This is the function called in order to sort the data previously prepared by the function\r
-        "sortImagePrepareData". It does a basic case sensitive comparison on the data using the\r
-        tableSort's in-built sortText method.\r
-*/\r
-var sortImage = fdTableSort.sortText;\r
-\r
-/*\r
-        This is the function used to prepare i.e. parse data, to be used during the sort\r
-        of the images within the last table.\r
-\r
-        In this case, we are checking to see if the TD node has any child nodes that are\r
-        images and, if an image exists, return it's "src" attribute.\r
-        If no image exists, then we return an empty string.\r
-\r
-        The "prepareData" functions are passed the actual TD node and also the TD node inner text\r
-        which means you are free to check for child nodes etc and are not just limited to\r
-        sorting on the TD node's inner text.\r
-\r
-        The prepareData functions are not required (only your bespoke sort function is required)\r
-        and only called by the script should they exist.\r
-*/\r
-function sortImagePrepareData(td, innerText) {\r
-        var img = td.getElementsByTagName('img');\r
-        return img.length ? img[0].src: "";\r
-}\r
-\r
-/*\r
-        sortFileSize\r
-        ------------\r
-\r
-        1 Byte = 8 Bit\r
-        1 Kilobyte = 1024 Bytes\r
-        1 Megabyte = 1048576 Bytes\r
-        1 Gigabyte = 1073741824 Bytes\r
-*/\r
-var sortFileSize = fdTableSort.sortNumeric;\r
-\r
-function sortFileSizePrepareData(td, innerText) {\r
-        var regExp = /(kb|mb|gb)/i;\r
-\r
-        var type = innerText.search(regExp) != -1 ? innerText.match(regExp)[0] : "";\r
-\r
-        switch (type.toLowerCase()) {\r
-                case "kb" :\r
-                        mult = 1024;\r
-                        break;\r
-                case "mb" :\r
-                        mult = 1048576;\r
-                        break;\r
-                case "gb" :\r
-                        mult = 1073741824;\r
-                        break;\r
-                default :\r
-                        mult = 1;\r
-        };\r
-\r
-        innerText = parseFloat(innerText.replace(/[^0-9\.\-]/g,''));\r
-\r
-        return isNaN(innerText) ? "" : innerText * mult;\r
-};\r
+/*
+    sortEnglishDateTime
+    -----------------------
+
+    This function sorts English dateTime vaues such as:
+
+    1st January 2003, 23:32:01
+    23/03/1972 Ã  10:22:22
+    1970/13/03 at 23:22:01
+    
+    The function is "safe" i.e. non-dateTime data (like the word "Unknown") can be passed in and is sorted properly.
+*/
+var sortEnglishDateTime = fdTableSort.sortNumeric;
+
+function sortEnglishDateTimePrepareData(tdNode, innerText) {
+        // You can localise the function here
+        var months = ['january','february','march','april','may','june','july','august','september','october','november','december','jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec'];
+
+        // Lowercase the text
+        var aa = innerText.toLowerCase();
+
+        // Replace the longhand months with an integer equivalent
+        for(var i = 0; i < months.length; i++) {
+                aa = aa.replace(months[i], (i+13)%12);
+        };
+
+        // Replace multiple spaces and anything that is not valid in the parsing of the date, then trim
+        aa = aa.replace(/\s+/g, " ").replace(/([^\d\s\/-:.])/g, "").replace(/^\s\s*/, '').replace(/\s\s*$/, '');
+
+        // No timestamp at the end, then return -1
+        if(aa.search(/(\d){2}:(\d){2}(:(\d){2})?$/) == -1) { return -1; };
+
+        // Grab the timestamp
+        var timestamp = aa.match(/(\d){2}:(\d){2}(:(\d){2})?$/)[0].replace(/:/g, "");
+
+        // Make the timestamp 6 characters by default
+        if(timestamp.length == 4) { timestamp += "00"; };
+
+        // Remove it from the string to assist the date parser, then trim
+        aa = aa.replace(/(\d){2}:(\d){2}(:(\d){2})?$/, "").replace(/\s\s*$/, '');
+
+        // If you want the parser to favour the parsing of European dd/mm/yyyy dates then leave this set to "true"
+        // If you want the parser to favour the parsing of American mm/dd/yyyy dates then set to "false"
+        var favourDMY = true;
+
+        // If you have a regular expression you wish to add, add the Object to the end of the array
+        var dateTest = [
+                       { regExp:/^(0?[1-9]|1[012])([- \/.])(0?[1-9]|[12][0-9]|3[01])([- \/.])((\d\d)?\d\d)$/, d:3, m:1, y:5 },  // mdy
+                       { regExp:/^(0?[1-9]|[12][0-9]|3[01])([- \/.])(0?[1-9]|1[012])([- \/.])((\d\d)?\d\d)$/, d:1, m:3, y:5 },  // dmy
+                       { regExp:/^(\d\d\d\d)([- \/.])(0?[1-9]|1[012])([- \/.])(0?[1-9]|[12][0-9]|3[01])$/, d:5, m:3, y:1 }      // ymd
+                       ];
+
+        var start,y,m,d;
+        var cnt = 0;
+        var numFormats = dateTest.length;
+        while(cnt < numFormats) {
+               start = (cnt + (favourDMY ? numFormats + 1 : numFormats)) % numFormats;
+               if(aa.match(dateTest[start].regExp)) {
+                       res = aa.match(dateTest[start].regExp);
+                       y = res[dateTest[start].y];
+                       m = res[dateTest[start].m];
+                       d = res[dateTest[start].d];
+                       if(m.length == 1) m = "0" + String(m);
+                       if(d.length == 1) d = "0" + String(d);
+                       if(y.length != 4) y = (parseInt(y) < 50) ? "20" + String(y) : "19" + String(y);
+
+                       return y+String(m)+d+String(timestamp);
+               };
+               cnt++;
+        };
+        return -1;
+};
+
+/*
+    sortAlphaNumeric
+    -----------------------
+
+    This function sorts alphaNumeric values e.g. 1, e, 1a, -23c, 54z
+    
+    Notice how the prepareData function actually returns an Array i.e. you are not limited
+    in the type of data you return to the tableSort script.
+*/
+function sortAlphaNumericPrepareData(tdNode, innerText){
+        var aa = innerText.toLowerCase().replace(" ", "");
+        var reg = /((\-|\+)?(\s+)?[0-9]+\.([0-9]+)?|(\-|\+)?(\s+)?(\.)?[0-9]+)([a-z]+)/;
+
+        if(reg.test(aa)) {
+                var aaP = aa.match(reg);
+                return [aaP[1], aaP[8]];
+        };
+
+        // Return an array
+        return isNaN(aa) ? ["",aa] : [aa,""];
+}
+
+function sortAlphaNumeric(a, b){
+        // Get the previously prepared array
+        var aa = a[fdTableSort.pos];
+        var bb = b[fdTableSort.pos];
+
+        // If they are equal then return 0
+        if(aa[0] == bb[0] && aa[1] == bb[1]) { return 0; };
+
+        // Check numeric parts if not equal
+        if(aa[0] != bb[0]) {
+                if(aa[0] != "" && bb[0] != "") { return aa[0] - bb[0]; };
+                if(aa[0] == "" && bb[0] != "") { return -1; };
+                return 1;
+        };
+        
+        // Check alpha parts if numeric parts equal
+        if(aa[1] == bb[1]) return 0;
+        if(aa[1] < bb[1])  return -1;
+        return 1;
+}
+
+/*
+    sortDutchCurrencyValues
+    -----------------------
+
+    This function sorts Dutch currency values (of the type 100.000,00)
+    The function is "safe" i.e. non-currency data (like the word "Unknown") can be passed in and is sorted properly.
+*/
+var sortDutchCurrencyValues = fdTableSort.sortNumeric;
+
+function sortDutchCurrencyValuesPrepareData(tdNode, innerText) {
+        innerText = parseInt(innerText.replace(/[^0-9\.,]+/g, "").replace(/\./g,"").replace(",","."));
+        return isNaN(innerText) ? "" : innerText;
+}
+
+/*
+   sortByTwelveHourTimestamp
+   -------------------------
+
+   This custom sort function sorts 12 hour timestamps of an hour/minute nature.
+   The hour/minute dividor can be a full-stop or a colon and it correctly calculates that 12.30am is before 1am etc
+   The am/pm part can be written in lower or uppercase and can optionally contain full-stops e.g.
+
+   am, a.m, a.m., AM, A.M etc
+
+   Additionally, the values "12 midnight" and "12 noon" are also handled correctly.
+
+   The question remains... does "12p.m." mean "midnight" or "12 noon"? I've decided here that it's 12 noon.
+
+   The function is "safe" i.e. non-timestamp data (like the word "Unknown") can be passed in and is sorted properly.
+*/
+var sortByTwelveHourTimestamp = fdTableSort.sortNumeric;
+
+function sortByTwelveHourTimestampPrepareData(tdNode, innerText) {
+        tmp = innerText
+        innerText = innerText.replace(":",".");
+
+        // Check for the special cases of "12 noon" or "12 midnight"
+        if(innerText.search(/12([\s]*)?noon/i) != -1) return "12.00";
+        if(innerText.search(/12([\s]*)?midnight/i) != -1) return "24.00";
+
+        var regExpPM = /^([0-9]{1,2}).([0-9]{2})([\s]*)?(p[\.]?m)/i;
+        var regExpAM = /^([0-9]{1,2}).([0-9]{2})([\s]*)?(a[\.]?m)/i;
+
+        if(innerText.search(regExpPM) != -1) {
+                var bits = innerText.match(regExpPM);
+                if(parseInt(bits[1]) < 12) { bits[1] = parseInt(bits[1]) + 12; }
+        } else if(innerText.search(regExpAM) != -1) {
+                var bits = innerText.match(regExpAM);
+                if(bits[1] == "12") { bits[1] = "00"; }
+        } else return "";
+
+        if(bits[2].length < 2) { bits[2] = "0" + String(bits[2]); }
+
+        innerText = bits[1] + "." + String(bits[2]);
+
+        return isNaN(innerText) ? "" : innerText;
+}
+/*
+   sortEnglishLonghandDateFormat
+   -----------------------------
+
+   This custom sort function sorts dates of the format:
+
+   "12th April, 2006" or "12 April 2006" or "12-4-2006" or "12 April" or "12 4" or "12 Apr 2006" etc
+
+   The function expects dates to be in the format day/month/year. Should no year be stipulated,
+   the function treats the year as being the current year.
+
+   The function is "safe" i.e. non-date data (like the word "Unknown") can be passed in and is sorted properly.
+*/
+var sortEnglishLonghandDateFormat = fdTableSort.sortNumeric;
+
+function sortEnglishLonghandDateFormatPrepareData(tdNode, innerText) {
+        var months = ['january','february','march','april','may','june','july','august','september','october','november','december'];
+
+        var aa = innerText.toLowerCase();
+
+        // Replace the longhand months with an integer equivalent
+        for(var i = 0; i < 12; i++) {
+                aa = aa.replace(months[i], i+1).replace(months[i].substring(0,3), i+1);
+        }
+
+        // If there are still alpha characters then return -1
+        if(aa.search(/a-z/) != -1) return -1;
+
+        // Replace multiple spaces and anything that is not numeric
+        aa = aa.replace(/\s+/g, " ").replace(/[^\d\s]/g, "");
+
+        // If were left with nothing then return -1
+        if(aa.replace(" ", "") == "") return -1;
+
+        // Split on the (now) single spaces
+        aa = aa.split(" ");
+
+        // If something has gone terribly wrong then return -1
+        if(aa.length < 2) return -1;
+
+        // If no year stipulated, then add this year as default
+        if(aa.length == 2) {
+                aa[2] = String(new Date().getFullYear());
+        }
+
+        // Equalise the day and month
+        if(aa[0].length < 2) aa[0] = "0" + String(aa[0]);
+        if(aa[1].length < 2) aa[1] = "0" + String(aa[1]);
+
+        // Deal with Y2K issues
+        if(aa[2].length != 4) {
+                aa[2] = (parseInt(aa[2]) < 50) ? '20' + aa[2] : '19' + aa[2];
+        }
+
+        // YMD (can be used as integer during comparison)
+        return aa[2] + String(aa[1]) + aa[0];
+}
+/*
+   sortIPAddress
+   -------------
+
+   This custom sort function correctly sorts IP addresses i.e. it checks all of the address parts and not just the first.
+
+   The function is "safe" i.e. non-IP address data (like the word "Unknown") can be passed in and is sorted properly.
+*/
+var sortIPAddress = fdTableSort.sortNumeric;
+
+function sortIPAddressPrepareData(tdNode, innerText) {
+        // Get the innerText of the TR nodes
+        var aa = innerText;
+
+        // Remove spaces
+        aa = aa.replace(" ","");
+
+        // If not an IP address then return -1
+        if(aa.search(/^([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3})$/) == -1) return -1;
+
+        // Split on the "."
+        aa = aa.split(".");
+
+        // If we don't have 4 parts then return -1
+        if(aa.length != 4) return -1;
+
+        var retVal = "";
+
+        // Make all the parts an equal length and create a master integer
+        for(var i = 0; i < 4; i++) {
+                retVal += (String(aa[i]).length < 3) ? "0000".substr(0, 3 - String(aa[i]).length) + String(aa[i]) : aa[i];
+        }
+
+        return retVal;
+}
+/*
+   sortScientificNotation
+   ----------------------
+
+   This custom sort function sorts numbers stipulated in scientific notation
+
+   The function is "safe" i.e. data like the word "Unknown" can be passed in and is sorted properly.
+
+   N.B. The only way I can think to really sort scientific notation is to convert
+        it to a floating point number and then perform the sort on that. If you can think of
+        an easier/better way then please let me know.
+*/
+var sortScientificNotation = fdTableSort.sortNumeric;
+
+function sortScientificNotationPrepareData(tdNode, innerText) {
+        var aa = innerText;
+
+        var floatRegExp = /((\-|\+)?(\s+)?[0-9]+\.([0-9]+)?|(\-|\+)?(\s+)?(\.)?[0-9]+)/g;
+
+        aa = aa.match(floatRegExp);
+
+        if(!aa || aa.length != 2) return "";
+
+        var f1 = parseFloat(aa[0].replace(" ",""))*Math.pow(10,parseFloat(aa[1].replace(" ","")));
+        return isNaN(f1) ? "" : f1;
+}
+
+/*
+        sortImage
+        ---------
+
+        This is the function called in order to sort the data previously prepared by the function
+        "sortImagePrepareData". It does a basic case sensitive comparison on the data using the
+        tableSort's in-built sortText method.
+*/
+var sortImage = fdTableSort.sortText;
+
+/*
+        This is the function used to prepare i.e. parse data, to be used during the sort
+        of the images within the last table.
+
+        In this case, we are checking to see if the TD node has any child nodes that are
+        images and, if an image exists, return it's "src" attribute.
+        If no image exists, then we return an empty string.
+
+        The "prepareData" functions are passed the actual TD node and also the TD node inner text
+        which means you are free to check for child nodes etc and are not just limited to
+        sorting on the TD node's inner text.
+
+        The prepareData functions are not required (only your bespoke sort function is required)
+        and only called by the script should they exist.
+*/
+function sortImagePrepareData(td, innerText) {
+        var img = td.getElementsByTagName('img');
+        return img.length ? img[0].src: "";
+}
+
+/*
+        sortFileSize
+        ------------
+
+        1 Byte = 8 Bit
+        1 Kilobyte = 1024 Bytes
+        1 Megabyte = 1048576 Bytes
+        1 Gigabyte = 1073741824 Bytes
+*/
+var sortFileSize = fdTableSort.sortNumeric;
+
+function sortFileSizePrepareData(td, innerText) {
+        var regExp = /(kb|mb|gb)/i;
+
+        var type = innerText.search(regExp) != -1 ? innerText.match(regExp)[0] : "";
+
+        switch (type.toLowerCase()) {
+                case "kb" :
+                        mult = 1024;
+                        break;
+                case "mb" :
+                        mult = 1048576;
+                        break;
+                case "gb" :
+                        mult = 1073741824;
+                        break;
+                default :
+                        mult = 1;
+        };
+
+        innerText = parseFloat(innerText.replace(/[^0-9\.\-]/g,''));
+
+        return isNaN(innerText) ? "" : innerText * mult;
+};
index 0dfcc7d..871c100 100644 (file)
-/*\r
-        paginate table object v2.0 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 tablePaginater = (function() {\r
-        /*\r
-\r
-        Localise the button titles here...\r
-\r
-        %p is replaced with the appropriate page number\r
-        %t is replaced with the total number of pages\r
-        \r
-        */\r
-        var tableInfo = {},\r
-            uniqueID  = 0,\r
-            text      = ["First Page","Previous Page (Page %p)","Next Page (Page %p)","Last Page (Page %t)","Page %p of %t"];\r
-            \r
-        var addClass = function(e,c) {\r
-                if(new RegExp("(^|\\s)" + c + "(\\s|$)").test(e.className)) return;\r
-                e.className += ( e.className ? " " : "" ) + c;\r
-        }; \r
-        \r
-        /*@cc_on\r
-        /*@if (@_win32)\r
-        var removeClass = function(e,c) {\r
-                e.className = !c ? "" : e.className.replace(new RegExp("(^|\\s)" + c + "(\\s|$)"), " ").replace(/^\s*((?:[\S\s]*\S)?)\s*$/, '$1');\r
-        };\r
-        @else @*/\r
-        var removeClass = function(e,c) {                 \r
-                e.className = !c ? "" : (e.className || "").replace(new RegExp("(^|\\s)" + c + "(\\s|$)"), " ").replace(/^\s\s*/, '').replace(/\s\s*$/, '');\r
-        };\r
-        /*@end\r
-        @*/  \r
-        \r
-        var addEvent = function(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
-        var removeEvent = function(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
-        var stopEvent = function(e) {\r
-                e = e || window.event;\r
-                if(e.stopPropagation) {\r
-                        e.stopPropagation();\r
-                        e.preventDefault();\r
-                };\r
-                \r
-                /*@cc_on@*/\r
-                /*@if(@_win32)\r
-                e.cancelBubble = true;\r
-                e.returnValue  = false;\r
-                /*@end@*/\r
-                return false;\r
-        }; \r
-        \r
-        var init = function(tableId) {\r
-                var tables = tableId && typeof(tableId) == "string" ? [document.getElementById(tableId)] : document.getElementsByTagName('table'),\r
-                    hook, maxPages, visibleRows, numPages, cp, cb, rowList;\r
-                \r
-                for(var t = 0, tbl; tbl = tables[t]; t++) {\r
-                        if(tbl.className.search(/paginate-([0-9]+)/) == -1) { continue; };\r
-\r
-                        if(!tbl.id) { tbl.id = "fdUniqueTableId_" + uniqueID++; };\r
-\r
-                        maxPages = tbl.className.search(/max-pages-([0-9]+)/) == -1 ? null : Number(tbl.className.match(/max-pages-([0-9]+)/)[1]);\r
-                        if(maxPages % 2 == 0 && maxPages > 1) { maxPages--; };\r
-                        \r
-                        hook = tbl.getElementsByTagName('tbody');\r
-                        hook = (hook.length) ? hook[0] : tbl;\r
-\r
-                        visibleRows = calculateVisibleRows(hook);\r
-                        \r
-                        if(maxPages > (visibleRows / Number(tbl.className.match(/paginate-([0-9]+)/)[1]))) {\r
-                                maxPages = null;\r
-                        };\r
-                        \r
-                        numPages = Math.ceil(visibleRows / Number(tbl.className.match(/paginate-([0-9]+)/)[1]));\r
-                        \r
-                        if(numPages < 2 && !(tbl.id in tableInfo)) {\r
-                                continue;\r
-                        };\r
-                        \r
-                        cp = (tbl.id in tableInfo) ? Math.min(tableInfo[tbl.id].currentPage, numPages) : 1;\r
-                        \r
-                        tableInfo[tbl.id] = {\r
-                                rowsPerPage:Number(tbl.className.match(/paginate-([0-9]+)/)[1]),\r
-                                currentPage:cp,\r
-                                totalRows:hook.getElementsByTagName('tr').length,\r
-                                hook:hook,\r
-                                maxPages:maxPages,\r
-                                numPages:numPages,\r
-                                rowStyle:tbl.className.search(/rowstyle-([\S]+)/) != -1 ? tbl.className.match(/rowstyle-([\S]+)/)[1] : false,\r
-                                callbacks:parseCallback(/^paginationcallback-/i, /paginationcallback-([\S-]+)/ig, tbl.className)\r
-                        };\r
-                        \r
-                        showPage(tbl.id);\r
-                        hook = null;\r
-                };\r
-        };\r
-        \r
-        var parseCallback = function(head, regExp, cname) {\r
-                var cbs    = [],\r
-                    matchs = cname.match(regExp),\r
-                    parts, obj, func;\r
-                \r
-                if(!matchs) { return []; };\r
-                  \r
-                for(var i = 0, mtch; mtch = matchs[i]; i++) {                         \r
-                        mtch = mtch.replace(head, "").replace(/-/g, ".");\r
-                         \r
-                        try {\r
-                                if(mtch.indexOf(".") != -1) {\r
-                                        parts = mtch.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[mtch];\r
-                                };\r
-                            \r
-                                if(!(func instanceof Function)) continue;\r
-                                cbs[cbs.length] = func;                              \r
-                        } catch(err) {};\r
-                };\r
-                \r
-                return cbs;                      \r
-        };\r
-                \r
-        var callback = function(tblId, opts) {                \r
-                if(!(tblId in tableInfo) || !(tableInfo[tblId]["callbacks"].length)) return;                \r
-                for(var i = 0, func; func = tableInfo[tblId]["callbacks"][i]; i++) {\r
-                        func(opts || {});\r
-                };\r
-        };\r
-        \r
-        var calculateVisibleRows = function(hook) {\r
-                var trs = hook.rows,\r
-                    cnt = 0,\r
-                    reg = /(^|\s)invisibleRow(\s|$)/;\r
-                \r
-                for(var i = 0, tr; tr = trs[i]; i++) {\r
-                        if(tr.parentNode != hook || tr.getElementsByTagName("th").length || (tr.parentNode && tr.parentNode.tagName.toLowerCase().search(/thead|tfoot/) != -1)) continue;\r
-                        if(tr.className.search(reg) == -1) { cnt++; };\r
-                };\r
-                \r
-                return cnt;\r
-        };\r
-        \r
-        var createButton = function(details, ul, pseudo) {\r
-                var li   = document.createElement("li"),\r
-                    but  = document.createElement(pseudo ? "div" : "a"),\r
-                    span = document.createElement("span");\r
-\r
-                if(!pseudo) { \r
-                        but.href = "#"; \r
-                        but.title = details.title; \r
-                };\r
-                \r
-                but.className = details.className;\r
-\r
-                ul.appendChild(li);\r
-                li.appendChild(but);\r
-                but.appendChild(span);\r
-                span.appendChild(document.createTextNode(details.text));\r
-\r
-                if(!pseudo) { \r
-                        li.onclick = but.onclick = buttonClick; \r
-                        if(details.id) { but.id = details.id; };\r
-                };                 \r
-                \r
-                li = but = span = null;\r
-        };\r
-        var removePagination = function(tableId) {\r
-                var wrapT = document.getElementById(tableId + "-fdtablePaginaterWrapTop"),\r
-                    wrapB = document.getElementById(tableId + "-fdtablePaginaterWrapBottom");\r
-                if(wrapT) { wrapT.parentNode.removeChild(wrapT); };\r
-                if(wrapB) { wrapB.parentNode.removeChild(wrapB); };\r
-        };\r
-        var buildPagination = function(tblId) {\r
-                if(!(tblId in tableInfo)) { return; };\r
-\r
-                removePagination(tblId);\r
-\r
-                var details = tableInfo[tblId];\r
-                \r
-                if(details.numPages < 2) return;\r
-                \r
-                function resolveText(txt, curr) {\r
-                        curr = curr || details.currentPage;\r
-                        return txt.replace("%p", curr).replace("%t", details.numPages);\r
-                };\r
-\r
-                if(details.maxPages) {\r
-                        findex = Math.max(0, Math.floor(Number(details.currentPage - 1) - (Number(details.maxPages - 1) / 2)));\r
-                        lindex = findex + Number(details.maxPages);\r
-                        if(lindex > details.numPages) {\r
-                                lindex = details.numPages;\r
-                                findex = Math.max(0, details.numPages - Number(details.maxPages));\r
-                        };\r
-                } else {\r
-                        findex = 0;\r
-                        lindex = details.numPages;\r
-                };\r
-                \r
-\r
-                var wrapT = document.createElement("div");\r
-                wrapT.className = "fdtablePaginaterWrap";\r
-                wrapT.id = tblId + "-fdtablePaginaterWrapTop";\r
-\r
-                var wrapB = document.createElement("div");\r
-                wrapB.className = "fdtablePaginaterWrap";\r
-                wrapB.id = tblId + "-fdtablePaginaterWrapBottom";\r
-\r
-                // Create list scaffold\r
-                var ulT = document.createElement("ul");\r
-                ulT.id  = tblId + "-tablePaginater";\r
-\r
-                var ulB = document.createElement("ul");\r
-                ulB.id  = tblId + "-tablePaginaterClone";\r
-                ulT.className = ulB.className = "fdtablePaginater";\r
-\r
-                // Add to the wrapper DIVs\r
-                wrapT.appendChild(ulT);\r
-                wrapB.appendChild(ulB);\r
-\r
-                // FIRST (only created if maxPages set)\r
-                if(details.maxPages) {\r
-                        createButton({title:text[0], className:"first-page", text:"\u00ab"}, ulT, !findex);\r
-                        createButton({title:text[0], className:"first-page", text:"\u00ab"}, ulB, !findex);\r
-                };\r
-                \r
-                // PREVIOUS (only created if there are more than two pages)\r
-                if(details.numPages > 2) {\r
-                        createButton({title:resolveText(text[1], details.currentPage-1), className:"previous-page", text:"\u2039", id:tblId+"-previousPage"}, ulT, details.currentPage == 1);\r
-                        createButton({title:resolveText(text[1], details.currentPage-1), className:"previous-page", text:"\u2039", id:tblId+"-previousPageC"}, ulB, details.currentPage == 1);\r
-                };\r
-                \r
-                // NUMBERED\r
-                for(var i = findex; i < lindex; i++) {\r
-                        createButton({title:resolveText(text[4], i+1), className:i != (details.currentPage-1) ? "page-"+(i+1) : "currentPage page-"+(i+1), text:(i+1), id:i == (details.currentPage-1) ? tblId + "-currentPage" : ""}, ulT);\r
-                        createButton({title:resolveText(text[4], i+1), className:i != (details.currentPage-1) ? "page-"+(i+1) : "currentPage page-"+(i+1), text:(i+1), id:i == (details.currentPage-1) ? tblId + "-currentPageC" : ""}, ulB);\r
-                };\r
-\r
-                // NEXT (only created if there are more than two pages)\r
-                if(details.numPages > 2) {\r
-                        createButton({title:resolveText(text[2], details.currentPage + 1), className:"next-page", text:"\u203a", id:tblId+"-nextPage"}, ulT, details.currentPage == details.numPages);\r
-                        createButton({title:resolveText(text[2], details.currentPage + 1), className:"next-page", text:"\u203a", id:tblId+"-nextPageC"}, ulB, details.currentPage == details.numPages);\r
-                };\r
-                \r
-                // LAST (only created if maxPages set)\r
-                if(details.maxPages) {\r
-                        createButton({title:resolveText(text[3], details.numPages), className:"last-page", text:"\u00bb"}, ulT, lindex == details.numPages);\r
-                        createButton({title:resolveText(text[3], details.numPages), className:"last-page", text:"\u00bb"}, ulB, lindex == details.numPages);\r
-                };\r
-                \r
-                // DOM inject wrapper DIVs (FireFox 2.x Bug: this has to be done here if you use display:table)\r
-                if(document.getElementById(tblId+"-paginationListWrapTop")) {\r
-                        document.getElementById(tblId+"-paginationListWrapTop").appendChild(wrapT);\r
-                } else {\r
-                        document.getElementById(tblId).parentNode.insertBefore(wrapT, document.getElementById(tblId));\r
-                };\r
-\r
-                if(document.getElementById(tblId+"-paginationListWrapBottom")) {\r
-                        document.getElementById(tblId+"-paginationListWrapBottom").appendChild(wrapB);\r
-                } else {\r
-                        document.getElementById(tblId).parentNode.insertBefore(wrapB, document.getElementById(tblId).nextSibling);\r
-                };\r
-        };\r
-        \r
-        // The tableSort script uses this function to redraw.\r
-        var tableSortRedraw = function(tableid, identical) {\r
-                if(!tableid || !(tableid in fdTableSort.tableCache) || !(tableid in tableInfo)) { return; };\r
-                \r
-                var dataObj     = fdTableSort.tableCache[tableid],\r
-                    data        = dataObj.data,\r
-                    len1        = data.length,\r
-                    len2        = len1 ? data[0].length - 1 : 0,\r
-                    hook        = dataObj.hook,\r
-                    colStyle    = dataObj.colStyle,\r
-                    rowStyle    = dataObj.rowStyle,\r
-                    colOrder    = dataObj.colOrder,                 \r
-                    page        = tableInfo[tableid].currentPage - 1,\r
-                    d1          = tableInfo[tableid].rowsPerPage * page,\r
-                    d2          = Math.min(tableInfo[tableid].totalRows, d1 + tableInfo[tableid].rowsPerPage), \r
-                    cnt         = 0,\r
-                    rs          = 0,\r
-                    reg         = /(^|\s)invisibleRow(\s|$)/,                \r
-                    tr, tds, cell, pos;\r
-                \r
-                for(var i = 0; i < len1; i++) {\r
-                        tr = data[i][len2];\r
-                        \r
-                        if(colStyle) {\r
-                                tds = tr.cells;\r
-                                for(thPos in colOrder) {\r
-                                        if(!colOrder[thPos]) removeClass(tds[thPos], colStyle);\r
-                                        else addClass(tds[thPos], colStyle);\r
-                                };\r
-                        };\r
-                        \r
-                        if(tr.className.search(reg) != -1) { continue; };\r
-                        \r
-                        if(!identical) {\r
-                                cnt++;\r
-\r
-                                if(cnt > d1 && cnt <= d2) {\r
-                                        if(rowStyle) {\r
-                                                if(rs++ & 1) addClass(tr, rowStyle);\r
-                                                else removeClass(tr, rowStyle);\r
-                                        };\r
-                                        tr.style.display = "";\r
-                                } else {\r
-                                        tr.style.display = "none";\r
-                                };\r
-\r
-                                // Netscape 8.1.2 requires the removeChild call or it freaks out, so add the line if you want to support this browser\r
-                                // hook.removeChild(tr);\r
-                                hook.appendChild(tr);\r
-                        };\r
-                };\r
-\r
-                tr = tds = hook = null;\r
-        };\r
-        \r
-        var showPage = function(tblId, pageNum) {\r
-                if(!(tblId in tableInfo)) { return; };\r
-\r
-                var page = Math.max(0, !pageNum ? tableInfo[tblId].currentPage - 1 : pageNum - 1),\r
-                    d1  = tableInfo[tblId].rowsPerPage * page,\r
-                    d2  = Math.min(tableInfo[tblId].totalRows, d1 + tableInfo[tblId].rowsPerPage),\r
-                    trs = tableInfo[tblId].hook.rows,\r
-                    cnt = 0,\r
-                    rc  = 0,\r
-                    len = trs.length,\r
-                    rs  = tableInfo[tblId].rowStyle,\r
-                    reg = /(^|\s)invisibleRow(\s|$)/,\r
-                    row = [];\r
-                \r
-                for(var i = 0; i < len; i++) {\r
-                        if(trs[i].className.search(reg) != -1 || trs[i].getElementsByTagName("th").length || (trs[i].parentNode && trs[i].parentNode.tagName.toLowerCase().search(/thead|tfoot/) != -1)) { continue; };\r
-                        \r
-                        cnt++;\r
-                        \r
-                        if(cnt > d1 && cnt <= d2) {\r
-                                if(rs) {\r
-                                        if(rc++ & 1) {\r
-                                                addClass(trs[i], rs);\r
-                                        } else {\r
-                                                removeClass(trs[i], rs);\r
-                                        }\r
-                                };\r
-                                trs[i].style.display = "";\r
-                                row[row.length] = trs[i];\r
-                        } else {\r
-                                trs[i].style.display = "none";\r
-                        };\r
-                };\r
-\r
-                buildPagination(tblId);\r
-                callback(tblId, {"totalRows":len, "currentPage":(page+1), "rowsPerPage":tableInfo[tblId].rowsPerPage, "visibleRows":row});\r
-        };\r
-        \r
-        var buttonClick = function(e) {\r
-                e = e || window.event;\r
-\r
-                var a = this.tagName.toLowerCase() == "a" ? this : this.getElementsByTagName("a")[0];\r
-\r
-                if(a.className.search("currentPage") != -1) return false;\r
-\r
-                var ul = this;\r
-                while(ul.tagName.toLowerCase() != "ul") ul = ul.parentNode;\r
-\r
-                var tblId = ul.id.replace("-tablePaginaterClone","").replace("-tablePaginater", "");\r
-\r
-                tableInfo[tblId].lastPage = tableInfo[tblId].currentPage;\r
-                \r
-                var showPrevNext = 0;\r
-                \r
-                if(a.className.search("previous-page") != -1) {\r
-                        tableInfo[tblId].currentPage = tableInfo[tblId].currentPage > 1 ? tableInfo[tblId].currentPage - 1 : tableInfo[tblId].numPages;\r
-                        showPrevNext = 1;\r
-                } else if(a.className.search("next-page") != -1) {\r
-                        tableInfo[tblId].currentPage = tableInfo[tblId].currentPage < tableInfo[tblId].numPages ? tableInfo[tblId].currentPage + 1 : 1;\r
-                        showPrevNext = 2;\r
-                } else if(a.className.search("first-page") != -1) {\r
-                        tableInfo[tblId].currentPage = 1;\r
-                } else if(a.className.search("last-page") != -1) {\r
-                        tableInfo[tblId].currentPage = tableInfo[tblId].numPages;\r
-                } else {\r
-                        tableInfo[tblId].currentPage = parseInt(a.className.match(/page-([0-9]+)/)[1]) || 1;\r
-                };\r
-\r
-                showPage(tblId);\r
-\r
-                // Focus on the appropriate button (previous, next or the current page)\r
-                // I'm hoping screen readers are savvy enough to indicate the focus event to the user\r
-                if(showPrevNext == 1) {\r
-                        var elem = document.getElementById(ul.id.search("-tablePaginaterClone") != -1 ? tblId + "-previousPageC" : tblId + "-previousPage");\r
-                } else if(showPrevNext == 2) {\r
-                        var elem = document.getElementById(ul.id.search("-tablePaginaterClone") != -1 ? tblId + "-nextPageC" : tblId + "-nextPage");\r
-                } else {\r
-                        var elem = document.getElementById(ul.id.search("-tablePaginaterClone") != -1 ? tblId + "-currentPageC" : tblId + "-currentPage");\r
-                };\r
-                \r
-                if(elem && elem.tagName.toLowerCase() == "a") { elem.focus(); };   \r
-                \r
-                return stopEvent(e);\r
-        };\r
-        \r
-        var onUnLoad = function(e) {\r
-                var tbl, lis, pagination, uls;\r
-                for(tblId in tableInfo) {\r
-                        uls = [tblId + "-tablePaginater", tblId + "-tablePaginaterClone"];\r
-                        for(var z = 0; z < 2; z++) {\r
-                                pagination = document.getElementById(uls[z]);\r
-                                if(!pagination) { continue; };\r
-                                lis = pagination.getElementsByTagName("li");\r
-                                for(var i = 0, li; li = lis[i]; i++) {\r
-                                        li.onclick = null;\r
-                                        if(li.getElementsByTagName("a").length) { li.getElementsByTagName("a")[0].onclick = null; };\r
-                                };\r
-                        };\r
-                };\r
-        };\r
-        \r
-        addEvent(window, "load",   init);\r
-        addEvent(window, "unload", onUnLoad); \r
-        \r
-        return {                  \r
-                init:                   function(tableId) { init(tableId); },                 \r
-                redraw:                 function(tableid, identical) { tableSortRedraw(tableid, identical); },\r
-                tableIsPaginated:       function(tableId) { return (tableId in tableInfo); },\r
-                changeTranslations:     function(translations) { text = translations; }\r
-        };        \r
+/*
+        paginate table object v2.0 by frequency-decoder.com
+
+        Released under a creative commons Attribution-ShareAlike 2.5 license (http://creativecommons.org/licenses/by-sa/2.5/)
+
+        Please credit frequency decoder in any derivative work - thanks
+
+        You are free:
+
+        * to copy, distribute, display, and perform the work
+        * to make derivative works
+        * to make commercial use of the work
+
+        Under the following conditions:
+
+                by Attribution.
+                --------------
+                You must attribute the work in the manner specified by the author or licensor.
+
+                sa
+                --
+                Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license identical to this one.
+
+        * For any reuse or distribution, you must make clear to others the license terms of this work.
+        * Any of these conditions can be waived if you get permission from the copyright holder.
+*/
+
+var tablePaginater = (function() {
+        /*
+
+        Localise the button titles here...
+
+        %p is replaced with the appropriate page number
+        %t is replaced with the total number of pages
+        
+        */
+        var tableInfo = {},
+            uniqueID  = 0,
+            text      = ["First Page","Previous Page (Page %p)","Next Page (Page %p)","Last Page (Page %t)","Page %p of %t"];
+            
+        var addClass = function(e,c) {
+                if(new RegExp("(^|\\s)" + c + "(\\s|$)").test(e.className)) return;
+                e.className += ( e.className ? " " : "" ) + c;
+        }; 
+        
+        /*@cc_on
+        /*@if (@_win32)
+        var removeClass = function(e,c) {
+                e.className = !c ? "" : e.className.replace(new RegExp("(^|\\s)" + c + "(\\s|$)"), " ").replace(/^\s*((?:[\S\s]*\S)?)\s*$/, '$1');
+        };
+        @else @*/
+        var removeClass = function(e,c) {                 
+                e.className = !c ? "" : (e.className || "").replace(new RegExp("(^|\\s)" + c + "(\\s|$)"), " ").replace(/^\s\s*/, '').replace(/\s\s*$/, '');
+        };
+        /*@end
+        @*/  
+        
+        var addEvent = function(obj, type, fn) {
+                if( obj.attachEvent ) {
+                        obj["e"+type+fn] = fn;
+                        obj[type+fn] = function(){obj["e"+type+fn]( window.event );};
+                        obj.attachEvent( "on"+type, obj[type+fn] );
+                } else {
+                        obj.addEventListener( type, fn, true );
+                };
+        };
+        var removeEvent = function(obj, type, fn) {
+                try {
+                        if( obj.detachEvent ) {
+                                obj.detachEvent( "on"+type, obj[type+fn] );
+                                obj[type+fn] = null;
+                        } else {
+                                obj.removeEventListener( type, fn, true );
+                        };
+                } catch(err) {};
+        };
+        var stopEvent = function(e) {
+                e = e || window.event;
+                if(e.stopPropagation) {
+                        e.stopPropagation();
+                        e.preventDefault();
+                };
+                
+                /*@cc_on@*/
+                /*@if(@_win32)
+                e.cancelBubble = true;
+                e.returnValue  = false;
+                /*@end@*/
+                return false;
+        }; 
+        
+        var init = function(tableId) {
+                var tables = tableId && typeof(tableId) == "string" ? [document.getElementById(tableId)] : document.getElementsByTagName('table'),
+                    hook, maxPages, visibleRows, numPages, cp, cb, rowList;
+                
+                for(var t = 0, tbl; tbl = tables[t]; t++) {
+                        if(tbl.className.search(/paginate-([0-9]+)/) == -1) { continue; };
+
+                        if(!tbl.id) { tbl.id = "fdUniqueTableId_" + uniqueID++; };
+
+                        maxPages = tbl.className.search(/max-pages-([0-9]+)/) == -1 ? null : Number(tbl.className.match(/max-pages-([0-9]+)/)[1]);
+                        if(maxPages % 2 == 0 && maxPages > 1) { maxPages--; };
+                        
+                        hook = tbl.getElementsByTagName('tbody');
+                        hook = (hook.length) ? hook[0] : tbl;
+
+                        visibleRows = calculateVisibleRows(hook);
+                        
+                        if(maxPages > (visibleRows / Number(tbl.className.match(/paginate-([0-9]+)/)[1]))) {
+                                maxPages = null;
+                        };
+                        
+                        numPages = Math.ceil(visibleRows / Number(tbl.className.match(/paginate-([0-9]+)/)[1]));
+                        
+                        if(numPages < 2 && !(tbl.id in tableInfo)) {
+                                continue;
+                        };
+                        
+                        cp = (tbl.id in tableInfo) ? Math.min(tableInfo[tbl.id].currentPage, numPages) : 1;
+                        
+                        tableInfo[tbl.id] = {
+                                rowsPerPage:Number(tbl.className.match(/paginate-([0-9]+)/)[1]),
+                                currentPage:cp,
+                                totalRows:hook.getElementsByTagName('tr').length,
+                                hook:hook,
+                                maxPages:maxPages,
+                                numPages:numPages,
+                                rowStyle:tbl.className.search(/rowstyle-([\S]+)/) != -1 ? tbl.className.match(/rowstyle-([\S]+)/)[1] : false,
+                                callbacks:parseCallback(/^paginationcallback-/i, /paginationcallback-([\S-]+)/ig, tbl.className)
+                        };
+                        
+                        showPage(tbl.id);
+                        hook = null;
+                };
+        };
+        
+        var parseCallback = function(head, regExp, cname) {
+                var cbs    = [],
+                    matchs = cname.match(regExp),
+                    parts, obj, func;
+                
+                if(!matchs) { return []; };
+                  
+                for(var i = 0, mtch; mtch = matchs[i]; i++) {                         
+                        mtch = mtch.replace(head, "").replace(/-/g, ".");
+                         
+                        try {
+                                if(mtch.indexOf(".") != -1) {
+                                        parts = mtch.split('.');
+                                        obj   = window;
+                                        for (var x = 0, part; part = obj[parts[x]]; x++) {
+                                                if(part instanceof Function) {
+                                                        (function() {
+                                                                var method = part;
+                                                                func = function (data) { method.apply(obj, [data]) };
+                                                        })();
+                                                } else {
+                                                        obj = part;
+                                                };
+                                        };
+                                } else {
+                                        func = window[mtch];
+                                };
+                            
+                                if(!(func instanceof Function)) continue;
+                                cbs[cbs.length] = func;                              
+                        } catch(err) {};
+                };
+                
+                return cbs;                      
+        };
+                
+        var callback = function(tblId, opts) {                
+                if(!(tblId in tableInfo) || !(tableInfo[tblId]["callbacks"].length)) return;                
+                for(var i = 0, func; func = tableInfo[tblId]["callbacks"][i]; i++) {
+                        func(opts || {});
+                };
+        };
+        
+        var calculateVisibleRows = function(hook) {
+                var trs = hook.rows,
+                    cnt = 0,
+                    reg = /(^|\s)invisibleRow(\s|$)/;
+                
+                for(var i = 0, tr; tr = trs[i]; i++) {
+                        if(tr.parentNode != hook || tr.getElementsByTagName("th").length || (tr.parentNode && tr.parentNode.tagName.toLowerCase().search(/thead|tfoot/) != -1)) continue;
+                        if(tr.className.search(reg) == -1) { cnt++; };
+                };
+                
+                return cnt;
+        };
+        
+        var createButton = function(details, ul, pseudo) {
+                var li   = document.createElement("li"),
+                    but  = document.createElement(pseudo ? "div" : "a"),
+                    span = document.createElement("span");
+
+                if(!pseudo) { 
+                        but.href = "#"; 
+                        but.title = details.title; 
+                };
+                
+                but.className = details.className;
+
+                ul.appendChild(li);
+                li.appendChild(but);
+                but.appendChild(span);
+                span.appendChild(document.createTextNode(details.text));
+
+                if(!pseudo) { 
+                        li.onclick = but.onclick = buttonClick; 
+                        if(details.id) { but.id = details.id; };
+                };                 
+                
+                li = but = span = null;
+        };
+        var removePagination = function(tableId) {
+                var wrapT = document.getElementById(tableId + "-fdtablePaginaterWrapTop"),
+                    wrapB = document.getElementById(tableId + "-fdtablePaginaterWrapBottom");
+                if(wrapT) { wrapT.parentNode.removeChild(wrapT); };
+                if(wrapB) { wrapB.parentNode.removeChild(wrapB); };
+        };
+        var buildPagination = function(tblId) {
+                if(!(tblId in tableInfo)) { return; };
+
+                removePagination(tblId);
+
+                var details = tableInfo[tblId];
+                
+                if(details.numPages < 2) return;
+                
+                function resolveText(txt, curr) {
+                        curr = curr || details.currentPage;
+                        return txt.replace("%p", curr).replace("%t", details.numPages);
+                };
+
+                if(details.maxPages) {
+                        findex = Math.max(0, Math.floor(Number(details.currentPage - 1) - (Number(details.maxPages - 1) / 2)));
+                        lindex = findex + Number(details.maxPages);
+                        if(lindex > details.numPages) {
+                                lindex = details.numPages;
+                                findex = Math.max(0, details.numPages - Number(details.maxPages));
+                        };
+                } else {
+                        findex = 0;
+                        lindex = details.numPages;
+                };
+                
+
+                var wrapT = document.createElement("div");
+                wrapT.className = "fdtablePaginaterWrap";
+                wrapT.id = tblId + "-fdtablePaginaterWrapTop";
+
+                var wrapB = document.createElement("div");
+                wrapB.className = "fdtablePaginaterWrap";
+                wrapB.id = tblId + "-fdtablePaginaterWrapBottom";
+
+                // Create list scaffold
+                var ulT = document.createElement("ul");
+                ulT.id  = tblId + "-tablePaginater";
+
+                var ulB = document.createElement("ul");
+                ulB.id  = tblId + "-tablePaginaterClone";
+                ulT.className = ulB.className = "fdtablePaginater";
+
+                // Add to the wrapper DIVs
+                wrapT.appendChild(ulT);
+                wrapB.appendChild(ulB);
+
+                // FIRST (only created if maxPages set)
+                if(details.maxPages) {
+                        createButton({title:text[0], className:"first-page", text:"\u00ab"}, ulT, !findex);
+                        createButton({title:text[0], className:"first-page", text:"\u00ab"}, ulB, !findex);
+                };
+                
+                // PREVIOUS (only created if there are more than two pages)
+                if(details.numPages > 2) {
+                        createButton({title:resolveText(text[1], details.currentPage-1), className:"previous-page", text:"\u2039", id:tblId+"-previousPage"}, ulT, details.currentPage == 1);
+                        createButton({title:resolveText(text[1], details.currentPage-1), className:"previous-page", text:"\u2039", id:tblId+"-previousPageC"}, ulB, details.currentPage == 1);
+                };
+                
+                // NUMBERED
+                for(var i = findex; i < lindex; i++) {
+                        createButton({title:resolveText(text[4], i+1), className:i != (details.currentPage-1) ? "page-"+(i+1) : "currentPage page-"+(i+1), text:(i+1), id:i == (details.currentPage-1) ? tblId + "-currentPage" : ""}, ulT);
+                        createButton({title:resolveText(text[4], i+1), className:i != (details.currentPage-1) ? "page-"+(i+1) : "currentPage page-"+(i+1), text:(i+1), id:i == (details.currentPage-1) ? tblId + "-currentPageC" : ""}, ulB);
+                };
+
+                // NEXT (only created if there are more than two pages)
+                if(details.numPages > 2) {
+                        createButton({title:resolveText(text[2], details.currentPage + 1), className:"next-page", text:"\u203a", id:tblId+"-nextPage"}, ulT, details.currentPage == details.numPages);
+                        createButton({title:resolveText(text[2], details.currentPage + 1), className:"next-page", text:"\u203a", id:tblId+"-nextPageC"}, ulB, details.currentPage == details.numPages);
+                };
+                
+                // LAST (only created if maxPages set)
+                if(details.maxPages) {
+                        createButton({title:resolveText(text[3], details.numPages), className:"last-page", text:"\u00bb"}, ulT, lindex == details.numPages);
+                        createButton({title:resolveText(text[3], details.numPages), className:"last-page", text:"\u00bb"}, ulB, lindex == details.numPages);
+                };
+                
+                // DOM inject wrapper DIVs (FireFox 2.x Bug: this has to be done here if you use display:table)
+                if(document.getElementById(tblId+"-paginationListWrapTop")) {
+                        document.getElementById(tblId+"-paginationListWrapTop").appendChild(wrapT);
+                } else {
+                        document.getElementById(tblId).parentNode.insertBefore(wrapT, document.getElementById(tblId));
+                };
+
+                if(document.getElementById(tblId+"-paginationListWrapBottom")) {
+                        document.getElementById(tblId+"-paginationListWrapBottom").appendChild(wrapB);
+                } else {
+                        document.getElementById(tblId).parentNode.insertBefore(wrapB, document.getElementById(tblId).nextSibling);
+                };
+        };
+        
+        // The tableSort script uses this function to redraw.
+        var tableSortRedraw = function(tableid, identical) {
+                if(!tableid || !(tableid in fdTableSort.tableCache) || !(tableid in tableInfo)) { return; };
+                
+                var dataObj     = fdTableSort.tableCache[tableid],
+                    data        = dataObj.data,
+                    len1        = data.length,
+                    len2        = len1 ? data[0].length - 1 : 0,
+                    hook        = dataObj.hook,
+                    colStyle    = dataObj.colStyle,
+                    rowStyle    = dataObj.rowStyle,
+                    colOrder    = dataObj.colOrder,                 
+                    page        = tableInfo[tableid].currentPage - 1,
+                    d1          = tableInfo[tableid].rowsPerPage * page,
+                    d2          = Math.min(tableInfo[tableid].totalRows, d1 + tableInfo[tableid].rowsPerPage), 
+                    cnt         = 0,
+                    rs          = 0,
+                    reg         = /(^|\s)invisibleRow(\s|$)/,                
+                    tr, tds, cell, pos;
+                
+                for(var i = 0; i < len1; i++) {
+                        tr = data[i][len2];
+                        
+                        if(colStyle) {
+                                tds = tr.cells;
+                                for(thPos in colOrder) {
+                                        if(!colOrder[thPos]) removeClass(tds[thPos], colStyle);
+                                        else addClass(tds[thPos], colStyle);
+                                };
+                        };
+                        
+                        if(tr.className.search(reg) != -1) { continue; };
+                        
+                        if(!identical) {
+                                cnt++;
+
+                                if(cnt > d1 && cnt <= d2) {
+                                        if(rowStyle) {
+                                                if(rs++ & 1) addClass(tr, rowStyle);
+                                                else removeClass(tr, rowStyle);
+                                        };
+                                        tr.style.display = "";
+                                } else {
+                                        tr.style.display = "none";
+                                };
+
+                                // Netscape 8.1.2 requires the removeChild call or it freaks out, so add the line if you want to support this browser
+                                // hook.removeChild(tr);
+                                hook.appendChild(tr);
+                        };
+                };
+
+                tr = tds = hook = null;
+        };
+        
+        var showPage = function(tblId, pageNum) {
+                if(!(tblId in tableInfo)) { return; };
+
+                var page = Math.max(0, !pageNum ? tableInfo[tblId].currentPage - 1 : pageNum - 1),
+                    d1  = tableInfo[tblId].rowsPerPage * page,
+                    d2  = Math.min(tableInfo[tblId].totalRows, d1 + tableInfo[tblId].rowsPerPage),
+                    trs = tableInfo[tblId].hook.rows,
+                    cnt = 0,
+                    rc  = 0,
+                    len = trs.length,
+                    rs  = tableInfo[tblId].rowStyle,
+                    reg = /(^|\s)invisibleRow(\s|$)/,
+                    row = [];
+                
+                for(var i = 0; i < len; i++) {
+                        if(trs[i].className.search(reg) != -1 || trs[i].getElementsByTagName("th").length || (trs[i].parentNode && trs[i].parentNode.tagName.toLowerCase().search(/thead|tfoot/) != -1)) { continue; };
+                        
+                        cnt++;
+                        
+                        if(cnt > d1 && cnt <= d2) {
+                                if(rs) {
+                                        if(rc++ & 1) {
+                                                addClass(trs[i], rs);
+                                        } else {
+                                                removeClass(trs[i], rs);
+                                        }
+                                };
+                                trs[i].style.display = "";
+                                row[row.length] = trs[i];
+                        } else {
+                                trs[i].style.display = "none";
+                        };
+                };
+
+                buildPagination(tblId);
+                callback(tblId, {"totalRows":len, "currentPage":(page+1), "rowsPerPage":tableInfo[tblId].rowsPerPage, "visibleRows":row});
+        };
+        
+        var buttonClick = function(e) {
+                e = e || window.event;
+
+                var a = this.tagName.toLowerCase() == "a" ? this : this.getElementsByTagName("a")[0];
+
+                if(a.className.search("currentPage") != -1) return false;
+
+                var ul = this;
+                while(ul.tagName.toLowerCase() != "ul") ul = ul.parentNode;
+
+                var tblId = ul.id.replace("-tablePaginaterClone","").replace("-tablePaginater", "");
+
+                tableInfo[tblId].lastPage = tableInfo[tblId].currentPage;
+                
+                var showPrevNext = 0;
+                
+                if(a.className.search("previous-page") != -1) {
+                        tableInfo[tblId].currentPage = tableInfo[tblId].currentPage > 1 ? tableInfo[tblId].currentPage - 1 : tableInfo[tblId].numPages;
+                        showPrevNext = 1;
+                } else if(a.className.search("next-page") != -1) {
+                        tableInfo[tblId].currentPage = tableInfo[tblId].currentPage < tableInfo[tblId].numPages ? tableInfo[tblId].currentPage + 1 : 1;
+                        showPrevNext = 2;
+                } else if(a.className.search("first-page") != -1) {
+                        tableInfo[tblId].currentPage = 1;
+                } else if(a.className.search("last-page") != -1) {
+                        tableInfo[tblId].currentPage = tableInfo[tblId].numPages;
+                } else {
+                        tableInfo[tblId].currentPage = parseInt(a.className.match(/page-([0-9]+)/)[1]) || 1;
+                };
+
+                showPage(tblId);
+
+                // Focus on the appropriate button (previous, next or the current page)
+                // I'm hoping screen readers are savvy enough to indicate the focus event to the user
+                if(showPrevNext == 1) {
+                        var elem = document.getElementById(ul.id.search("-tablePaginaterClone") != -1 ? tblId + "-previousPageC" : tblId + "-previousPage");
+                } else if(showPrevNext == 2) {
+                        var elem = document.getElementById(ul.id.search("-tablePaginaterClone") != -1 ? tblId + "-nextPageC" : tblId + "-nextPage");
+                } else {
+                        var elem = document.getElementById(ul.id.search("-tablePaginaterClone") != -1 ? tblId + "-currentPageC" : tblId + "-currentPage");
+                };
+                
+                if(elem && elem.tagName.toLowerCase() == "a") { elem.focus(); };   
+                
+                return stopEvent(e);
+        };
+        
+        var onUnLoad = function(e) {
+                var tbl, lis, pagination, uls;
+                for(tblId in tableInfo) {
+                        uls = [tblId + "-tablePaginater", tblId + "-tablePaginaterClone"];
+                        for(var z = 0; z < 2; z++) {
+                                pagination = document.getElementById(uls[z]);
+                                if(!pagination) { continue; };
+                                lis = pagination.getElementsByTagName("li");
+                                for(var i = 0, li; li = lis[i]; i++) {
+                                        li.onclick = null;
+                                        if(li.getElementsByTagName("a").length) { li.getElementsByTagName("a")[0].onclick = null; };
+                                };
+                        };
+                };
+        };
+        
+        addEvent(window, "load",   init);
+        addEvent(window, "unload", onUnLoad); 
+        
+        return {                  
+                init:                   function(tableId) { init(tableId); },                 
+                redraw:                 function(tableid, identical) { tableSortRedraw(tableid, identical); },
+                tableIsPaginated:       function(tableId) { return (tableId in tableInfo); },
+                changeTranslations:     function(translations) { text = translations; }
+        };        
 })();
\ No newline at end of file
index 27e8c3c..9b55e59 100644 (file)
-/*\r
-        TableSort revisited v5.0 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
-(function() {\r
-fdTableSort = {\r
-        regExp_Currency:        /^[£$€¥¤]/,\r
-        regExp_Number:          /^(\-)?[0-9]+(\.[0-9]*)?$/,\r
-        pos:                    -1,\r
-        uniqueHash:             1,\r
-        thNode:                 null,\r
-        tableId:                null,\r
-        tableCache:             {},\r
-        tmpCache:               {},\r
-        sortActiveClass:        "sort-active",\r
-        /*@cc_on\r
-        /*@if (@_win32)\r
-        colspan:                "colSpan",\r
-        rowspan:                "rowSpan",\r
-        @else @*/\r
-        colspan:                "colspan",\r
-        rowspan:                "rowspan",\r
-        /*@end\r
-        @*/\r
-        \r
-        addEvent: function(obj, type, fn, tmp) {\r
-                tmp || (tmp = true);\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
-        removeEvent: function(obj, type, fn, tmp) {\r
-                tmp || (tmp = true);\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
-        stopEvent: function(e) {\r
-                e = e || window.event;\r
-\r
-                if(e.stopPropagation) {\r
-                        e.stopPropagation();\r
-                        e.preventDefault();\r
-                };\r
-                \r
-                /*@cc_on@*/\r
-                /*@if(@_win32)\r
-                e.cancelBubble = true;\r
-                e.returnValue  = false;\r
-                /*@end@*/\r
-                return false;\r
-        },\r
-        parseClassName: function(head, tbl) {\r
-                var colMatch = tbl.className.match(new RegExp(head + "((-[\\d]+([r]){0,1})+)"));\r
-                return colMatch && colMatch.length ? colMatch[0].replace(head, "").split("-") : [];\r
-        },\r
-        disableSelection: function(element) {\r
-                element.onselectstart = function() {\r
-                        return false;\r
-                };\r
-                element.unselectable = "on";\r
-                element.style.MozUserSelect = "none";\r
-        },\r
-        removeTableCache: function(tableId) {\r
-                if(!(tableId in fdTableSort.tableCache)) return;\r
-\r
-                fdTableSort.tableCache[tableId] = null;\r
-                delete fdTableSort.tableCache[tableId];\r
-\r
-                var tbl = document.getElementById(tableId);\r
-                if(!tbl) return;\r
-                var ths = tbl.getElementsByTagName("th");\r
-                var a;\r
-                for(var i = 0, th; th = ths[i]; i++) {\r
-                        a = th.getElementsByTagName("a");\r
-                        if(a.length) a[0].onkeydown = a[0].onclick = null;\r
-                        th.onclick = th.onselectstart = th = a = null;\r
-                };\r
-        },\r
-        removeTmpCache: function(tableId) {\r
-                if(!(tableId in fdTableSort.tmpCache)) return;\r
-                var headers = fdTableSort.tmpCache[tableId].headers;\r
-                var a;\r
-                for(var i = 0, row; row = headers[i]; i++) {\r
-                        for(var j = 0, th; th = row[j]; j++) {\r
-                                a = th.getElementsByTagName("a");\r
-                                if(a.length) a[0].onkeydown = a[0].onclick = null;\r
-                                th.onclick = th.onselectstart = th = a = null;\r
-                        };\r
-                };\r
-                fdTableSort.tmpCache[tableId] = null;\r
-                delete fdTableSort.tmpCache[tableId];\r
-        },\r
-        initEvt: function(e) {\r
-                fdTableSort.init(false);\r
-        },\r
-        init: function(tableId) {\r
-                if (!document.getElementsByTagName || !document.createElement || !document.getElementById) return;\r
-\r
-                var tables = tableId && document.getElementById(tableId) ? [document.getElementById(tableId)] : document.getElementsByTagName("table");\r
-                var c, ii, len, colMatch, showOnly, match, showArrow, columnNumSortObj, obj, workArr, headers, thtext, aclone, multi, colCnt, cel, allRowArr, rowArr, sortableTable, celCount, colspan, rowspan, rowLength;\r
-\r
-                var a          = document.createElement("a");\r
-                a.href         = "#";\r
-                a.className    = "fdTableSortTrigger";\r
-\r
-                var span       = document.createElement("span");\r
-\r
-                for(var k = 0, tbl; tbl = tables[k]; k++) {\r
-\r
-                        if(tbl.id) {\r
-                                fdTableSort.removeTableCache(tbl.id);\r
-                                fdTableSort.removeTmpCache(tbl.id);\r
-                        };\r
-\r
-                        allRowArr     = tbl.getElementsByTagName('thead').length ? tbl.getElementsByTagName('thead')[0].getElementsByTagName('tr') : tbl.getElementsByTagName('tr');\r
-                        rowArr        = [];\r
-                        sortableTable = false;\r
-\r
-                        for(var i = 0, tr; tr = allRowArr[i]; i++) {\r
-                                if(tr.getElementsByTagName('td').length || !tr.getElementsByTagName('th').length) { continue; };\r
-                                rowArr[rowArr.length] = tr.getElementsByTagName('th');\r
-                                for(var j = 0, th; th = rowArr[rowArr.length - 1][j]; j++) {\r
-                                        if(th.className.search(/sortable/) != -1) { sortableTable = true; };\r
-                                };\r
-                        };\r
-\r
-                        if(!sortableTable) continue;\r
-\r
-                        if(!tbl.id) { tbl.id = "fd-table-" + fdTableSort.uniqueHash++; };\r
-\r
-                        showArrow   = tbl.className.search("no-arrow") == -1;\r
-                        showOnly    = tbl.className.search("sortable-onload-show") != -1;\r
-\r
-                        columnNumSortObj = {};\r
-                        colMatch         = fdTableSort.parseClassName(showOnly ? "sortable-onload-show" : "sortable-onload", tbl);\r
-                        for(match = 1; match < colMatch.length; match++) {\r
-                                columnNumSortObj[parseInt(colMatch[match], 10)] = { "reverse":colMatch[match].search("r") != -1 };\r
-                        };\r
-\r
-                        rowLength = rowArr[0].length;\r
-\r
-                        for(c = 0;c < rowArr[0].length;c++){\r
-                                if(rowArr[0][c].getAttribute(fdTableSort.colspan) && rowArr[0][c].getAttribute(fdTableSort.colspan) > 1){\r
-                                        rowLength = rowLength + (rowArr[0][c].getAttribute(fdTableSort.colspan) - 1);\r
-                                };\r
-                        };\r
-\r
-                        workArr = new Array(rowArr.length);\r
-                        for(c = rowArr.length;c--;){ workArr[c]= new Array(rowLength); };\r
-\r
-                        for(c = 0;c < workArr.length;c++){\r
-                                celCount = 0;\r
-                                for(i = 0;i < rowLength;i++){\r
-                                        if(!workArr[c][i]){\r
-                                                cel = rowArr[c][celCount];\r
-                                                colspan = (cel.getAttribute(fdTableSort.colspan) > 1) ? cel.getAttribute(fdTableSort.colspan):1;\r
-                                                rowspan = (cel.getAttribute(fdTableSort.rowspan) > 1) ? cel.getAttribute(fdTableSort.rowspan):1;\r
-                                                for(var t = 0;((t < colspan)&&((i+t) < rowLength));t++){\r
-                                                        for(var n = 0;((n < rowspan)&&((c+n) < workArr.length));n++) {\r
-                                                                workArr[(c+n)][(i+t)] = cel;\r
-                                                        };\r
-                                                };\r
-                                                if(++celCount == rowArr[c].length) break;\r
-                                        };\r
-                                };\r
-                        };\r
-\r
-                        for(c = 0;c < workArr.length;c++) {\r
-                                for(i = 0;i < workArr[c].length;i++){\r
-\r
-                                        if(workArr[c][i].className.search("fd-column-") == -1 && workArr[c][i].className.search("sortable") != -1) workArr[c][i].className = workArr[c][i].className + " fd-column-" + i;\r
-\r
-                                        if(workArr[c][i].className.match('sortable')) {\r
-                                                workArr[c][i].className = workArr[c][i].className.replace(/forwardSort|reverseSort/, "");\r
-\r
-                                                if(i in columnNumSortObj) {\r
-                                                        columnNumSortObj[i]["thNode"] = workArr[c][i];\r
-                                                        columnNumSortObj["active"] = true;\r
-                                                };\r
-\r
-                                                thtext = fdTableSort.getInnerText(workArr[c][i], true);\r
-                                                \r
-                                                for(var cn = workArr[c][i].childNodes.length; cn--;) {\r
-                                                        // Skip image nodes and links created by the filter script.\r
-                                                        if(workArr[c][i].childNodes[cn].nodeType == 1 && (workArr[c][i].childNodes[cn].className == "fdFilterTrigger" || /img/i.test(workArr[c][i].childNodes[cn].nodeName))) {\r
-                                                                continue;\r
-                                                        };\r
-                                                        if(workArr[c][i].childNodes[cn].nodeType == 1 && /^a$/i.test(workArr[c][i].childNodes[cn].nodeName)) {\r
-                                                                workArr[c][i].childNodes[cn].onclick = workArr[c][i].childNodes[cn].onkeydown = null;\r
-                                                        };\r
-                                                        workArr[c][i].removeChild(workArr[c][i].childNodes[cn]);\r
-                                                };\r
-\r
-                                                aclone = a.cloneNode(true);\r
-                                                //aclone.appendChild(document.createTextNode(thtext));\r
-                                                aclone.innerHTML = thtext;\r
-                                                aclone.title = "Sort on \u201c" + thtext.replace('<br />', '') + "\u201d";\r
-                                                aclone.onclick = aclone.onkeydown = workArr[c][i].onclick = fdTableSort.initWrapper;\r
-                                                workArr[c][i].appendChild(aclone);\r
-                                                if(showArrow) workArr[c][i].appendChild(span.cloneNode(false));\r
-                                                workArr[c][i].className = workArr[c][i].className.replace(/fd-identical|fd-not-identical/, "");\r
-                                                fdTableSort.disableSelection(workArr[c][i]);\r
-                                                aclone = null;\r
-                                        };\r
-                                };\r
-                        };\r
-\r
-                        fdTableSort.tmpCache[tbl.id] = {cols:rowLength, headers:workArr};\r
-\r
-                        workArr = null;\r
-                        multi   = 0;\r
-\r
-                        if("active" in columnNumSortObj) {\r
-                                fdTableSort.tableId = tbl.id;\r
-                                fdTableSort.prepareTableData(document.getElementById(fdTableSort.tableId));\r
-\r
-                                delete columnNumSortObj["active"];\r
-\r
-                                for(col in columnNumSortObj) {\r
-                                        obj = columnNumSortObj[col];\r
-                                        if(!("thNode" in obj)) { continue; };\r
-                                        fdTableSort.multi = true;\r
-\r
-                                        len = obj.reverse ? 2 : 1;\r
-\r
-                                        for(ii = 0; ii < len; ii++) {\r
-                                                fdTableSort.thNode = obj.thNode;\r
-                                                if(!showOnly) {\r
-                                                        fdTableSort.initSort(false, true);\r
-                                                } else {\r
-                                                        fdTableSort.addThNode();\r
-                                                };\r
-                                        };\r
-\r
-                                        if(showOnly) {\r
-                                                fdTableSort.removeClass(obj.thNode, "(forwardSort|reverseSort)");\r
-                                                fdTableSort.addClass(obj.thNode, obj.reverse ? "reverseSort" : "forwardSort");\r
-                                                if(showArrow) {\r
-                                                        span = fdTableSort.thNode.getElementsByTagName('span')[0];\r
-                                                        if(span.firstChild) { span.removeChild(span.firstChild); };\r
-                                                        span.appendChild(document.createTextNode(len == 1 ? " \u2193" : " \u2191"));\r
-                                                };\r
-                                        };\r
-                                };\r
-                                if(showOnly && (fdTableSort.tableCache[tbl.id].colStyle || fdTableSort.tableCache[tbl.id].rowStyle)) {\r
-                                        fdTableSort.redraw(tbl.id, false);\r
-                                };\r
-                        } else if(tbl.className.search(/onload-zebra/) != -1) {\r
-                                fdTableSort.tableId = tbl.id;\r
-                                fdTableSort.prepareTableData(tbl);\r
-                                if(fdTableSort.tableCache[tbl.id].rowStyle) { fdTableSort.redraw(tbl.id, false); };\r
-                        };\r
-                };\r
-\r
-                fdTableSort.thNode = aclone = a = span = columnNumSortObj = thNode = tbl = allRowArr = rowArr = null;\r
-        },\r
-        initWrapper: function(e) {\r
-                e = e || window.event;\r
-                var kc = e.type == "keydown" ? e.keyCode != null ? e.keyCode : e.charCode : -1;\r
-                if(fdTableSort.thNode == null && (e.type == "click" || kc == 13)) {\r
-                        var targ = this;\r
-                        while(targ.tagName.toLowerCase() != "th") { targ = targ.parentNode; };\r
-                        fdTableSort.thNode = targ;\r
-                        while(targ.tagName.toLowerCase() != "table") { targ = targ.parentNode; };\r
-                        fdTableSort.tableId = targ.id;\r
-                        fdTableSort.multi = e.shiftKey;\r
-                        fdTableSort.addSortActiveClass();\r
-                        setTimeout(fdTableSort.initSort,5,false);\r
-                        return fdTableSort.stopEvent(e);\r
-                };\r
-                return kc != -1 ? true : fdTableSort.stopEvent(e);\r
-        },\r
-        jsWrapper: function(tableid, colNums) {\r
-                if(!(tableid in fdTableSort.tmpCache)) { return false; };\r
-                if(!(tableid in fdTableSort.tableCache)) { fdTableSort.prepareTableData(document.getElementById(tableid)); };\r
-                if(!(colNums instanceof Array)) { colNums = [colNums]; };\r
-\r
-                fdTableSort.tableId = tableid;\r
-                var len = colNums.length, colNum;\r
-\r
-                if(fdTableSort.tableCache[tableid].thList.length == colNums.length) {\r
-                        var identical = true;\r
-                        var th;\r
-                        for(var i = 0; i < len; i++) {\r
-                                colNum = colNums[i];\r
-                                th = fdTableSort.tmpCache[tableid].headers[0][colNum];\r
-                                if(th != fdTableSort.tableCache[tableid].thList[i]) {\r
-                                        identical = false;\r
-                                        break;\r
-                                };\r
-                        };\r
-                        if(identical) {\r
-                                fdTableSort.thNode = th;\r
-                                fdTableSort.initSort(true);\r
-                                return;\r
-                        };\r
-                };\r
-\r
-                fdTableSort.addSortActiveClass();\r
-\r
-                for(var i = 0; i < len; i++) {\r
-                        fdTableSort.multi = i;\r
-                        colNum = colNums[i];\r
-                        fdTableSort.thNode = fdTableSort.tmpCache[tableid].headers[0][colNum];\r
-                        fdTableSort.initSort(true);\r
-                };\r
-        },\r
-        addSortActiveClass: function() {\r
-                if(fdTableSort.thNode == null) { return; };\r
-                fdTableSort.addClass(fdTableSort.thNode, fdTableSort.sortActiveClass);\r
-                fdTableSort.addClass(document.getElementsByTagName('body')[0], fdTableSort.sortActiveClass);\r
-        },\r
-        removeSortActiveClass: function() {\r
-                if(fdTableSort.thNode == null) return;\r
-                fdTableSort.removeClass(fdTableSort.thNode, fdTableSort.sortActiveClass);\r
-                fdTableSort.removeClass(document.getElementsByTagName('body')[0], fdTableSort.sortActiveClass);\r
-        },\r
-        doCallback: function(init) {\r
-                if(!fdTableSort.tableId || !(fdTableSort.tableId in fdTableSort.tableCache)) { return; };\r
-                fdTableSort.callback(fdTableSort.tableId, init ? fdTableSort.tableCache[fdTableSort.tableId].initiatedCallback : fdTableSort.tableCache[fdTableSort.tableId].completeCallback);\r
-        },\r
-        addClass: function(e,c) {\r
-                if(new RegExp("(^|\\s)" + c + "(\\s|$)").test(e.className)) { return; };\r
-                e.className += ( e.className ? " " : "" ) + c;\r
-        },\r
-        /*@cc_on\r
-        /*@if (@_win32)\r
-        removeClass: function(e,c) {\r
-                e.className = !c ? "" : e.className.replace(new RegExp("(^|\\s)" + c + "(\\s|$)"), " ").replace(/^\s*((?:[\S\s]*\S)?)\s*$/, '$1');\r
-        },\r
-        @else @*/\r
-        removeClass: function(e,c) {\r
-                e.className = !c ? "" : e.className.replace(new RegExp("(^|\\s)" + c + "(\\s|$)"), " ").replace(/^\s\s*/, '').replace(/\s\s*$/, '');\r
-        },\r
-        /*@end\r
-        @*/\r
-        callback: function(tblId, cb) {\r
-                var func, parts;\r
-                try {\r
-                        if(cb.indexOf(".") != -1) {                              \r
-                                parts = cb.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 if(cb + tblId in window) {\r
-                                func = window[cb + tblId];\r
-                        } else if(cb in window) {\r
-                                func = window[cb];\r
-                        } else {\r
-                                func = null;\r
-                        };\r
-                 } catch(err) {};\r
-                           \r
-                if(!(func instanceof Function)) return;\r
-                func(tblId, fdTableSort.tableCache[tblId].thList);                               \r
-        },\r
-        prepareTableData: function(table) {\r
-                var data = [];\r
-\r
-                var start = table.getElementsByTagName('tbody');\r
-                start = start.length ? start[0] : table;\r
-\r
-                var trs = start.rows;\r
-                var ths = table.getElementsByTagName('th');\r
-\r
-                var numberOfRows = trs.length;\r
-                var numberOfCols = fdTableSort.tmpCache[table.id].cols;\r
-\r
-                var data = [];\r
-                var identical = new Array(numberOfCols);\r
-                var identVal  = new Array(numberOfCols);\r
-\r
-                for(var tmp = 0; tmp < numberOfCols; tmp++) identical[tmp] = true;\r
-\r
-                var tr, td, th, txt, tds, col, row;\r
-\r
-                var re = new RegExp(/fd-column-([0-9]+)/);\r
-                var rowCnt = 0;\r
-\r
-                var sortableColumnNumbers = [];\r
-\r
-                for(var tmp = 0, th; th = ths[tmp]; tmp++) {\r
-                        if(th.className.search(re) == -1) continue;\r
-                        sortableColumnNumbers[sortableColumnNumbers.length] = th;\r
-                };\r
-\r
-                for(row = 0; row < numberOfRows; row++) {\r
-\r
-                        tr              = trs[row];\r
-                        if(tr.parentNode != start || tr.getElementsByTagName("th").length || (tr.parentNode && tr.parentNode.tagName.toLowerCase().search(/thead|tfoot/) != -1)) continue;\r
-                        data[rowCnt]    = [];\r
-                        tds             = tr.cells;\r
-\r
-                        for(var tmp = 0, th; th = sortableColumnNumbers[tmp]; tmp++) {\r
-                                col = th.className.match(re)[1];\r
-\r
-                                td  = tds[col];\r
-                                txt = fdTableSort.getInnerText(td) + " ";\r
-                                txt = txt.replace(/^\s+/,'').replace(/\s+$/,'');\r
-\r
-                                if(th.className.search(/sortable-date/) != -1) {\r
-                                        txt = fdTableSort.dateFormat(txt, th.className.search(/sortable-date-dmy/) != -1);\r
-                                } else if(th.className.search(/sortable-numeric|sortable-currency/) != -1) {\r
-                                        txt = parseFloat(txt.replace(/[^0-9\.\-]/g,''));\r
-                                        if(isNaN(txt)) txt = "";\r
-                                } else if(th.className.search(/sortable-text/) != -1) {\r
-                                        txt = txt.toLowerCase();\r
-                                } else if (th.className.search(/sortable-keep/) != -1) {\r
-                                        txt = rowCnt;\r
-                                } else if(th.className.search(/sortable-([a-zA-Z\_]+)/) != -1) {\r
-                                        if((th.className.match(/sortable-([a-zA-Z\_]+)/)[1] + "PrepareData") in window) {\r
-                                                txt = window[th.className.match(/sortable-([a-zA-Z\_]+)/)[1] + "PrepareData"](td, txt);\r
-                                        };\r
-                                } else if(txt != "") {\r
-                                        fdTableSort.removeClass(th, "sortable");\r
-                                        if(fdTableSort.dateFormat(txt) != 0) {\r
-                                                fdTableSort.addClass(th, "sortable-date");\r
-                                                txt = fdTableSort.dateFormat(txt);\r
-                                        } else if(txt.search(fdTableSort.regExp_Number) != -1 || txt.search(fdTableSort.regExp_Currency) != -1) {\r
-                                                fdTableSort.addClass(th, "sortable-numeric");\r
-                                                txt = parseFloat(txt.replace(/[^0-9\.\-]/g,''));\r
-                                                if(isNaN(txt)) txt = "";\r
-                                        } else {\r
-                                                fdTableSort.addClass(th, "sortable-text");\r
-                                                txt = txt.toLowerCase();\r
-                                        };\r
-                                };\r
-\r
-                                if(rowCnt > 0 && identical[col] && identVal[col] != txt) { identical[col] = false; };\r
-\r
-                                identVal[col]     = txt;\r
-                                data[rowCnt][col] = txt;\r
-                        };\r
-                        data[rowCnt][numberOfCols] = tr;\r
-                        rowCnt++;\r
-                };\r
-\r
-                var colStyle = table.className.search(/colstyle-([\S]+)/) != -1 ? table.className.match(/colstyle-([\S]+)/)[1] : false;\r
-                var rowStyle = table.className.search(/rowstyle-([\S]+)/) != -1 ? table.className.match(/rowstyle-([\S]+)/)[1] : false;\r
-                var iCBack   = table.className.search(/sortinitiatedcallback-([\S-]+)/) == -1 ? "sortInitiatedCallback" : table.className.match(/sortinitiatedcallback-([\S]+)/)[1];\r
-                var cCBack   = table.className.search(/sortcompletecallback-([\S-]+)/) == -1 ? "sortCompleteCallback" : table.className.match(/sortcompletecallback-([\S]+)/)[1];\r
-                iCBack = iCBack.replace("-", ".");\r
-                cCBack = cCBack.replace("-", ".");\r
-                fdTableSort.tableCache[table.id] = { hook:start, initiatedCallback:iCBack, completeCallback:cCBack, thList:[], colOrder:{}, data:data, identical:identical, colStyle:colStyle, rowStyle:rowStyle, noArrow:table.className.search(/no-arrow/) != -1 };\r
-                sortableColumnNumbers = data = tr = td = th = trs = identical = identVal = null;\r
-        },\r
-        onUnload: function() {\r
-                for(tbl in fdTableSort.tableCache) { fdTableSort.removeTableCache(tbl); };\r
-                for(tbl in fdTableSort.tmpCache) { fdTableSort.removeTmpCache(tbl); };\r
-                fdTableSort.removeEvent(window, "load", fdTableSort.initEvt);\r
-                fdTableSort.removeEvent(window, "unload", fdTableSort.onUnload);\r
-                fdTableSort.tmpCache = fdTableSort.tableCache = null;\r
-        },\r
-        addThNode: function() {\r
-                var dataObj = fdTableSort.tableCache[fdTableSort.tableId];\r
-                var pos     = fdTableSort.thNode.className.match(/fd-column-([0-9]+)/)[1];\r
-                var alt     = false;\r
-\r
-                if(!fdTableSort.multi) {\r
-                        if(dataObj.colStyle) {\r
-                                var len = dataObj.thList.length;\r
-                                for(var i = 0; i < len; i++) {\r
-                                        dataObj.colOrder[dataObj.thList[i].className.match(/fd-column-([0-9]+)/)[1]] = false;\r
-                                };\r
-                        };\r
-                        if(dataObj.thList.length && dataObj.thList[0] == fdTableSort.thNode) alt = true;\r
-                        dataObj.thList = [];\r
-                };\r
-\r
-                var found = false;\r
-                var l = dataObj.thList.length;\r
-\r
-                for(var i = 0, n; n = dataObj.thList[i]; i++) {\r
-                        if(n == fdTableSort.thNode) {\r
-                                found = true;\r
-                                break;\r
-                        };\r
-                };\r
-\r
-                if(!found) {\r
-                        dataObj.thList.push(fdTableSort.thNode);\r
-                        if(dataObj.colStyle) { dataObj.colOrder[pos] = true; };\r
-                };\r
-\r
-                var ths = document.getElementById(fdTableSort.tableId).getElementsByTagName("th");\r
-                for(var i = 0, th; th = ths[i]; i++) {\r
-                        found = false;\r
-                        for(var z = 0, n; n = dataObj.thList[z]; z++) {\r
-                                if(n == th) {\r
-                                        found = true;\r
-                                        break;\r
-                                };\r
-                        };\r
-                        if(!found) {\r
-                                fdTableSort.removeClass(th, "(forwardSort|reverseSort)");\r
-                                if(!dataObj.noArrow) {\r
-                                        span = th.getElementsByTagName('span');\r
-                                        if(span.length) {\r
-                                                span = span[0];\r
-                                                while(span.firstChild) span.removeChild(span.firstChild);\r
-                                        };\r
-                                };\r
-                        };\r
-                };\r
-\r
-                if(dataObj.thList.length > 1) {\r
-                        classToAdd = fdTableSort.thNode.className.search(/forwardSort/) != -1 ? "reverseSort" : "forwardSort";\r
-                        fdTableSort.removeClass(fdTableSort.thNode, "(forwardSort|reverseSort)");\r
-                        fdTableSort.addClass(fdTableSort.thNode, classToAdd);\r
-                        dataObj.pos = -1\r
-                } else if(alt) { dataObj.pos = fdTableSort.thNode };\r
-        },\r
-        initSort: function(noCallback, ident) {\r
-                var thNode      = fdTableSort.thNode;\r
-                var tableElem   = document.getElementById(fdTableSort.tableId);\r
-\r
-                if(!(fdTableSort.tableId in fdTableSort.tableCache)) { fdTableSort.prepareTableData(document.getElementById(fdTableSort.tableId)); };\r
-\r
-                fdTableSort.addThNode();\r
-\r
-                if(!noCallback) { fdTableSort.doCallback(true); };\r
-\r
-                fdTableSort.pos = thNode.className.match(/fd-column-([0-9]+)/)[1];\r
-                var dataObj     = fdTableSort.tableCache[tableElem.id];\r
-                var lastPos     = dataObj.pos && dataObj.pos.className ? dataObj.pos.className.match(/fd-column-([0-9]+)/)[1] : -1;\r
-                var len1        = dataObj.data.length;\r
-                var len2        = dataObj.data.length > 0 ? dataObj.data[0].length - 1 : 0;\r
-                var identical   = dataObj.identical[fdTableSort.pos];\r
-                var classToAdd  = "forwardSort";\r
-\r
-                if(dataObj.thList.length > 1) {\r
-                        var js  = "var sortWrapper = function(a,b) {\n";\r
-                        var l   = dataObj.thList.length;\r
-                        var cnt = 0;\r
-                        var e,d,th,p,f;\r
-\r
-                        for(var i=0; i < l; i++) {\r
-                                th = dataObj.thList[i];\r
-                                p  = th.className.match(/fd-column-([0-9]+)/)[1];\r
-                                if(dataObj.identical[p]) { continue; };\r
-                                cnt++;\r
-\r
-                                if(th.className.match(/sortable-(numeric|currency|date|keep)/)) {\r
-                                        f = "fdTableSort.sortNumeric";\r
-                                } else if(th.className.match('sortable-text')) {\r
-                                        f = "fdTableSort.sortText";\r
-                                } else if(th.className.search(/sortable-([a-zA-Z\_]+)/) != -1 && th.className.match(/sortable-([a-zA-Z\_]+)/)[1] in window) {\r
-                                        f = "window['" + th.className.match(/sortable-([a-zA-Z\_]+)/)[1] + "']";\r
-                                } else  f = "fdTableSort.sortText";\r
-\r
-                                e = "e" + i;\r
-                                d = th.className.search('forwardSort') != -1 ? "a,b" : "b,a";\r
-                                js += "fdTableSort.pos   = " + p + ";\n";\r
-                                js += "var " + e + " = "+f+"(" + d +");\n";\r
-                                js += "if(" + e + ") return " + e + ";\n";\r
-                                js += "else { \n";\r
-                        };\r
-\r
-                        js += "return 0;\n";\r
-\r
-                        for(var i=0; i < cnt; i++) {\r
-                                js += "};\n";\r
-                        };\r
-\r
-                        if(cnt) js += "return 0;\n";\r
-                        js += "};\n";\r
-\r
-                        eval(js);\r
-                        dataObj.data.sort(sortWrapper);\r
-                        identical = false;\r
-                } else if((lastPos == fdTableSort.pos && !identical) || (thNode.className.search(/sortable-keep/) != -1 && lastPos == -1)) {\r
-                        dataObj.data.reverse();\r
-                        classToAdd = thNode.className.search(/reverseSort/) != -1 ? "forwardSort" : "reverseSort";\r
-                        if(thNode.className.search(/sortable-keep/) != -1 && lastPos == -1) fdTableSort.tableCache[tableElem.id].pos = thNode;\r
-                } else {\r
-                        fdTableSort.tableCache[tableElem.id].pos = thNode;\r
-                        classToAdd = thNode.className.search(/forwardSort/) != -1 ? "reverseSort" : "forwardSort";\r
-                        if(!identical) {\r
-                                if(thNode.className.match(/sortable-(numeric|currency|date|keep)/)) {\r
-                                        dataObj.data.sort(fdTableSort.sortNumeric);\r
-                                } else if(thNode.className.match('sortable-text')) {\r
-                                        dataObj.data.sort(fdTableSort.sortText);\r
-                                } else if(thNode.className.search(/sortable-([a-zA-Z\_]+)/) != -1 && thNode.className.match(/sortable-([a-zA-Z\_]+)/)[1] in window) {\r
-                                        dataObj.data.sort(window[thNode.className.match(/sortable-([a-zA-Z\_]+)/)[1]]);\r
-                                };\r
-\r
-                                if(thNode.className.search(/(^|\s)favour-reverse($|\s)/) != -1) {\r
-                                        classToAdd = classToAdd == "forwardSort" ? "reverseSort" : "forwardSort";\r
-                                        dataObj.data.reverse();\r
-                                };\r
-                        };\r
-                };\r
-                if(ident) { identical = false; };\r
-                if(dataObj.thList.length == 1) {\r
-                        fdTableSort.removeClass(thNode, "(forwardSort|reverseSort)");\r
-                        fdTableSort.addClass(thNode, classToAdd);\r
-                };\r
-                if(!dataObj.noArrow) {\r
-                        var span = fdTableSort.thNode.getElementsByTagName('span')[0];\r
-                        if(span.firstChild) span.removeChild(span.firstChild);\r
-                        span.appendChild(document.createTextNode(fdTableSort.thNode.className.search(/forwardSort/) != -1 ? " \u2193" : " \u2191"));\r
-                };\r
-                if(!dataObj.rowStyle && !dataObj.colStyle && identical) {\r
-                        fdTableSort.removeSortActiveClass();\r
-                        if(!noCallback) { fdTableSort.doCallback(false); };\r
-                        fdTableSort.thNode = null;\r
-                        return;\r
-                };\r
-                if("tablePaginater" in window && tablePaginater.tableIsPaginated(fdTableSort.tableId)) {\r
-                        tablePaginater.redraw(fdTableSort.tableId, identical);\r
-                } else {\r
-                        fdTableSort.redraw(fdTableSort.tableId, identical);\r
-                };\r
-                fdTableSort.removeSortActiveClass();\r
-                if(!noCallback) { fdTableSort.doCallback(false); };\r
-                fdTableSort.thNode = null;\r
-        },\r
-        redraw: function(tableid, identical) {\r
-                if(!tableid || !(tableid in fdTableSort.tableCache)) { return; };\r
-                var dataObj     = fdTableSort.tableCache[tableid];\r
-                var data        = dataObj.data;\r
-                var len1        = data.length;\r
-                var len2        = len1 ? data[0].length - 1 : 0;\r
-                var hook        = dataObj.hook;\r
-                var colStyle    = dataObj.colStyle;\r
-                var rowStyle    = dataObj.rowStyle;\r
-                var colOrder    = dataObj.colOrder;\r
-                var highLight   = 0;\r
-                var reg         = /(^|\s)invisibleRow(\s|$)/;\r
-                var tr, tds;\r
-\r
-                for(var i = 0; i < len1; i++) {\r
-                        tr = data[i][len2];\r
-                        if(colStyle) {\r
-                                tds = tr.cells;\r
-                                for(thPos in colOrder) {\r
-                                        if(!colOrder[thPos]) fdTableSort.removeClass(tds[thPos], colStyle);\r
-                                        else fdTableSort.addClass(tds[thPos], colStyle);\r
-                                };\r
-                        };\r
-                        if(!identical) {\r
-                                if(rowStyle && tr.className.search(reg) == -1) {\r
-                                        if(highLight++ & 1) fdTableSort.addClass(tr, rowStyle);\r
-                                        else fdTableSort.removeClass(tr, rowStyle);\r
-                                };\r
-\r
-                                // Netscape 8.1.2 requires the removeChild call or it freaks out, so add the line if you want to support this browser\r
-                                // hook.removeChild(tr);\r
-                                hook.appendChild(tr);\r
-                        };\r
-                };\r
-                tr = tds = hook = null;\r
-        },\r
-        getInnerText: function(el, allowBrTags) {\r
-                if (typeof el == "string" || typeof el == "undefined") return el;\r
-                if(el.innerText) return el.innerText;\r
-                var txt = '', i;\r
-                for(i = el.firstChild; i; i = i.nextSibling) {\r
-                        if(allowBrTags && i.nodeName && i.nodeName == "BR") txt += "<br />";\r
-                        else if(i.nodeType == 3)       txt += i.nodeValue;\r
-                        else if(i.nodeType == 1)       txt += fdTableSort.getInnerText(i);\r
-                };\r
-                return txt;\r
-        },\r
-        dateFormat: function(dateIn, favourDMY) {\r
-                var dateTest = [\r
-                        { regExp:/^(0?[1-9]|1[012])([- \/.])(0?[1-9]|[12][0-9]|3[01])([- \/.])((\d\d)?\d\d)$/, d:3, m:1, y:5 },  // mdy\r
-                        { regExp:/^(0?[1-9]|[12][0-9]|3[01])([- \/.])(0?[1-9]|1[012])([- \/.])((\d\d)?\d\d)$/, d:1, m:3, y:5 },  // dmy\r
-                        { regExp:/^(\d\d\d\d)([- \/.])(0?[1-9]|1[012])([- \/.])(0?[1-9]|[12][0-9]|3[01])$/, d:5, m:3, y:1 }      // ymd\r
-                        ];\r
-                var start, cnt = 0, numFormats = dateTest.length;\r
-                while(cnt < numFormats) {\r
-                        start = (cnt + (favourDMY ? numFormats + 1 : numFormats)) % numFormats;\r
-                        if(dateIn.match(dateTest[start].regExp)) {\r
-                                res = dateIn.match(dateTest[start].regExp);\r
-                                y = res[dateTest[start].y];\r
-                                m = res[dateTest[start].m];\r
-                                d = res[dateTest[start].d];\r
-                                if(m.length == 1) m = "0" + String(m);\r
-                                if(d.length == 1) d = "0" + String(d);\r
-                                if(y.length != 4) y = (parseInt(y) < 50) ? "20" + String(y) : "19" + String(y);\r
-\r
-                                return y+String(m)+d;\r
-                        };\r
-                        cnt++;\r
-                };\r
-                return 0;\r
-        },\r
-        sortNumeric:function(a,b) {\r
-                var aa = a[fdTableSort.pos];\r
-                var bb = b[fdTableSort.pos];\r
-                if(aa == bb) return 0;\r
-                if(aa === "" && !isNaN(bb)) return -1;\r
-                if(bb === "" && !isNaN(aa)) return 1;\r
-                return aa - bb;\r
-        },\r
-        sortText:function(a,b) {\r
-                var aa = a[fdTableSort.pos];\r
-                var bb = b[fdTableSort.pos];\r
-                if(aa == bb) return 0;\r
-                if(aa < bb)  return -1;\r
-                return 1;\r
-        }\r
-};\r
-})();\r
-fdTableSort.addEvent(window, "load",   fdTableSort.initEvt);\r
-fdTableSort.addEvent(window, "unload", fdTableSort.onUnload);\r
+/*
+        TableSort revisited v5.0 by frequency-decoder.com
+
+        Released under a creative commons Attribution-ShareAlike 2.5 license (http://creativecommons.org/licenses/by-sa/2.5/)
+
+        Please credit frequency decoder in any derivative work - thanks
+
+        You are free:
+
+        * to copy, distribute, display, and perform the work
+        * to make derivative works
+        * to make commercial use of the work
+
+        Under the following conditions:
+
+                by Attribution.
+                --------------
+                You must attribute the work in the manner specified by the author or licensor.
+
+                sa
+                --
+                Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license identical to this one.
+
+        * For any reuse or distribution, you must make clear to others the license terms of this work.
+        * Any of these conditions can be waived if you get permission from the copyright holder.
+*/
+
+(function() {
+fdTableSort = {
+        regExp_Currency:        /^[£$€¥¤]/,
+        regExp_Number:          /^(\-)?[0-9]+(\.[0-9]*)?$/,
+        pos:                    -1,
+        uniqueHash:             1,
+        thNode:                 null,
+        tableId:                null,
+        tableCache:             {},
+        tmpCache:               {},
+        sortActiveClass:        "sort-active",
+        /*@cc_on
+        /*@if (@_win32)
+        colspan:                "colSpan",
+        rowspan:                "rowSpan",
+        @else @*/
+        colspan:                "colspan",
+        rowspan:                "rowspan",
+        /*@end
+        @*/
+        
+        addEvent: function(obj, type, fn, tmp) {
+                tmp || (tmp = true);
+                if( obj.attachEvent ) {
+                        obj["e"+type+fn] = fn;
+                        obj[type+fn] = function(){obj["e"+type+fn]( window.event );};
+                        obj.attachEvent( "on"+type, obj[type+fn] );
+                } else {
+                        obj.addEventListener( type, fn, true );
+                };
+        },
+        removeEvent: function(obj, type, fn, tmp) {
+                tmp || (tmp = true);
+                try {
+                        if( obj.detachEvent ) {
+                                obj.detachEvent( "on"+type, obj[type+fn] );
+                                obj[type+fn] = null;
+                        } else {
+                                obj.removeEventListener( type, fn, true );
+                        };
+                } catch(err) {};
+        },
+        stopEvent: function(e) {
+                e = e || window.event;
+
+                if(e.stopPropagation) {
+                        e.stopPropagation();
+                        e.preventDefault();
+                };
+                
+                /*@cc_on@*/
+                /*@if(@_win32)
+                e.cancelBubble = true;
+                e.returnValue  = false;
+                /*@end@*/
+                return false;
+        },
+        parseClassName: function(head, tbl) {
+                var colMatch = tbl.className.match(new RegExp(head + "((-[\\d]+([r]){0,1})+)"));
+                return colMatch && colMatch.length ? colMatch[0].replace(head, "").split("-") : [];
+        },
+        disableSelection: function(element) {
+                element.onselectstart = function() {
+                        return false;
+                };
+                element.unselectable = "on";
+                element.style.MozUserSelect = "none";
+        },
+        removeTableCache: function(tableId) {
+                if(!(tableId in fdTableSort.tableCache)) return;
+
+                fdTableSort.tableCache[tableId] = null;
+                delete fdTableSort.tableCache[tableId];
+
+                var tbl = document.getElementById(tableId);
+                if(!tbl) return;
+                var ths = tbl.getElementsByTagName("th");
+                var a;
+                for(var i = 0, th; th = ths[i]; i++) {
+                        a = th.getElementsByTagName("a");
+                        if(a.length) a[0].onkeydown = a[0].onclick = null;
+                        th.onclick = th.onselectstart = th = a = null;
+                };
+        },
+        removeTmpCache: function(tableId) {
+                if(!(tableId in fdTableSort.tmpCache)) return;
+                var headers = fdTableSort.tmpCache[tableId].headers;
+                var a;
+                for(var i = 0, row; row = headers[i]; i++) {
+                        for(var j = 0, th; th = row[j]; j++) {
+                                a = th.getElementsByTagName("a");
+                                if(a.length) a[0].onkeydown = a[0].onclick = null;
+                                th.onclick = th.onselectstart = th = a = null;
+                        };
+                };
+                fdTableSort.tmpCache[tableId] = null;
+                delete fdTableSort.tmpCache[tableId];
+        },
+        initEvt: function(e) {
+                fdTableSort.init(false);
+        },
+        init: function(tableId) {
+                if (!document.getElementsByTagName || !document.createElement || !document.getElementById) return;
+
+                var tables = tableId && document.getElementById(tableId) ? [document.getElementById(tableId)] : document.getElementsByTagName("table");
+                var c, ii, len, colMatch, showOnly, match, showArrow, columnNumSortObj, obj, workArr, headers, thtext, aclone, multi, colCnt, cel, allRowArr, rowArr, sortableTable, celCount, colspan, rowspan, rowLength;
+
+                var a          = document.createElement("a");
+                a.href         = "#";
+                a.className    = "fdTableSortTrigger";
+
+                var span       = document.createElement("span");
+
+                for(var k = 0, tbl; tbl = tables[k]; k++) {
+
+                        if(tbl.id) {
+                                fdTableSort.removeTableCache(tbl.id);
+                                fdTableSort.removeTmpCache(tbl.id);
+                        };
+
+                        allRowArr     = tbl.getElementsByTagName('thead').length ? tbl.getElementsByTagName('thead')[0].getElementsByTagName('tr') : tbl.getElementsByTagName('tr');
+                        rowArr        = [];
+                        sortableTable = false;
+
+                        for(var i = 0, tr; tr = allRowArr[i]; i++) {
+                                if(tr.getElementsByTagName('td').length || !tr.getElementsByTagName('th').length) { continue; };
+                                rowArr[rowArr.length] = tr.getElementsByTagName('th');
+                                for(var j = 0, th; th = rowArr[rowArr.length - 1][j]; j++) {
+                                        if(th.className.search(/sortable/) != -1) { sortableTable = true; };
+                                };
+                        };
+
+                        if(!sortableTable) continue;
+
+                        if(!tbl.id) { tbl.id = "fd-table-" + fdTableSort.uniqueHash++; };
+
+                        showArrow   = tbl.className.search("no-arrow") == -1;
+                        showOnly    = tbl.className.search("sortable-onload-show") != -1;
+
+                        columnNumSortObj = {};
+                        colMatch         = fdTableSort.parseClassName(showOnly ? "sortable-onload-show" : "sortable-onload", tbl);
+                        for(match = 1; match < colMatch.length; match++) {
+                                columnNumSortObj[parseInt(colMatch[match], 10)] = { "reverse":colMatch[match].search("r") != -1 };
+                        };
+
+                        rowLength = rowArr[0].length;
+
+                        for(c = 0;c < rowArr[0].length;c++){
+                                if(rowArr[0][c].getAttribute(fdTableSort.colspan) && rowArr[0][c].getAttribute(fdTableSort.colspan) > 1){
+                                        rowLength = rowLength + (rowArr[0][c].getAttribute(fdTableSort.colspan) - 1);
+                                };
+                        };
+
+                        workArr = new Array(rowArr.length);
+                        for(c = rowArr.length;c--;){ workArr[c]= new Array(rowLength); };
+
+                        for(c = 0;c < workArr.length;c++){
+                                celCount = 0;
+                                for(i = 0;i < rowLength;i++){
+                                        if(!workArr[c][i]){
+                                                cel = rowArr[c][celCount];
+                                                colspan = (cel.getAttribute(fdTableSort.colspan) > 1) ? cel.getAttribute(fdTableSort.colspan):1;
+                                                rowspan = (cel.getAttribute(fdTableSort.rowspan) > 1) ? cel.getAttribute(fdTableSort.rowspan):1;
+                                                for(var t = 0;((t < colspan)&&((i+t) < rowLength));t++){
+                                                        for(var n = 0;((n < rowspan)&&((c+n) < workArr.length));n++) {
+                                                                workArr[(c+n)][(i+t)] = cel;
+                                                        };
+                                                };
+                                                if(++celCount == rowArr[c].length) break;
+                                        };
+                                };
+                        };
+
+                        for(c = 0;c < workArr.length;c++) {
+                                for(i = 0;i < workArr[c].length;i++){
+
+                                        if(workArr[c][i].className.search("fd-column-") == -1 && workArr[c][i].className.search("sortable") != -1) workArr[c][i].className = workArr[c][i].className + " fd-column-" + i;
+
+                                        if(workArr[c][i].className.match('sortable')) {
+                                                workArr[c][i].className = workArr[c][i].className.replace(/forwardSort|reverseSort/, "");
+
+                                                if(i in columnNumSortObj) {
+                                                        columnNumSortObj[i]["thNode"] = workArr[c][i];
+                                                        columnNumSortObj["active"] = true;
+                                                };
+
+                                                thtext = fdTableSort.getInnerText(workArr[c][i], true);
+                                                
+                                                for(var cn = workArr[c][i].childNodes.length; cn--;) {
+                                                        // Skip image nodes and links created by the filter script.
+                                                        if(workArr[c][i].childNodes[cn].nodeType == 1 && (workArr[c][i].childNodes[cn].className == "fdFilterTrigger" || /img/i.test(workArr[c][i].childNodes[cn].nodeName))) {
+                                                                continue;
+                                                        };
+                                                        if(workArr[c][i].childNodes[cn].nodeType == 1 && /^a$/i.test(workArr[c][i].childNodes[cn].nodeName)) {
+                                                                workArr[c][i].childNodes[cn].onclick = workArr[c][i].childNodes[cn].onkeydown = null;
+                                                        };
+                                                        workArr[c][i].removeChild(workArr[c][i].childNodes[cn]);
+                                                };
+
+                                                aclone = a.cloneNode(true);
+                                                //aclone.appendChild(document.createTextNode(thtext));
+                                                aclone.innerHTML = thtext;
+                                                aclone.title = "Sort on \u201c" + thtext.replace('<br />', '') + "\u201d";
+                                                aclone.onclick = aclone.onkeydown = workArr[c][i].onclick = fdTableSort.initWrapper;
+                                                workArr[c][i].appendChild(aclone);
+                                                if(showArrow) workArr[c][i].appendChild(span.cloneNode(false));
+                                                workArr[c][i].className = workArr[c][i].className.replace(/fd-identical|fd-not-identical/, "");
+                                                fdTableSort.disableSelection(workArr[c][i]);
+                                                aclone = null;
+                                        };
+                                };
+                        };
+
+                        fdTableSort.tmpCache[tbl.id] = {cols:rowLength, headers:workArr};
+
+                        workArr = null;
+                        multi   = 0;
+
+                        if("active" in columnNumSortObj) {
+                                fdTableSort.tableId = tbl.id;
+                                fdTableSort.prepareTableData(document.getElementById(fdTableSort.tableId));
+
+                                delete columnNumSortObj["active"];
+
+                                for(col in columnNumSortObj) {
+                                        obj = columnNumSortObj[col];
+                                        if(!("thNode" in obj)) { continue; };
+                                        fdTableSort.multi = true;
+
+                                        len = obj.reverse ? 2 : 1;
+
+                                        for(ii = 0; ii < len; ii++) {
+                                                fdTableSort.thNode = obj.thNode;
+                                                if(!showOnly) {
+                                                        fdTableSort.initSort(false, true);
+                                                } else {
+                                                        fdTableSort.addThNode();
+                                                };
+                                        };
+
+                                        if(showOnly) {
+                                                fdTableSort.removeClass(obj.thNode, "(forwardSort|reverseSort)");
+                                                fdTableSort.addClass(obj.thNode, obj.reverse ? "reverseSort" : "forwardSort");
+                                                if(showArrow) {
+                                                        span = fdTableSort.thNode.getElementsByTagName('span')[0];
+                                                        if(span.firstChild) { span.removeChild(span.firstChild); };
+                                                        span.appendChild(document.createTextNode(len == 1 ? " \u2193" : " \u2191"));
+                                                };
+                                        };
+                                };
+                                if(showOnly && (fdTableSort.tableCache[tbl.id].colStyle || fdTableSort.tableCache[tbl.id].rowStyle)) {
+                                        fdTableSort.redraw(tbl.id, false);
+                                };
+                        } else if(tbl.className.search(/onload-zebra/) != -1) {
+                                fdTableSort.tableId = tbl.id;
+                                fdTableSort.prepareTableData(tbl);
+                                if(fdTableSort.tableCache[tbl.id].rowStyle) { fdTableSort.redraw(tbl.id, false); };
+                        };
+                };
+
+                fdTableSort.thNode = aclone = a = span = columnNumSortObj = thNode = tbl = allRowArr = rowArr = null;
+        },
+        initWrapper: function(e) {
+                e = e || window.event;
+                var kc = e.type == "keydown" ? e.keyCode != null ? e.keyCode : e.charCode : -1;
+                if(fdTableSort.thNode == null && (e.type == "click" || kc == 13)) {
+                        var targ = this;
+                        while(targ.tagName.toLowerCase() != "th") { targ = targ.parentNode; };
+                        fdTableSort.thNode = targ;
+                        while(targ.tagName.toLowerCase() != "table") { targ = targ.parentNode; };
+                        fdTableSort.tableId = targ.id;
+                        fdTableSort.multi = e.shiftKey;
+                        fdTableSort.addSortActiveClass();
+                        setTimeout(fdTableSort.initSort,5,false);
+                        return fdTableSort.stopEvent(e);
+                };
+                return kc != -1 ? true : fdTableSort.stopEvent(e);
+        },
+        jsWrapper: function(tableid, colNums) {
+                if(!(tableid in fdTableSort.tmpCache)) { return false; };
+                if(!(tableid in fdTableSort.tableCache)) { fdTableSort.prepareTableData(document.getElementById(tableid)); };
+                if(!(colNums instanceof Array)) { colNums = [colNums]; };
+
+                fdTableSort.tableId = tableid;
+                var len = colNums.length, colNum;
+
+                if(fdTableSort.tableCache[tableid].thList.length == colNums.length) {
+                        var identical = true;
+                        var th;
+                        for(var i = 0; i < len; i++) {
+                                colNum = colNums[i];
+                                th = fdTableSort.tmpCache[tableid].headers[0][colNum];
+                                if(th != fdTableSort.tableCache[tableid].thList[i]) {
+                                        identical = false;
+                                        break;
+                                };
+                        };
+                        if(identical) {
+                                fdTableSort.thNode = th;
+                                fdTableSort.initSort(true);
+                                return;
+                        };
+                };
+
+                fdTableSort.addSortActiveClass();
+
+                for(var i = 0; i < len; i++) {
+                        fdTableSort.multi = i;
+                        colNum = colNums[i];
+                        fdTableSort.thNode = fdTableSort.tmpCache[tableid].headers[0][colNum];
+                        fdTableSort.initSort(true);
+                };
+        },
+        addSortActiveClass: function() {
+                if(fdTableSort.thNode == null) { return; };
+                fdTableSort.addClass(fdTableSort.thNode, fdTableSort.sortActiveClass);
+                fdTableSort.addClass(document.getElementsByTagName('body')[0], fdTableSort.sortActiveClass);
+        },
+        removeSortActiveClass: function() {
+                if(fdTableSort.thNode == null) return;
+                fdTableSort.removeClass(fdTableSort.thNode, fdTableSort.sortActiveClass);
+                fdTableSort.removeClass(document.getElementsByTagName('body')[0], fdTableSort.sortActiveClass);
+        },
+        doCallback: function(init) {
+                if(!fdTableSort.tableId || !(fdTableSort.tableId in fdTableSort.tableCache)) { return; };
+                fdTableSort.callback(fdTableSort.tableId, init ? fdTableSort.tableCache[fdTableSort.tableId].initiatedCallback : fdTableSort.tableCache[fdTableSort.tableId].completeCallback);
+        },
+        addClass: function(e,c) {
+                if(new RegExp("(^|\\s)" + c + "(\\s|$)").test(e.className)) { return; };
+                e.className += ( e.className ? " " : "" ) + c;
+        },
+        /*@cc_on
+        /*@if (@_win32)
+        removeClass: function(e,c) {
+                e.className = !c ? "" : e.className.replace(new RegExp("(^|\\s)" + c + "(\\s|$)"), " ").replace(/^\s*((?:[\S\s]*\S)?)\s*$/, '$1');
+        },
+        @else @*/
+        removeClass: function(e,c) {
+                e.className = !c ? "" : e.className.replace(new RegExp("(^|\\s)" + c + "(\\s|$)"), " ").replace(/^\s\s*/, '').replace(/\s\s*$/, '');
+        },
+        /*@end
+        @*/
+        callback: function(tblId, cb) {
+                var func, parts;
+                try {
+                        if(cb.indexOf(".") != -1) {                              
+                                parts = cb.split('.');
+                                obj   = window;
+                                for (var x = 0, part; part = obj[parts[x]]; x++) {
+                                        if(part instanceof Function) {
+                                                (function() {
+                                                        var method = part;
+                                                        func = function (data) { method.apply(obj, [data]) };
+                                                })();
+                                        } else {
+                                                obj = part;
+                                        };
+                                };
+                        } else if(cb + tblId in window) {
+                                func = window[cb + tblId];
+                        } else if(cb in window) {
+                                func = window[cb];
+                        } else {
+                                func = null;
+                        };
+                 } catch(err) {};
+                           
+                if(!(func instanceof Function)) return;
+                func(tblId, fdTableSort.tableCache[tblId].thList);                               
+        },
+        prepareTableData: function(table) {
+                var data = [];
+
+                var start = table.getElementsByTagName('tbody');
+                start = start.length ? start[0] : table;
+
+                var trs = start.rows;
+                var ths = table.getElementsByTagName('th');
+
+                var numberOfRows = trs.length;
+                var numberOfCols = fdTableSort.tmpCache[table.id].cols;
+
+                var data = [];
+                var identical = new Array(numberOfCols);
+                var identVal  = new Array(numberOfCols);
+
+                for(var tmp = 0; tmp < numberOfCols; tmp++) identical[tmp] = true;
+
+                var tr, td, th, txt, tds, col, row;
+
+                var re = new RegExp(/fd-column-([0-9]+)/);
+                var rowCnt = 0;
+
+                var sortableColumnNumbers = [];
+
+                for(var tmp = 0, th; th = ths[tmp]; tmp++) {
+                        if(th.className.search(re) == -1) continue;
+                        sortableColumnNumbers[sortableColumnNumbers.length] = th;
+                };
+
+                for(row = 0; row < numberOfRows; row++) {
+
+                        tr              = trs[row];
+                        if(tr.parentNode != start || tr.getElementsByTagName("th").length || (tr.parentNode && tr.parentNode.tagName.toLowerCase().search(/thead|tfoot/) != -1)) continue;
+                        data[rowCnt]    = [];
+                        tds             = tr.cells;
+
+                        for(var tmp = 0, th; th = sortableColumnNumbers[tmp]; tmp++) {
+                                col = th.className.match(re)[1];
+
+                                td  = tds[col];
+                                txt = fdTableSort.getInnerText(td) + " ";
+                                txt = txt.replace(/^\s+/,'').replace(/\s+$/,'');
+
+                                if(th.className.search(/sortable-date/) != -1) {
+                                        txt = fdTableSort.dateFormat(txt, th.className.search(/sortable-date-dmy/) != -1);
+                                } else if(th.className.search(/sortable-numeric|sortable-currency/) != -1) {
+                                        txt = parseFloat(txt.replace(/[^0-9\.\-]/g,''));
+                                        if(isNaN(txt)) txt = "";
+                                } else if(th.className.search(/sortable-text/) != -1) {
+                                        txt = txt.toLowerCase();
+                                } else if (th.className.search(/sortable-keep/) != -1) {
+                                        txt = rowCnt;
+                                } else if(th.className.search(/sortable-([a-zA-Z\_]+)/) != -1) {
+                                        if((th.className.match(/sortable-([a-zA-Z\_]+)/)[1] + "PrepareData") in window) {
+                                                txt = window[th.className.match(/sortable-([a-zA-Z\_]+)/)[1] + "PrepareData"](td, txt);
+                                        };
+                                } else if(txt != "") {
+                                        fdTableSort.removeClass(th, "sortable");
+                                        if(fdTableSort.dateFormat(txt) != 0) {
+                                                fdTableSort.addClass(th, "sortable-date");
+                                                txt = fdTableSort.dateFormat(txt);
+                                        } else if(txt.search(fdTableSort.regExp_Number) != -1 || txt.search(fdTableSort.regExp_Currency) != -1) {
+                                                fdTableSort.addClass(th, "sortable-numeric");
+                                                txt = parseFloat(txt.replace(/[^0-9\.\-]/g,''));
+                                                if(isNaN(txt)) txt = "";
+                                        } else {
+                                                fdTableSort.addClass(th, "sortable-text");
+                                                txt = txt.toLowerCase();
+                                        };
+                                };
+
+                                if(rowCnt > 0 && identical[col] && identVal[col] != txt) { identical[col] = false; };
+
+                                identVal[col]     = txt;
+                                data[rowCnt][col] = txt;
+                        };
+                        data[rowCnt][numberOfCols] = tr;
+                        rowCnt++;
+                };
+
+                var colStyle = table.className.search(/colstyle-([\S]+)/) != -1 ? table.className.match(/colstyle-([\S]+)/)[1] : false;
+                var rowStyle = table.className.search(/rowstyle-([\S]+)/) != -1 ? table.className.match(/rowstyle-([\S]+)/)[1] : false;
+                var iCBack   = table.className.search(/sortinitiatedcallback-([\S-]+)/) == -1 ? "sortInitiatedCallback" : table.className.match(/sortinitiatedcallback-([\S]+)/)[1];
+                var cCBack   = table.className.search(/sortcompletecallback-([\S-]+)/) == -1 ? "sortCompleteCallback" : table.className.match(/sortcompletecallback-([\S]+)/)[1];
+                iCBack = iCBack.replace("-", ".");
+                cCBack = cCBack.replace("-", ".");
+                fdTableSort.tableCache[table.id] = { hook:start, initiatedCallback:iCBack, completeCallback:cCBack, thList:[], colOrder:{}, data:data, identical:identical, colStyle:colStyle, rowStyle:rowStyle, noArrow:table.className.search(/no-arrow/) != -1 };
+                sortableColumnNumbers = data = tr = td = th = trs = identical = identVal = null;
+        },
+        onUnload: function() {
+                for(tbl in fdTableSort.tableCache) { fdTableSort.removeTableCache(tbl); };
+                for(tbl in fdTableSort.tmpCache) { fdTableSort.removeTmpCache(tbl); };
+                fdTableSort.removeEvent(window, "load", fdTableSort.initEvt);
+                fdTableSort.removeEvent(window, "unload", fdTableSort.onUnload);
+                fdTableSort.tmpCache = fdTableSort.tableCache = null;
+        },
+        addThNode: function() {
+                var dataObj = fdTableSort.tableCache[fdTableSort.tableId];
+                var pos     = fdTableSort.thNode.className.match(/fd-column-([0-9]+)/)[1];
+                var alt     = false;
+
+                if(!fdTableSort.multi) {
+                        if(dataObj.colStyle) {
+                                var len = dataObj.thList.length;
+                                for(var i = 0; i < len; i++) {
+                                        dataObj.colOrder[dataObj.thList[i].className.match(/fd-column-([0-9]+)/)[1]] = false;
+                                };
+                        };
+                        if(dataObj.thList.length && dataObj.thList[0] == fdTableSort.thNode) alt = true;
+                        dataObj.thList = [];
+                };
+
+                var found = false;
+                var l = dataObj.thList.length;
+
+                for(var i = 0, n; n = dataObj.thList[i]; i++) {
+                        if(n == fdTableSort.thNode) {
+                                found = true;
+                                break;
+                        };
+                };
+
+                if(!found) {
+                        dataObj.thList.push(fdTableSort.thNode);
+                        if(dataObj.colStyle) { dataObj.colOrder[pos] = true; };
+                };
+
+                var ths = document.getElementById(fdTableSort.tableId).getElementsByTagName("th");
+                for(var i = 0, th; th = ths[i]; i++) {
+                        found = false;
+                        for(var z = 0, n; n = dataObj.thList[z]; z++) {
+                                if(n == th) {
+                                        found = true;
+                                        break;
+                                };
+                        };
+                        if(!found) {
+                                fdTableSort.removeClass(th, "(forwardSort|reverseSort)");
+                                if(!dataObj.noArrow) {
+                                        span = th.getElementsByTagName('span');
+                                        if(span.length) {
+                                                span = span[0];
+                                                while(span.firstChild) span.removeChild(span.firstChild);
+                                        };
+                                };
+                        };
+                };
+
+                if(dataObj.thList.length > 1) {
+                        classToAdd = fdTableSort.thNode.className.search(/forwardSort/) != -1 ? "reverseSort" : "forwardSort";
+                        fdTableSort.removeClass(fdTableSort.thNode, "(forwardSort|reverseSort)");
+                        fdTableSort.addClass(fdTableSort.thNode, classToAdd);
+                        dataObj.pos = -1
+                } else if(alt) { dataObj.pos = fdTableSort.thNode };
+        },
+        initSort: function(noCallback, ident) {
+                var thNode      = fdTableSort.thNode;
+                var tableElem   = document.getElementById(fdTableSort.tableId);
+
+                if(!(fdTableSort.tableId in fdTableSort.tableCache)) { fdTableSort.prepareTableData(document.getElementById(fdTableSort.tableId)); };
+
+                fdTableSort.addThNode();
+
+                if(!noCallback) { fdTableSort.doCallback(true); };
+
+                fdTableSort.pos = thNode.className.match(/fd-column-([0-9]+)/)[1];
+                var dataObj     = fdTableSort.tableCache[tableElem.id];
+                var lastPos     = dataObj.pos && dataObj.pos.className ? dataObj.pos.className.match(/fd-column-([0-9]+)/)[1] : -1;
+                var len1        = dataObj.data.length;
+                var len2        = dataObj.data.length > 0 ? dataObj.data[0].length - 1 : 0;
+                var identical   = dataObj.identical[fdTableSort.pos];
+                var classToAdd  = "forwardSort";
+
+                if(dataObj.thList.length > 1) {
+                        var js  = "var sortWrapper = function(a,b) {\n";
+                        var l   = dataObj.thList.length;
+                        var cnt = 0;
+                        var e,d,th,p,f;
+
+                        for(var i=0; i < l; i++) {
+                                th = dataObj.thList[i];
+                                p  = th.className.match(/fd-column-([0-9]+)/)[1];
+                                if(dataObj.identical[p]) { continue; };
+                                cnt++;
+
+                                if(th.className.match(/sortable-(numeric|currency|date|keep)/)) {
+                                        f = "fdTableSort.sortNumeric";
+                                } else if(th.className.match('sortable-text')) {
+                                        f = "fdTableSort.sortText";
+                                } else if(th.className.search(/sortable-([a-zA-Z\_]+)/) != -1 && th.className.match(/sortable-([a-zA-Z\_]+)/)[1] in window) {
+                                        f = "window['" + th.className.match(/sortable-([a-zA-Z\_]+)/)[1] + "']";
+                                } else  f = "fdTableSort.sortText";
+
+                                e = "e" + i;
+                                d = th.className.search('forwardSort') != -1 ? "a,b" : "b,a";
+                                js += "fdTableSort.pos   = " + p + ";\n";
+                                js += "var " + e + " = "+f+"(" + d +");\n";
+                                js += "if(" + e + ") return " + e + ";\n";
+                                js += "else { \n";
+                        };
+
+                        js += "return 0;\n";
+
+                        for(var i=0; i < cnt; i++) {
+                                js += "};\n";
+                        };
+
+                        if(cnt) js += "return 0;\n";
+                        js += "};\n";
+
+                        eval(js);
+                        dataObj.data.sort(sortWrapper);
+                        identical = false;
+                } else if((lastPos == fdTableSort.pos && !identical) || (thNode.className.search(/sortable-keep/) != -1 && lastPos == -1)) {
+                        dataObj.data.reverse();
+                        classToAdd = thNode.className.search(/reverseSort/) != -1 ? "forwardSort" : "reverseSort";
+                        if(thNode.className.search(/sortable-keep/) != -1 && lastPos == -1) fdTableSort.tableCache[tableElem.id].pos = thNode;
+                } else {
+                        fdTableSort.tableCache[tableElem.id].pos = thNode;
+                        classToAdd = thNode.className.search(/forwardSort/) != -1 ? "reverseSort" : "forwardSort";
+                        if(!identical) {
+                                if(thNode.className.match(/sortable-(numeric|currency|date|keep)/)) {
+                                        dataObj.data.sort(fdTableSort.sortNumeric);
+                                } else if(thNode.className.match('sortable-text')) {
+                                        dataObj.data.sort(fdTableSort.sortText);
+                                } else if(thNode.className.search(/sortable-([a-zA-Z\_]+)/) != -1 && thNode.className.match(/sortable-([a-zA-Z\_]+)/)[1] in window) {
+                                        dataObj.data.sort(window[thNode.className.match(/sortable-([a-zA-Z\_]+)/)[1]]);
+                                };
+
+                                if(thNode.className.search(/(^|\s)favour-reverse($|\s)/) != -1) {
+                                        classToAdd = classToAdd == "forwardSort" ? "reverseSort" : "forwardSort";
+                                        dataObj.data.reverse();
+                                };
+                        };
+                };
+                if(ident) { identical = false; };
+                if(dataObj.thList.length == 1) {
+                        fdTableSort.removeClass(thNode, "(forwardSort|reverseSort)");
+                        fdTableSort.addClass(thNode, classToAdd);
+                };
+                if(!dataObj.noArrow) {
+                        var span = fdTableSort.thNode.getElementsByTagName('span')[0];
+                        if(span.firstChild) span.removeChild(span.firstChild);
+                        span.appendChild(document.createTextNode(fdTableSort.thNode.className.search(/forwardSort/) != -1 ? " \u2193" : " \u2191"));
+                };
+                if(!dataObj.rowStyle && !dataObj.colStyle && identical) {
+                        fdTableSort.removeSortActiveClass();
+                        if(!noCallback) { fdTableSort.doCallback(false); };
+                        fdTableSort.thNode = null;
+                        return;
+                };
+                if("tablePaginater" in window && tablePaginater.tableIsPaginated(fdTableSort.tableId)) {
+                        tablePaginater.redraw(fdTableSort.tableId, identical);
+                } else {
+                        fdTableSort.redraw(fdTableSort.tableId, identical);
+                };
+                fdTableSort.removeSortActiveClass();
+                if(!noCallback) { fdTableSort.doCallback(false); };
+                fdTableSort.thNode = null;
+        },
+        redraw: function(tableid, identical) {
+                if(!tableid || !(tableid in fdTableSort.tableCache)) { return; };
+                var dataObj     = fdTableSort.tableCache[tableid];
+                var data        = dataObj.data;
+                var len1        = data.length;
+                var len2        = len1 ? data[0].length - 1 : 0;
+                var hook        = dataObj.hook;
+                var colStyle    = dataObj.colStyle;
+                var rowStyle    = dataObj.rowStyle;
+                var colOrder    = dataObj.colOrder;
+                var highLight   = 0;
+                var reg         = /(^|\s)invisibleRow(\s|$)/;
+                var tr, tds;
+
+                for(var i = 0; i < len1; i++) {
+                        tr = data[i][len2];
+                        if(colStyle) {
+                                tds = tr.cells;
+                                for(thPos in colOrder) {
+                                        if(!colOrder[thPos]) fdTableSort.removeClass(tds[thPos], colStyle);
+                                        else fdTableSort.addClass(tds[thPos], colStyle);
+                                };
+                        };
+                        if(!identical) {
+                                if(rowStyle && tr.className.search(reg) == -1) {
+                                        if(highLight++ & 1) fdTableSort.addClass(tr, rowStyle);
+                                        else fdTableSort.removeClass(tr, rowStyle);
+                                };
+
+                                // Netscape 8.1.2 requires the removeChild call or it freaks out, so add the line if you want to support this browser
+                                // hook.removeChild(tr);
+                                hook.appendChild(tr);
+                        };
+                };
+                tr = tds = hook = null;
+        },
+        getInnerText: function(el, allowBrTags) {
+                if (typeof el == "string" || typeof el == "undefined") return el;
+                if(el.innerText) return el.innerText;
+                var txt = '', i;
+                for(i = el.firstChild; i; i = i.nextSibling) {
+                        if(allowBrTags && i.nodeName && i.nodeName == "BR") txt += "<br />";
+                        else if(i.nodeType == 3)       txt += i.nodeValue;
+                        else if(i.nodeType == 1)       txt += fdTableSort.getInnerText(i);
+                };
+                return txt;
+        },
+        dateFormat: function(dateIn, favourDMY) {
+                var dateTest = [
+                        { regExp:/^(0?[1-9]|1[012])([- \/.])(0?[1-9]|[12][0-9]|3[01])([- \/.])((\d\d)?\d\d)$/, d:3, m:1, y:5 },  // mdy
+                        { regExp:/^(0?[1-9]|[12][0-9]|3[01])([- \/.])(0?[1-9]|1[012])([- \/.])((\d\d)?\d\d)$/, d:1, m:3, y:5 },  // dmy
+                        { regExp:/^(\d\d\d\d)([- \/.])(0?[1-9]|1[012])([- \/.])(0?[1-9]|[12][0-9]|3[01])$/, d:5, m:3, y:1 }      // ymd
+                        ];
+                var start, cnt = 0, numFormats = dateTest.length;
+                while(cnt < numFormats) {
+                        start = (cnt + (favourDMY ? numFormats + 1 : numFormats)) % numFormats;
+                        if(dateIn.match(dateTest[start].regExp)) {
+                                res = dateIn.match(dateTest[start].regExp);
+                                y = res[dateTest[start].y];
+                                m = res[dateTest[start].m];
+                                d = res[dateTest[start].d];
+                                if(m.length == 1) m = "0" + String(m);
+                                if(d.length == 1) d = "0" + String(d);
+                                if(y.length != 4) y = (parseInt(y) < 50) ? "20" + String(y) : "19" + String(y);
+
+                                return y+String(m)+d;
+                        };
+                        cnt++;
+                };
+                return 0;
+        },
+        sortNumeric:function(a,b) {
+                var aa = a[fdTableSort.pos];
+                var bb = b[fdTableSort.pos];
+                if(aa == bb) return 0;
+                if(aa === "" && !isNaN(bb)) return -1;
+                if(bb === "" && !isNaN(aa)) return 1;
+                return aa - bb;
+        },
+        sortText:function(a,b) {
+                var aa = a[fdTableSort.pos];
+                var bb = b[fdTableSort.pos];
+                if(aa == bb) return 0;
+                if(aa < bb)  return -1;
+                return 1;
+        }
+};
+})();
+fdTableSort.addEvent(window, "load",   fdTableSort.initEvt);
+fdTableSort.addEvent(window, "unload", fdTableSort.onUnload);