From adfd75f0d83b047e2a3c1494cbbe0c492e10886c Mon Sep 17 00:00:00 2001 From: Thierry Parmentelat Date: Thu, 28 May 2009 08:44:42 +0000 Subject: [PATCH] dos2unix --- plekit/datepicker/datepicker.css | 876 +++--- plekit/datepicker/datepicker.js | 4214 +++++++++++++-------------- plekit/niftycorner/niftyCorners.css | 70 +- plekit/niftycorner/niftycube.js | 654 ++--- plekit/tablesort/customsort.js | 712 ++--- plekit/tablesort/paginate.js | 956 +++--- plekit/tablesort/tablesort.js | 1496 +++++----- 7 files changed, 4489 insertions(+), 4489 deletions(-) diff --git a/plekit/datepicker/datepicker.css b/plekit/datepicker/datepicker.css index c3d0f0b..c03362b 100644 --- a/plekit/datepicker/datepicker.css +++ b/plekit/datepicker/datepicker.css @@ -1,438 +1,438 @@ -/* 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); - } - -} - +/* 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); + } + +} + diff --git a/plekit/datepicker/datepicker.js b/plekit/datepicker/datepicker.js index 16b099f..586f52f 100644 --- a/plekit/datepicker/datepicker.js +++ b/plekit/datepicker/datepicker.js @@ -1,2107 +1,2107 @@ -/* - 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:'';"; - 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$2"); - msg = msg.split(/|<\/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"]); +/* + 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:'';"; + 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$2"); + msg = msg.split(/|<\/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"]); diff --git a/plekit/niftycorner/niftyCorners.css b/plekit/niftycorner/niftyCorners.css index 9e56ec0..9c7cd64 100755 --- a/plekit/niftycorner/niftyCorners.css +++ b/plekit/niftycorner/niftyCorners.css @@ -1,35 +1,35 @@ -/*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} +/*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} diff --git a/plekit/niftycorner/niftycube.js b/plekit/niftycorner/niftycube.js index 14406a7..aade96f 100755 --- a/plekit/niftycorner/niftycube.js +++ b/plekit/niftycorner/niftycube.js @@ -1,327 +1,327 @@ -/* 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;i0;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;imaxh) maxh=els[i].offsetHeight; - els[i].style.height="auto"; - } -for(i=0;i0){ - 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=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;i0;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;imaxh) maxh=els[i].offsetHeight; + els[i].style.height="auto"; + } +for(i=0;i0){ + 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 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; } - }; +/* + 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 diff --git a/plekit/tablesort/tablesort.js b/plekit/tablesort/tablesort.js index 27e8c3c..9b55e59 100644 --- a/plekit/tablesort/tablesort.js +++ b/plekit/tablesort/tablesort.js @@ -1,748 +1,748 @@ -/* - 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('
', '') + "\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 += "
"; - 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); +/* + 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('
', '') + "\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 += "
"; + 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); -- 2.43.0