alfa 0.0.1.pre → 0.0.2.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (238) hide show
  1. data/assets/css/960gs/960.css +653 -0
  2. data/assets/css/960gs/960_12_col.css +357 -0
  3. data/assets/css/960gs/960_12_col_rtl.css +357 -0
  4. data/assets/css/960gs/960_16_col.css +446 -0
  5. data/assets/css/960gs/960_16_col_rtl.css +446 -0
  6. data/assets/css/960gs/960_24_col.css +621 -0
  7. data/assets/css/960gs/960_24_col_rtl.css +621 -0
  8. data/assets/css/960gs/960_rtl.css +653 -0
  9. data/assets/css/960gs/demo.css +55 -0
  10. data/assets/css/960gs/min/960.css +1 -0
  11. data/assets/css/960gs/min/960_12_col.css +1 -0
  12. data/assets/css/960gs/min/960_12_col_rtl.css +1 -0
  13. data/assets/css/960gs/min/960_16_col.css +1 -0
  14. data/assets/css/960gs/min/960_16_col_rtl.css +1 -0
  15. data/assets/css/960gs/min/960_24_col.css +1 -0
  16. data/assets/css/960gs/min/960_24_col_rtl.css +1 -0
  17. data/assets/css/960gs/min/960_rtl.css +1 -0
  18. data/assets/css/960gs/min/reset.css +1 -0
  19. data/assets/css/960gs/min/reset_rtl.css +1 -0
  20. data/assets/css/960gs/min/text.css +1 -0
  21. data/assets/css/960gs/min/text_rtl.css +1 -0
  22. data/assets/css/960gs/reset.css +211 -0
  23. data/assets/css/960gs/reset_rtl.css +211 -0
  24. data/assets/css/960gs/text.css +86 -0
  25. data/assets/css/960gs/text_rtl.css +86 -0
  26. data/assets/js/jquery/jquery-1.3.2.js +4376 -0
  27. data/assets/js/jquery/jquery-1.3.2.min.js +19 -0
  28. data/assets/js/jquery/jquery-1.4.2.js +6240 -0
  29. data/assets/js/jquery/jquery-1.4.2.min.js +154 -0
  30. data/assets/js/jquery/jquery-1.4.4.js +7179 -0
  31. data/assets/js/jquery/jquery-1.4.4.min.js +167 -0
  32. data/assets/js/jquery/jquery-1.8.2.js +9440 -0
  33. data/assets/js/jquery/jquery-1.8.2.min.js +2 -0
  34. data/assets/js/jquery/jquery-latest.js +2 -0
  35. data/assets/js/jquery/plugins/corner.js +178 -0
  36. data/assets/js/jquery/plugins/corner_12x.js +503 -0
  37. data/assets/js/jquery/plugins/datepick/calendar-green.gif +0 -0
  38. data/assets/js/jquery/plugins/datepick/calendar.gif +0 -0
  39. data/assets/js/jquery/plugins/datepick/datepickBasics.html +34 -0
  40. data/assets/js/jquery/plugins/datepick/flora.datepick.css +221 -0
  41. data/assets/js/jquery/plugins/datepick/humanity.datepick.css +192 -0
  42. data/assets/js/jquery/plugins/datepick/jquery.datepick-ar.js +27 -0
  43. data/assets/js/jquery/plugins/datepick/jquery.datepick-az.js +26 -0
  44. data/assets/js/jquery/plugins/datepick/jquery.datepick-bg.js +26 -0
  45. data/assets/js/jquery/plugins/datepick/jquery.datepick-ca.js +26 -0
  46. data/assets/js/jquery/plugins/datepick/jquery.datepick-cs.js +26 -0
  47. data/assets/js/jquery/plugins/datepick/jquery.datepick-da.js +26 -0
  48. data/assets/js/jquery/plugins/datepick/jquery.datepick-de.js +26 -0
  49. data/assets/js/jquery/plugins/datepick/jquery.datepick-el.js +26 -0
  50. data/assets/js/jquery/plugins/datepick/jquery.datepick-eo.js +26 -0
  51. data/assets/js/jquery/plugins/datepick/jquery.datepick-es.js +26 -0
  52. data/assets/js/jquery/plugins/datepick/jquery.datepick-et.js +26 -0
  53. data/assets/js/jquery/plugins/datepick/jquery.datepick-fa.js +26 -0
  54. data/assets/js/jquery/plugins/datepick/jquery.datepick-fi.js +26 -0
  55. data/assets/js/jquery/plugins/datepick/jquery.datepick-fr.js +26 -0
  56. data/assets/js/jquery/plugins/datepick/jquery.datepick-he.js +26 -0
  57. data/assets/js/jquery/plugins/datepick/jquery.datepick-hr.js +26 -0
  58. data/assets/js/jquery/plugins/datepick/jquery.datepick-hu.js +26 -0
  59. data/assets/js/jquery/plugins/datepick/jquery.datepick-hy.js +26 -0
  60. data/assets/js/jquery/plugins/datepick/jquery.datepick-id.js +26 -0
  61. data/assets/js/jquery/plugins/datepick/jquery.datepick-is.js +26 -0
  62. data/assets/js/jquery/plugins/datepick/jquery.datepick-it.js +26 -0
  63. data/assets/js/jquery/plugins/datepick/jquery.datepick-ja.js +26 -0
  64. data/assets/js/jquery/plugins/datepick/jquery.datepick-ko.js +26 -0
  65. data/assets/js/jquery/plugins/datepick/jquery.datepick-lt.js +26 -0
  66. data/assets/js/jquery/plugins/datepick/jquery.datepick-lv.js +26 -0
  67. data/assets/js/jquery/plugins/datepick/jquery.datepick-ms.js +26 -0
  68. data/assets/js/jquery/plugins/datepick/jquery.datepick-nl.js +26 -0
  69. data/assets/js/jquery/plugins/datepick/jquery.datepick-no.js +26 -0
  70. data/assets/js/jquery/plugins/datepick/jquery.datepick-pl.js +26 -0
  71. data/assets/js/jquery/plugins/datepick/jquery.datepick-pt-BR.js +26 -0
  72. data/assets/js/jquery/plugins/datepick/jquery.datepick-ro.js +26 -0
  73. data/assets/js/jquery/plugins/datepick/jquery.datepick-ru.js +26 -0
  74. data/assets/js/jquery/plugins/datepick/jquery.datepick-sk.js +26 -0
  75. data/assets/js/jquery/plugins/datepick/jquery.datepick-sl.js +27 -0
  76. data/assets/js/jquery/plugins/datepick/jquery.datepick-sq.js +26 -0
  77. data/assets/js/jquery/plugins/datepick/jquery.datepick-sr-SR.js +25 -0
  78. data/assets/js/jquery/plugins/datepick/jquery.datepick-sr.js +25 -0
  79. data/assets/js/jquery/plugins/datepick/jquery.datepick-sv.js +26 -0
  80. data/assets/js/jquery/plugins/datepick/jquery.datepick-th.js +26 -0
  81. data/assets/js/jquery/plugins/datepick/jquery.datepick-tr.js +26 -0
  82. data/assets/js/jquery/plugins/datepick/jquery.datepick-uk.js +26 -0
  83. data/assets/js/jquery/plugins/datepick/jquery.datepick-validation.js +141 -0
  84. data/assets/js/jquery/plugins/datepick/jquery.datepick-validation.min.js +8 -0
  85. data/assets/js/jquery/plugins/datepick/jquery.datepick-validation.pack.js +8 -0
  86. data/assets/js/jquery/plugins/datepick/jquery.datepick-zh-CN.js +26 -0
  87. data/assets/js/jquery/plugins/datepick/jquery.datepick-zh-TW.js +26 -0
  88. data/assets/js/jquery/plugins/datepick/jquery.datepick.css +216 -0
  89. data/assets/js/jquery/plugins/datepick/jquery.datepick.ent +76 -0
  90. data/assets/js/jquery/plugins/datepick/jquery.datepick.js +1974 -0
  91. data/assets/js/jquery/plugins/datepick/jquery.datepick.min.js +8 -0
  92. data/assets/js/jquery/plugins/datepick/jquery.datepick.pack.js +8 -0
  93. data/assets/js/jquery/plugins/datepick/redmond.datepick.css +204 -0
  94. data/assets/js/jquery/plugins/datepick/smoothness.datepick.css +205 -0
  95. data/assets/js/jquery/plugins/fancybox/blank.gif +0 -0
  96. data/assets/js/jquery/plugins/fancybox/fancy_close.png +0 -0
  97. data/assets/js/jquery/plugins/fancybox/fancy_loading.png +0 -0
  98. data/assets/js/jquery/plugins/fancybox/fancy_nav_left.png +0 -0
  99. data/assets/js/jquery/plugins/fancybox/fancy_nav_right.png +0 -0
  100. data/assets/js/jquery/plugins/fancybox/fancy_shadow_e.png +0 -0
  101. data/assets/js/jquery/plugins/fancybox/fancy_shadow_n.png +0 -0
  102. data/assets/js/jquery/plugins/fancybox/fancy_shadow_ne.png +0 -0
  103. data/assets/js/jquery/plugins/fancybox/fancy_shadow_nw.png +0 -0
  104. data/assets/js/jquery/plugins/fancybox/fancy_shadow_s.png +0 -0
  105. data/assets/js/jquery/plugins/fancybox/fancy_shadow_se.png +0 -0
  106. data/assets/js/jquery/plugins/fancybox/fancy_shadow_sw.png +0 -0
  107. data/assets/js/jquery/plugins/fancybox/fancy_shadow_w.png +0 -0
  108. data/assets/js/jquery/plugins/fancybox/fancy_title_left.png +0 -0
  109. data/assets/js/jquery/plugins/fancybox/fancy_title_main.png +0 -0
  110. data/assets/js/jquery/plugins/fancybox/fancy_title_over.png +0 -0
  111. data/assets/js/jquery/plugins/fancybox/fancy_title_right.png +0 -0
  112. data/assets/js/jquery/plugins/fancybox/fancybox-x.png +0 -0
  113. data/assets/js/jquery/plugins/fancybox/fancybox-y.png +0 -0
  114. data/assets/js/jquery/plugins/fancybox/fancybox.png +0 -0
  115. data/assets/js/jquery/plugins/fancybox/jquery.easing-1.3.pack.js +72 -0
  116. data/assets/js/jquery/plugins/fancybox/jquery.fancybox-1.3.2.css +359 -0
  117. data/assets/js/jquery/plugins/fancybox/jquery.fancybox-1.3.2.js +1136 -0
  118. data/assets/js/jquery/plugins/fancybox/jquery.fancybox-1.3.2.pack.js +46 -0
  119. data/assets/js/jquery/plugins/fancybox/jquery.fancybox-1.3.4.css +359 -0
  120. data/assets/js/jquery/plugins/fancybox/jquery.fancybox-1.3.4.js +1156 -0
  121. data/assets/js/jquery/plugins/fancybox/jquery.fancybox-1.3.4.pack.js +46 -0
  122. data/assets/js/jquery/plugins/fancybox/jquery.mousewheel-3.0.4.pack.js +14 -0
  123. data/assets/js/jquery/plugins/jquery.cookie.js +96 -0
  124. data/assets/js/jquery/plugins/jquery.easing.1.3.js +205 -0
  125. data/assets/js/jquery/plugins/jquery.flash.js +288 -0
  126. data/assets/js/jquery/plugins/jquery.flash.min.js +1 -0
  127. data/assets/js/jquery/plugins/jquery.ifixpng.js +137 -0
  128. data/assets/js/jquery/plugins/jquery.mousewheel.js +84 -0
  129. data/assets/js/jquery/plugins/jquery.mousewheel.min.js +12 -0
  130. data/assets/js/jquery/plugins/jquery.numberformatter-1.2.2.js +486 -0
  131. data/assets/js/jquery/plugins/jquery.sifr.js +224 -0
  132. data/assets/js/jquery/plugins/jquery.sifr.min.js +1 -0
  133. data/assets/js/jquery/plugins/jquery.swfobject.js +1 -0
  134. data/assets/js/jquery/plugins/jquery.timers-1.1.2.js +147 -0
  135. data/assets/js/jquery/plugins/simplegallery.js +167 -0
  136. data/assets/js/jquery/ui/external/jquery.bgiframe-2.1.2.js +39 -0
  137. data/assets/js/jquery/ui/external/jquery.cookie.js +89 -0
  138. data/assets/js/jquery/ui/external/jquery.metadata.js +122 -0
  139. data/assets/js/jquery/ui/external/qunit.css +153 -0
  140. data/assets/js/jquery/ui/external/qunit.js +1261 -0
  141. data/assets/js/jquery/ui/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  142. data/assets/js/jquery/ui/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  143. data/assets/js/jquery/ui/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  144. data/assets/js/jquery/ui/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  145. data/assets/js/jquery/ui/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  146. data/assets/js/jquery/ui/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  147. data/assets/js/jquery/ui/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  148. data/assets/js/jquery/ui/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  149. data/assets/js/jquery/ui/images/ui-icons_222222_256x240.png +0 -0
  150. data/assets/js/jquery/ui/images/ui-icons_2e83ff_256x240.png +0 -0
  151. data/assets/js/jquery/ui/images/ui-icons_454545_256x240.png +0 -0
  152. data/assets/js/jquery/ui/images/ui-icons_888888_256x240.png +0 -0
  153. data/assets/js/jquery/ui/images/ui-icons_cd0a0a_256x240.png +0 -0
  154. data/assets/js/jquery/ui/jquery-ui-latest.min.js +778 -0
  155. data/assets/js/jquery/ui/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  156. data/assets/js/jquery/ui/themes/base/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  157. data/assets/js/jquery/ui/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  158. data/assets/js/jquery/ui/themes/base/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  159. data/assets/js/jquery/ui/themes/base/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  160. data/assets/js/jquery/ui/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  161. data/assets/js/jquery/ui/themes/base/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  162. data/assets/js/jquery/ui/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  163. data/assets/js/jquery/ui/themes/base/images/ui-icons_222222_256x240.png +0 -0
  164. data/assets/js/jquery/ui/themes/base/images/ui-icons_2e83ff_256x240.png +0 -0
  165. data/assets/js/jquery/ui/themes/base/images/ui-icons_454545_256x240.png +0 -0
  166. data/assets/js/jquery/ui/themes/base/images/ui-icons_888888_256x240.png +0 -0
  167. data/assets/js/jquery/ui/themes/base/images/ui-icons_cd0a0a_256x240.png +0 -0
  168. data/assets/js/jquery/ui/themes/base/jquery.ui.accordion.css +19 -0
  169. data/assets/js/jquery/ui/themes/base/jquery.ui.all.css +11 -0
  170. data/assets/js/jquery/ui/themes/base/jquery.ui.autocomplete.css +53 -0
  171. data/assets/js/jquery/ui/themes/base/jquery.ui.base.css +11 -0
  172. data/assets/js/jquery/ui/themes/base/jquery.ui.button.css +38 -0
  173. data/assets/js/jquery/ui/themes/base/jquery.ui.core.css +41 -0
  174. data/assets/js/jquery/ui/themes/base/jquery.ui.datepicker.css +68 -0
  175. data/assets/js/jquery/ui/themes/base/jquery.ui.dialog.css +21 -0
  176. data/assets/js/jquery/ui/themes/base/jquery.ui.progressbar.css +11 -0
  177. data/assets/js/jquery/ui/themes/base/jquery.ui.resizable.css +20 -0
  178. data/assets/js/jquery/ui/themes/base/jquery.ui.selectable.css +10 -0
  179. data/assets/js/jquery/ui/themes/base/jquery.ui.slider.css +24 -0
  180. data/assets/js/jquery/ui/themes/base/jquery.ui.tabs.css +18 -0
  181. data/assets/js/jquery/ui/themes/base/jquery.ui.theme.css +252 -0
  182. data/assets/js/jquery/ui/themes/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  183. data/assets/js/jquery/ui/themes/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  184. data/assets/js/jquery/ui/themes/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  185. data/assets/js/jquery/ui/themes/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  186. data/assets/js/jquery/ui/themes/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  187. data/assets/js/jquery/ui/themes/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  188. data/assets/js/jquery/ui/themes/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  189. data/assets/js/jquery/ui/themes/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  190. data/assets/js/jquery/ui/themes/smoothness/images/ui-icons_222222_256x240.png +0 -0
  191. data/assets/js/jquery/ui/themes/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  192. data/assets/js/jquery/ui/themes/smoothness/images/ui-icons_454545_256x240.png +0 -0
  193. data/assets/js/jquery/ui/themes/smoothness/images/ui-icons_888888_256x240.png +0 -0
  194. data/assets/js/jquery/ui/themes/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  195. data/assets/js/jquery/ui/themes/smoothness/jquery-ui-1.8.6.custom.css +572 -0
  196. data/assets/js/jquery/ui/themes/smoothness/jquery.ui.accordion.css +19 -0
  197. data/assets/js/jquery/ui/themes/smoothness/jquery.ui.all.css +11 -0
  198. data/assets/js/jquery/ui/themes/smoothness/jquery.ui.autocomplete.css +53 -0
  199. data/assets/js/jquery/ui/themes/smoothness/jquery.ui.base.css +11 -0
  200. data/assets/js/jquery/ui/themes/smoothness/jquery.ui.button.css +38 -0
  201. data/assets/js/jquery/ui/themes/smoothness/jquery.ui.core.css +41 -0
  202. data/assets/js/jquery/ui/themes/smoothness/jquery.ui.datepicker.css +68 -0
  203. data/assets/js/jquery/ui/themes/smoothness/jquery.ui.dialog.css +21 -0
  204. data/assets/js/jquery/ui/themes/smoothness/jquery.ui.progressbar.css +11 -0
  205. data/assets/js/jquery/ui/themes/smoothness/jquery.ui.resizable.css +20 -0
  206. data/assets/js/jquery/ui/themes/smoothness/jquery.ui.selectable.css +10 -0
  207. data/assets/js/jquery/ui/themes/smoothness/jquery.ui.slider.css +24 -0
  208. data/assets/js/jquery/ui/themes/smoothness/jquery.ui.tabs.css +18 -0
  209. data/assets/js/jquery/ui/themes/smoothness/jquery.ui.theme.css +254 -0
  210. data/bin/alfa +15 -0
  211. data/lib/alfa/application.rb +36 -0
  212. data/lib/alfa/cli_application.rb +11 -3
  213. data/lib/alfa/commands/new.rb +4 -0
  214. data/lib/alfa/config.rb +11 -0
  215. data/lib/alfa/controller.rb +1 -1
  216. data/lib/alfa/database/mysql.rb +60 -8
  217. data/lib/alfa/database.rb +2 -1
  218. data/lib/alfa/logger.rb +38 -0
  219. data/lib/alfa/models/base.rb +1 -1
  220. data/lib/alfa/models/base_sql.rb +1 -1
  221. data/lib/alfa/models/dummy.rb +1 -1
  222. data/lib/alfa/models/mysql.rb +36 -26
  223. data/lib/alfa/models.rb +1 -1
  224. data/lib/alfa/query_logger.rb +29 -0
  225. data/lib/alfa/router.rb +155 -0
  226. data/lib/alfa/support.rb +58 -2
  227. data/lib/alfa/tfile.rb +97 -0
  228. data/lib/alfa/web_application.rb +106 -85
  229. data/lib/alfa.rb +1 -1
  230. data/lib/ruty/bugfix.rb +21 -0
  231. data/lib/ruty/tags/resources.rb +45 -2
  232. data/lib/ruty/upgrade.rb +61 -0
  233. data/test/data/test_router/config/routes.rb +4 -0
  234. data/test/test_alfa.rb +1 -52
  235. data/test/test_router.rb +132 -0
  236. data/test/test_support.rb +26 -0
  237. data/test/test_tfile.rb +186 -0
  238. metadata +259 -100
@@ -0,0 +1,1974 @@
1
+ /* http://keith-wood.name/datepick.html
2
+ Datepicker for jQuery 3.6.1.
3
+ Written by Marc Grabanski (m@marcgrabanski.com) and
4
+ Keith Wood (kbwood{at}iinet.com.au).
5
+ Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and
6
+ MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses.
7
+ Please attribute the authors if you use it. */
8
+
9
+ (function($) { // Hide the namespace
10
+
11
+ var PROP_NAME = 'datepick';
12
+
13
+ /* Date picker manager.
14
+ Use the singleton instance of this class, $.datepick, to interact with the date picker.
15
+ Settings for (groups of) date pickers are maintained in an instance object,
16
+ allowing multiple different settings on the same page. */
17
+
18
+ function Datepick() {
19
+ this._uuid = new Date().getTime(); // Unique identifier seed
20
+ this._curInst = null; // The current instance in use
21
+ this._keyEvent = false; // If the last event was a key event
22
+ this._disabledInputs = []; // List of date picker inputs that have been disabled
23
+ this._datepickerShowing = false; // True if the popup picker is showing , false if not
24
+ this._inDialog = false; // True if showing within a "dialog", false if not
25
+ this.regional = []; // Available regional settings, indexed by language code
26
+ this.regional[''] = { // Default regional settings
27
+ clearText: 'Clear', // Display text for clear link
28
+ clearStatus: 'Erase the current date', // Status text for clear link
29
+ closeText: 'Close', // Display text for close link
30
+ closeStatus: 'Close without change', // Status text for close link
31
+ prevText: '<Prev', // Display text for previous month link
32
+ prevStatus: 'Show the previous month', // Status text for previous month link
33
+ prevBigText: '<<', // Display text for previous year link
34
+ prevBigStatus: 'Show the previous year', // Status text for previous year link
35
+ nextText: 'Next>', // Display text for next month link
36
+ nextStatus: 'Show the next month', // Status text for next month link
37
+ nextBigText: '>>', // Display text for next year link
38
+ nextBigStatus: 'Show the next year', // Status text for next year link
39
+ currentText: 'Today', // Display text for current month link
40
+ currentStatus: 'Show the current month', // Status text for current month link
41
+ monthNames: ['January','February','March','April','May','June',
42
+ 'July','August','September','October','November','December'], // Names of months for drop-down and formatting
43
+ monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
44
+ monthStatus: 'Show a different month', // Status text for selecting a month
45
+ yearStatus: 'Show a different year', // Status text for selecting a year
46
+ weekHeader: 'Wk', // Header for the week of the year column
47
+ weekStatus: 'Week of the year', // Status text for the week of the year column
48
+ dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
49
+ dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
50
+ dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
51
+ dayStatus: 'Set DD as first week day', // Status text for the day of the week selection
52
+ dateStatus: 'Select DD, M d', // Status text for the date selection
53
+ dateFormat: 'mm/dd/yy', // See format options on parseDate
54
+ firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
55
+ initStatus: 'Select a date', // Initial Status text on opening
56
+ isRTL: false, // True if right-to-left language, false if left-to-right
57
+ showMonthAfterYear: false, // True if the year select precedes month, false for month then year
58
+ yearSuffix: '' // Additional text to append to the year in the month headers
59
+ };
60
+ this._defaults = { // Global defaults for all the date picker instances
61
+ showOn: 'focus', // 'focus' for popup on focus,
62
+ // 'button' for trigger button, or 'both' for either
63
+ showAnim: 'show', // Name of jQuery animation for popup
64
+ showOptions: {}, // Options for enhanced animations
65
+ duration: 'normal', // Duration of display/closure
66
+ buttonText: '...', // Text for trigger button
67
+ buttonImage: '', // URL for trigger button image
68
+ buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
69
+ defaultDate: null, // Used when field is blank: actual date,
70
+ // +/-number for offset from today, null for today
71
+ showDefault: false, // True to populate field with the default date
72
+ appendText: '', // Display text following the input box, e.g. showing the format
73
+ closeAtTop: true, // True to have the clear/close at the top,
74
+ // false to have them at the bottom
75
+ mandatory: false, // True to hide the Clear link, false to include it
76
+ hideIfNoPrevNext: false, // True to hide next/previous month links
77
+ // if not applicable, false to just disable them
78
+ navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
79
+ showBigPrevNext: false, // True to show big prev/next links
80
+ stepMonths: 1, // Number of months to step back/forward
81
+ stepBigMonths: 12, // Number of months to step back/forward for the big links
82
+ gotoCurrent: false, // True if today link goes back to current selection instead
83
+ changeMonth: true, // True if month can be selected directly, false if only prev/next
84
+ changeYear: true, // True if year can be selected directly, false if only prev/next
85
+ yearRange: '-10:+10', // Range of years to display in drop-down,
86
+ // either relative to current year (-nn:+nn) or absolute (nnnn:nnnn)
87
+ changeFirstDay: false, // True to click on day name to change, false to remain as set
88
+ showOtherMonths: false, // True to show dates in other months, false to leave blank
89
+ selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
90
+ highlightWeek: false, // True to highlight the selected week
91
+ showWeeks: false, // True to show week of the year, false to omit
92
+ calculateWeek: this.iso8601Week, // How to calculate the week of the year,
93
+ // takes a Date and returns the number of the week for it
94
+ shortYearCutoff: '+10', // Short year values < this are in the current century,
95
+ // > this are in the previous century, string value starting with '+'
96
+ // for current year + value, -1 for no change
97
+ showStatus: false, // True to show status bar at bottom, false to not show it
98
+ statusForDate: this.dateStatus, // Function to provide status text for a date -
99
+ // takes date and instance as parameters, returns display text
100
+ minDate: null, // The earliest selectable date, or null for no limit
101
+ maxDate: null, // The latest selectable date, or null for no limit
102
+ numberOfMonths: 1, // Number of months to show at a time
103
+ showCurrentAtPos: 0, // The position in multiple months at which to show the current month (starting at 0)
104
+ rangeSelect: false, // Allows for selecting a date range on one date picker
105
+ rangeSeparator: ' - ', // Text between two dates in a range
106
+ multiSelect: 0, // Maximum number of selectable dates
107
+ multiSeparator: ',', // Text between multiple dates
108
+ beforeShow: null, // Function that takes an input field and
109
+ // returns a set of custom settings for the date picker
110
+ beforeShowDay: null, // Function that takes a date and returns an array with
111
+ // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
112
+ // [2] = cell title (optional), e.g. $.datepick.noWeekends
113
+ onChangeMonthYear: null, // Define a callback function when the month or year is changed
114
+ onHover: null, // Define a callback function when hovering over a day
115
+ onSelect: null, // Define a callback function when a date is selected
116
+ onClose: null, // Define a callback function when the datepicker is closed
117
+ altField: '', // Selector for an alternate field to store selected dates into
118
+ altFormat: '', // The date format to use for the alternate field
119
+ constrainInput: true // The input is constrained by the current date format
120
+ };
121
+ $.extend(this._defaults, this.regional['']);
122
+ this.dpDiv = $('<div id="' + this._mainDivId + '" style="display: none;"></div>');
123
+ }
124
+
125
+ $.extend(Datepick.prototype, {
126
+ version: '3.6.0', // Current version
127
+
128
+ /* Class name added to elements to indicate already configured with a date picker. */
129
+ markerClassName: 'hasDatepick',
130
+
131
+ _mainDivId: 'datepick-div', // The ID of the main datepicker division
132
+ _inlineClass: 'datepick-inline', // The name of the inline marker class
133
+ _appendClass: 'datepick-append', // The name of the append marker class
134
+ _triggerClass: 'datepick-trigger', // The name of the trigger marker class
135
+ _dialogClass: 'datepick-dialog', // The name of the dialog marker class
136
+ _promptClass: 'datepick-prompt', // The name of the dialog prompt marker class
137
+ _disableClass: 'datepick-disabled', // The name of the disabled covering marker class
138
+ _oneMonthClass: 'datepick-one-month', // The name of the single month marker class
139
+ _unselectableClass: 'datepick-unselectable', // The name of the unselectable cell marker class
140
+ _currentClass: 'datepick-current-day', // The name of the current day marker class
141
+ _dayOverClass: 'datepick-days-cell-over', // The name of the day hover marker class
142
+ _weekOverClass: 'datepick-week-over', // The name of the week hover marker class
143
+ _coverClass: 'datepick-cover', // The name of the IE6- iframe marker class
144
+
145
+ /* Override the default settings for all instances of the date picker.
146
+ @param settings (object) the new settings to use as defaults (anonymous object)
147
+ @return (Datepick) the manager object */
148
+ setDefaults: function(settings) {
149
+ extendRemove(this._defaults, settings || {});
150
+ return this;
151
+ },
152
+
153
+ /* Attach the date picker to a jQuery selection.
154
+ @param target (element) the target input field or division or span
155
+ @param settings (object) the new settings to use for this date picker instance */
156
+ _attachDatepick: function(target, settings) {
157
+ // Check for settings on the control itself - in namespace 'date:'
158
+ var inlineSettings = null;
159
+ for (var attrName in this._defaults) {
160
+ var attrValue = target.getAttribute('date:' + attrName);
161
+ if (attrValue) {
162
+ inlineSettings = inlineSettings || {};
163
+ try {
164
+ inlineSettings[attrName] = eval(attrValue);
165
+ } catch (err) {
166
+ inlineSettings[attrName] = attrValue;
167
+ }
168
+ }
169
+ }
170
+ var nodeName = target.nodeName.toLowerCase();
171
+ var inline = (nodeName == 'div' || nodeName == 'span');
172
+ if (!target.id)
173
+ target.id = 'dp' + (++this._uuid);
174
+ var inst = this._newInst($(target), inline);
175
+ inst.settings = $.extend({}, settings || {}, inlineSettings || {});
176
+ if (nodeName == 'input')
177
+ this._connectDatepick(target, inst);
178
+ else if (inline)
179
+ this._inlineDatepick(target, inst);
180
+ },
181
+
182
+ /* Create a new instance object.
183
+ @param target (jQuery) the target input field or division or span
184
+ @param inline (boolean) true if this datepicker appears inline */
185
+ _newInst: function(target, inline) {
186
+ var id = target[0].id.replace(/([:\[\]\.])/g, '\\\\$1'); // Escape jQuery meta chars
187
+ return {id: id, input: target, // Associated target
188
+ cursorDate: this._daylightSavingAdjust(new Date()), // Current position
189
+ drawMonth: 0, drawYear: 0, // Month being drawn
190
+ dates: [], // Selected dates
191
+ inline: inline, // Is datepicker inline or not
192
+ dpDiv: (!inline ? this.dpDiv : // presentation div
193
+ $('<div class="' + this._inlineClass + '"></div>')),
194
+ siblings: $([])}; // Created siblings (trigger/append)
195
+ },
196
+
197
+ /* Attach the date picker to an input field.
198
+ @param target (element) the target input field or division or span
199
+ @param inst (object) the instance settings for this datepicker */
200
+ _connectDatepick: function(target, inst) {
201
+ var input = $(target);
202
+ if (input.hasClass(this.markerClassName))
203
+ return;
204
+ var appendText = this._get(inst, 'appendText');
205
+ var isRTL = this._get(inst, 'isRTL');
206
+ if (appendText) {
207
+ var append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
208
+ input[isRTL ? 'before' : 'after'](append);
209
+ inst.siblings = inst.siblings.add(append);
210
+ }
211
+ var showOn = this._get(inst, 'showOn');
212
+ if (showOn == 'focus' || showOn == 'both') // Pop-up date picker when in the marked field
213
+ input.focus(this._showDatepick);
214
+ if (showOn == 'button' || showOn == 'both') { // Pop-up date picker when button clicked
215
+ var buttonText = this._get(inst, 'buttonText');
216
+ var buttonImage = this._get(inst, 'buttonImage');
217
+ var trigger = $(this._get(inst, 'buttonImageOnly') ?
218
+ $('<img/>').addClass(this._triggerClass).
219
+ attr({src: buttonImage, alt: buttonText, title: buttonText}) :
220
+ $('<button type="button"></button>').addClass(this._triggerClass).
221
+ html(buttonImage == '' ? buttonText : $('<img/>').attr(
222
+ {src: buttonImage, alt: buttonText, title: buttonText})));
223
+ input[isRTL ? 'before' : 'after'](trigger);
224
+ inst.siblings = inst.siblings.add(trigger);
225
+ trigger.click(function() {
226
+ if ($.datepick._datepickerShowing && $.datepick._lastInput == target)
227
+ $.datepick._hideDatepick();
228
+ else
229
+ $.datepick._showDatepick(target);
230
+ return false;
231
+ });
232
+ }
233
+ input.addClass(this.markerClassName).keydown(this._doKeyDown).
234
+ keypress(this._doKeyPress).keyup(this._doKeyUp);
235
+ if (this._get(inst, 'showDefault') && !inst.input.val()) {
236
+ inst.dates = [this._getDefaultDate(inst)];
237
+ this._showDate(inst);
238
+ }
239
+ $.data(target, PROP_NAME, inst);
240
+ },
241
+
242
+ /* Attach an inline date picker to a div.
243
+ @param target (element) the target input field or division or span
244
+ @param inst (object) the instance settings for this datepicker */
245
+ _inlineDatepick: function(target, inst) {
246
+ var divSpan = $(target);
247
+ if (divSpan.hasClass(this.markerClassName))
248
+ return;
249
+ divSpan.addClass(this.markerClassName);
250
+ $.data(target, PROP_NAME, inst);
251
+ inst.drawMonth = inst.cursorDate.getMonth();
252
+ inst.drawYear = inst.cursorDate.getFullYear();
253
+ $('body').append(inst.dpDiv);
254
+ this._updateDatepick(inst);
255
+ // Fix width for dynamic number of date pickers
256
+ inst.dpDiv.width(this._getNumberOfMonths(inst)[1] *
257
+ $('.' + this._oneMonthClass, inst.dpDiv)[0].offsetWidth);
258
+ divSpan.append(inst.dpDiv);
259
+ this._updateAlternate(inst);
260
+ },
261
+
262
+ /* Pop-up the date picker in a "dialog" box.
263
+ @param input (element) ignored
264
+ @param dateText (string) the initial date to display (in the current format)
265
+ @param onSelect (function) the function(dateText) to call when a date is selected
266
+ @param settings (object) update the dialog date picker instance's settings (anonymous object)
267
+ @param pos (int[2]) coordinates for the dialog's position within the screen or
268
+ (event) with x/y coordinates or
269
+ leave empty for default (screen centre) */
270
+ _dialogDatepick: function(input, dateText, onSelect, settings, pos) {
271
+ var inst = this._dialogInst; // Internal instance
272
+ if (!inst) {
273
+ var id = 'dp' + (++this._uuid);
274
+ this._dialogInput = $('<input type="text" id="' + id +
275
+ '" size="1" style="position: absolute; top: -100px;"/>');
276
+ this._dialogInput.keydown(this._doKeyDown);
277
+ $('body').append(this._dialogInput);
278
+ inst = this._dialogInst = this._newInst(this._dialogInput, false);
279
+ inst.settings = {};
280
+ $.data(this._dialogInput[0], PROP_NAME, inst);
281
+ }
282
+ extendRemove(inst.settings, settings || {});
283
+ this._dialogInput.val(dateText);
284
+
285
+ this._pos = (pos ? (isArray(pos) ? pos : [pos.pageX, pos.pageY]) : null);
286
+ if (!this._pos) {
287
+ var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
288
+ var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
289
+ this._pos = // Should use actual width/height below
290
+ [(document.documentElement.clientWidth / 2) - 100 + scrollX,
291
+ (document.documentElement.clientHeight / 2) - 150 + scrollY];
292
+ }
293
+
294
+ // Move input on screen for focus, but hidden behind dialog
295
+ this._dialogInput.css('left', this._pos[0] + 'px').css('top', this._pos[1] + 'px');
296
+ inst.settings.onSelect = onSelect;
297
+ this._inDialog = true;
298
+ this.dpDiv.addClass(this._dialogClass);
299
+ this._showDatepick(this._dialogInput[0]);
300
+ if ($.blockUI)
301
+ $.blockUI(this.dpDiv);
302
+ $.data(this._dialogInput[0], PROP_NAME, inst);
303
+ },
304
+
305
+ /* Detach a datepicker from its control.
306
+ @param target (element) the target input field or division or span */
307
+ _destroyDatepick: function(target) {
308
+ var $target = $(target);
309
+ if (!$target.hasClass(this.markerClassName)) {
310
+ return;
311
+ }
312
+ var nodeName = target.nodeName.toLowerCase();
313
+ var inst = $.data(target, PROP_NAME);
314
+ $.removeData(target, PROP_NAME);
315
+ if (nodeName == 'input') {
316
+ $(inst.siblings).remove();
317
+ $target.removeClass(this.markerClassName).
318
+ unbind('focus', this._showDatepick).unbind('keydown', this._doKeyDown).
319
+ unbind('keypress', this._doKeyPress).unbind('keyup', this._doKeyUp);
320
+ }
321
+ else if (nodeName == 'div' || nodeName == 'span')
322
+ $target.removeClass(this.markerClassName).empty();
323
+ },
324
+
325
+ /* Enable the date picker to a jQuery selection.
326
+ @param target (element) the target input field or division or span */
327
+ _enableDatepick: function(target) {
328
+ var $target = $(target);
329
+ if (!$target.hasClass(this.markerClassName)) {
330
+ return;
331
+ }
332
+ var nodeName = target.nodeName.toLowerCase();
333
+ var inst = $.data(target, PROP_NAME);
334
+ if (nodeName == 'input') {
335
+ target.disabled = false;
336
+ inst.siblings.filter('button.' + this._triggerClass).
337
+ each(function() { this.disabled = false; }).end().
338
+ filter('img.' + this._triggerClass).
339
+ css({opacity: '1.0', cursor: ''});
340
+ }
341
+ else if (nodeName == 'div' || nodeName == 'span') {
342
+ $target.children('.' + this._disableClass).remove().end().
343
+ find('select').attr('disabled', '');
344
+ }
345
+ this._disabledInputs = $.map(this._disabledInputs,
346
+ function(value) { return (value == target ? null : value); }); // Delete entry
347
+ },
348
+
349
+ /* Disable the date picker to a jQuery selection.
350
+ @param target (element) the target input field or division or span */
351
+ _disableDatepick: function(target) {
352
+ var $target = $(target);
353
+ if (!$target.hasClass(this.markerClassName)) {
354
+ return;
355
+ }
356
+ var nodeName = target.nodeName.toLowerCase();
357
+ var inst = $.data(target, PROP_NAME);
358
+ if (nodeName == 'input') {
359
+ target.disabled = true;
360
+ inst.siblings.filter('button.' + this._triggerClass).
361
+ each(function() { this.disabled = true; }).end().
362
+ filter('img.' + this._triggerClass).
363
+ css({opacity: '0.5', cursor: 'default'});
364
+ }
365
+ else if (nodeName == 'div' || nodeName == 'span') {
366
+ var inline = $target.children('.' + this._inlineClass);
367
+ var offset = inline.offset();
368
+ var relOffset = {left: 0, top: 0};
369
+ inline.parents().each(function() {
370
+ if ($(this).css('position') == 'relative') {
371
+ relOffset = $(this).offset();
372
+ return false;
373
+ }
374
+ });
375
+ $target.prepend('<div class="' + this._disableClass + '" style="' +
376
+ 'width: ' + inline.width() + 'px; height: ' + inline.height() +
377
+ 'px; left: ' + (offset.left - relOffset.left) +
378
+ 'px; top: ' + (offset.top - relOffset.top) + 'px;"></div>').
379
+ find('select').attr('disabled', 'disabled');
380
+ }
381
+ this._disabledInputs = $.map(this._disabledInputs,
382
+ function(value) { return (value == target ? null : value); }); // Delete entry
383
+ this._disabledInputs.push(target);
384
+ },
385
+
386
+ /* Is the first field in a jQuery collection disabled as a datepicker?
387
+ @param target (element) the target input field or division or span
388
+ @return (boolean) true if disabled, false if enabled */
389
+ _isDisabledDatepick: function(target) {
390
+ return (!target ? false : $.inArray(target, this._disabledInputs) > -1);
391
+ },
392
+
393
+ /* Retrieve the instance data for the target control.
394
+ @param target (element) the target input field or division or span
395
+ @return (object) the associated instance data
396
+ @throws error if a jQuery problem getting data */
397
+ _getInst: function(target) {
398
+ try {
399
+ return $.data(target, PROP_NAME);
400
+ }
401
+ catch (err) {
402
+ throw 'Missing instance data for this datepicker';
403
+ }
404
+ },
405
+
406
+ /* Update or retrieve the settings for a date picker attached to an input field or division.
407
+ @param target (element) the target input field or division or span
408
+ @param name (object) the new settings to update or
409
+ (string) the name of the setting to change or retrieve,
410
+ when retrieving also 'all' for all instance settings or
411
+ 'defaults' for all global defaults
412
+ @param value (any) the new value for the setting
413
+ (omit if above is an object or to retrieve value) */
414
+ _optionDatepick: function(target, name, value) {
415
+ var inst = this._getInst(target);
416
+ if (arguments.length == 2 && typeof name == 'string') {
417
+ return (name == 'defaults' ? $.extend({}, $.datepick._defaults) :
418
+ (inst ? (name == 'all' ? $.extend({}, inst.settings) :
419
+ this._get(inst, name)) : null));
420
+ }
421
+ var settings = name || {};
422
+ if (typeof name == 'string') {
423
+ settings = {};
424
+ settings[name] = value;
425
+ }
426
+ if (inst) {
427
+ if (this._curInst == inst) {
428
+ this._hideDatepick(null);
429
+ }
430
+ var dates = this._getDateDatepick(target);
431
+ extendRemove(inst.settings, settings);
432
+ extendRemove(inst, {dates: []});
433
+ var blank = (!dates || isArray(dates));
434
+ if (isArray(dates))
435
+ for (var i = 0; i < dates.length; i++)
436
+ if (dates[i]) {
437
+ blank = false;
438
+ break;
439
+ }
440
+ if (!blank)
441
+ this._setDateDatepick(target, dates);
442
+ this._updateDatepick(inst);
443
+ }
444
+ },
445
+
446
+ // Change method deprecated
447
+ _changeDatepick: function(target, name, value) {
448
+ this._optionDatepick(target, name, value);
449
+ },
450
+
451
+ /* Redraw the date picker attached to an input field or division.
452
+ @param target (element) the target input field or division or span */
453
+ _refreshDatepick: function(target) {
454
+ var inst = this._getInst(target);
455
+ if (inst) {
456
+ this._updateDatepick(inst);
457
+ }
458
+ },
459
+
460
+ /* Set the dates for a jQuery selection.
461
+ @param target (element) the target input field or division or span
462
+ @param date (Date) the new date
463
+ @param endDate (Date) the new end date for a range (optional) */
464
+ _setDateDatepick: function(target, date, endDate) {
465
+ var inst = this._getInst(target);
466
+ if (inst) {
467
+ this._setDate(inst, date, endDate);
468
+ this._updateDatepick(inst);
469
+ this._updateAlternate(inst);
470
+ }
471
+ },
472
+
473
+ /* Get the date(s) for the first entry in a jQuery selection.
474
+ @param target (element) the target input field or division or span
475
+ @return (Date) the current date or
476
+ (Date[2]) the current dates for a range */
477
+ _getDateDatepick: function(target) {
478
+ var inst = this._getInst(target);
479
+ if (inst && !inst.inline)
480
+ this._setDateFromField(inst);
481
+ return (inst ? this._getDate(inst) : null);
482
+ },
483
+
484
+ /* Handle keystrokes.
485
+ @param event (KeyEvent) the keystroke details
486
+ @return (boolean) true to continue, false to discard */
487
+ _doKeyDown: function(event) {
488
+ var inst = $.datepick._getInst(event.target);
489
+ inst._keyEvent = true;
490
+ var handled = true;
491
+ var isRTL = $.datepick._get(inst, 'isRTL');
492
+ if ($.datepick._datepickerShowing)
493
+ switch (event.keyCode) {
494
+ case 9: $.datepick._hideDatepick(null, '');
495
+ break; // Hide on tab out
496
+ case 13: var sel = $('td.' + $.datepick._dayOverClass, inst.dpDiv);
497
+ if (sel.length == 0)
498
+ sel = $('td.' + $.datepick._currentClass + ':first', inst.dpDiv);
499
+ if (sel[0])
500
+ $.datepick._selectDay(event.target, inst.cursorDate.getTime(), sel[0]);
501
+ else
502
+ $.datepick._hideDatepick(null, $.datepick._get(inst, 'duration'));
503
+ break; // Select the value on enter
504
+ case 27: $.datepick._hideDatepick(null, $.datepick._get(inst, 'duration'));
505
+ break; // Hide on escape
506
+ case 33: $.datepick._adjustDate(event.target, (event.ctrlKey ?
507
+ -$.datepick._get(inst, 'stepBigMonths') :
508
+ -$.datepick._get(inst, 'stepMonths')), 'M');
509
+ break; // Previous month/year on page up/+ ctrl
510
+ case 34: $.datepick._adjustDate(event.target, (event.ctrlKey ?
511
+ +$.datepick._get(inst, 'stepBigMonths') :
512
+ +$.datepick._get(inst, 'stepMonths')), 'M');
513
+ break; // Next month/year on page down/+ ctrl
514
+ case 35: if (event.ctrlKey || event.metaKey)
515
+ $.datepick._clearDate(event.target);
516
+ handled = event.ctrlKey || event.metaKey;
517
+ break; // Clear on ctrl or command + end
518
+ case 36: if (event.ctrlKey || event.metaKey)
519
+ $.datepick._gotoToday(event.target);
520
+ handled = event.ctrlKey || event.metaKey;
521
+ break; // Current on ctrl or command + home
522
+ case 37: if (event.ctrlKey || event.metaKey)
523
+ $.datepick._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
524
+ handled = event.ctrlKey || event.metaKey;
525
+ // -1 day on ctrl or command + left
526
+ if (event.originalEvent.altKey)
527
+ $.datepick._adjustDate(event.target,
528
+ (event.ctrlKey ? -$.datepick._get(inst, 'stepBigMonths') :
529
+ -$.datepick._get(inst, 'stepMonths')), 'M');
530
+ // Next month/year on alt + left/+ ctrl
531
+ break;
532
+ case 38: if (event.ctrlKey || event.metaKey)
533
+ $.datepick._adjustDate(event.target, -7, 'D');
534
+ handled = event.ctrlKey || event.metaKey;
535
+ break; // -1 week on ctrl or command + up
536
+ case 39: if (event.ctrlKey || event.metaKey)
537
+ $.datepick._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
538
+ handled = event.ctrlKey || event.metaKey;
539
+ // +1 day on ctrl or command + right
540
+ if (event.originalEvent.altKey)
541
+ $.datepick._adjustDate(event.target,
542
+ (event.ctrlKey ? +$.datepick._get(inst, 'stepBigMonths') :
543
+ +$.datepick._get(inst, 'stepMonths')), 'M');
544
+ // Next month/year on alt + right/+ ctrl
545
+ break;
546
+ case 40: if (event.ctrlKey || event.metaKey)
547
+ $.datepick._adjustDate(event.target, +7, 'D');
548
+ handled = event.ctrlKey || event.metaKey;
549
+ break; // +1 week on ctrl or command + down
550
+ default: handled = false;
551
+ }
552
+ else if (event.keyCode == 36 && event.ctrlKey) // Display the date picker on ctrl+home
553
+ $.datepick._showDatepick(this);
554
+ else
555
+ handled = false;
556
+ if (handled) {
557
+ event.preventDefault();
558
+ event.stopPropagation();
559
+ }
560
+ return !handled;
561
+ },
562
+
563
+ /* Filter entered characters - based on date format.
564
+ @param event (KeyEvent) the keystroke details
565
+ @return (boolean) true to continue, false to discard */
566
+ _doKeyPress: function(event) {
567
+ var inst = $.datepick._getInst(event.target);
568
+ if ($.datepick._get(inst, 'constrainInput')) {
569
+ var chars = $.datepick._possibleChars(inst);
570
+ var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
571
+ return event.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
572
+ }
573
+ },
574
+
575
+ /* Synchronise manual entry and field/alternate field.
576
+ @param event (KeyEvent) the keystroke details
577
+ @return (boolean) true to continue */
578
+ _doKeyUp: function(event) {
579
+ var inst = $.datepick._getInst(event.target);
580
+ try {
581
+ var separator = ($.datepick._get(inst, 'rangeSelect') ?
582
+ $.datepick._get(inst, 'rangeSeparator') :
583
+ ($.datepick._get(inst, 'multiSelect') ?
584
+ $.datepick._get(inst, 'multiSeparator') : ''));
585
+ var dates = (inst.input ? inst.input.val() : '');
586
+ dates = (separator ? dates.split(separator) : [dates]);
587
+ var ok = true;
588
+ for (var i = 0; i < dates.length; i++) {
589
+ if (!$.datepick.parseDate($.datepick._get(inst, 'dateFormat'),
590
+ dates[i], $.datepick._getFormatConfig(inst))) {
591
+ ok = false;
592
+ break;
593
+ }
594
+ }
595
+ if (ok) { // Only if valid
596
+ $.datepick._setDateFromField(inst);
597
+ $.datepick._updateAlternate(inst);
598
+ $.datepick._updateDatepick(inst);
599
+ }
600
+ }
601
+ catch (event) {
602
+ // Ignore
603
+ }
604
+ return true;
605
+ },
606
+
607
+ /* Extract all possible characters from the date format.
608
+ @param inst (object) the instance settings for this datepicker
609
+ @return (string) the set of characters allowed by this format */
610
+ _possibleChars: function (inst) {
611
+ var dateFormat = $.datepick._get(inst, 'dateFormat');
612
+ var chars = ($.datepick._get(inst, 'rangeSelect') ?
613
+ $.datepick._get(inst, 'rangeSeparator') :
614
+ ($.datepick._get(inst, 'multiSelect') ?
615
+ $.datepick._get(inst, 'multiSeparator') : ''));
616
+ var literal = false;
617
+ for (var iFormat = 0; iFormat < dateFormat.length; iFormat++)
618
+ if (literal)
619
+ if (dateFormat.charAt(iFormat) == "'" && !lookAhead("'"))
620
+ literal = false;
621
+ else
622
+ chars += dateFormat.charAt(iFormat);
623
+ else
624
+ switch (dateFormat.charAt(iFormat)) {
625
+ case 'd': case 'm': case 'y': case '@':
626
+ chars += '0123456789';
627
+ break;
628
+ case 'D': case 'M':
629
+ return null; // Accept anything
630
+ case "'":
631
+ if (lookAhead("'"))
632
+ chars += "'";
633
+ else
634
+ literal = true;
635
+ break;
636
+ default:
637
+ chars += dateFormat.charAt(iFormat);
638
+ }
639
+ return chars;
640
+ },
641
+
642
+ /* Pop-up the date picker for a given input field.
643
+ @param input (element) the input field attached to the date picker or
644
+ (event) if triggered by focus */
645
+ _showDatepick: function(input) {
646
+ input = input.target || input;
647
+ if (input.nodeName.toLowerCase() != 'input') // Find from button/image trigger
648
+ input = $('input', input.parentNode)[0];
649
+ if ($.datepick._isDisabledDatepick(input) || $.datepick._lastInput == input) // Already here
650
+ return;
651
+ var inst = $.datepick._getInst(input);
652
+ var beforeShow = $.datepick._get(inst, 'beforeShow');
653
+ extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
654
+ $.datepick._hideDatepick(null, '');
655
+ $.datepick._lastInput = input;
656
+ $.datepick._setDateFromField(inst);
657
+ if ($.datepick._inDialog) // Hide cursor
658
+ input.value = '';
659
+ if (!$.datepick._pos) { // Position below input
660
+ $.datepick._pos = $.datepick._findPos(input);
661
+ $.datepick._pos[1] += input.offsetHeight; // Add the height
662
+ }
663
+ var isFixed = false;
664
+ $(input).parents().each(function() {
665
+ isFixed |= $(this).css('position') == 'fixed';
666
+ return !isFixed;
667
+ });
668
+ if (isFixed && $.browser.opera) { // Correction for Opera when fixed and scrolled
669
+ $.datepick._pos[0] -= document.documentElement.scrollLeft;
670
+ $.datepick._pos[1] -= document.documentElement.scrollTop;
671
+ }
672
+ var offset = {left: $.datepick._pos[0], top: $.datepick._pos[1]};
673
+ $.datepick._pos = null;
674
+ // Determine sizing offscreen
675
+ inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
676
+ $.datepick._updateDatepick(inst);
677
+ // Fix width for dynamic number of date pickers
678
+ inst.dpDiv.width($.datepick._getNumberOfMonths(inst)[1] *
679
+ $('.' + $.datepick._oneMonthClass, inst.dpDiv).width());
680
+ // And adjust position before showing
681
+ offset = $.datepick._checkOffset(inst, offset, isFixed);
682
+ inst.dpDiv.css({position: ($.datepick._inDialog && $.blockUI ?
683
+ 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
684
+ left: offset.left + 'px', top: offset.top + 'px'});
685
+ if (!inst.inline) {
686
+ var showAnim = $.datepick._get(inst, 'showAnim') || 'show';
687
+ var duration = $.datepick._get(inst, 'duration');
688
+ var postProcess = function() {
689
+ $.datepick._datepickerShowing = true;
690
+ var borders = $.datepick._getBorders(inst.dpDiv);
691
+ inst.dpDiv.find('iframe.' + $.datepick._coverClass). // IE6- only
692
+ css({left: -borders[0], top: -borders[1],
693
+ width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
694
+ };
695
+ if ($.effects && $.effects[showAnim])
696
+ inst.dpDiv.show(showAnim, $.datepick._get(inst, 'showOptions'), duration, postProcess);
697
+ else
698
+ inst.dpDiv[showAnim](duration, postProcess);
699
+ if (duration == '')
700
+ postProcess();
701
+ if (inst.input[0].type != 'hidden')
702
+ inst.input.focus();
703
+ $.datepick._curInst = inst;
704
+ }
705
+ },
706
+
707
+ /* Generate the date picker content.
708
+ @param inst (object) the instance settings for this datepicker */
709
+ _updateDatepick: function(inst) {
710
+ var borders = this._getBorders(inst.dpDiv);
711
+ inst.dpDiv.empty().append(this._generateHTML(inst)).
712
+ find('iframe.' + this._coverClass). // IE6- only
713
+ css({left: -borders[0], top: -borders[1],
714
+ width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
715
+ var numMonths = this._getNumberOfMonths(inst);
716
+ inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ?
717
+ 'add' : 'remove') + 'Class']('datepick-multi');
718
+ inst.dpDiv[(this._get(inst, 'isRTL') ?
719
+ 'add' : 'remove') + 'Class']('datepick-rtl');
720
+ if (inst.input && inst.input[0].type != 'hidden' && inst == $.datepick._curInst)
721
+ $(inst.input).focus();
722
+ },
723
+
724
+ /* Retrieve the size of left and top borders for an element.
725
+ @param elem (jQuery object) the element of interest
726
+ @return (number[2]) the left and top borders */
727
+ _getBorders: function(elem) {
728
+ var convert = function(value) {
729
+ var extra = ($.browser.msie ? 1 : 0);
730
+ return {thin: 1 + extra, medium: 3 + extra, thick: 5 + extra}[value] || value;
731
+ };
732
+ return [parseFloat(convert(elem.css('border-left-width'))),
733
+ parseFloat(convert(elem.css('border-top-width')))];
734
+ },
735
+
736
+ /* Check positioning to remain on the screen.
737
+ @param inst (object) the instance settings for this datepicker
738
+ @param offset (object) the offset of the attached field
739
+ @param isFixed (boolean) true if control or a parent is 'fixed' in position
740
+ @return (object) the updated offset for the datepicker */
741
+ _checkOffset: function(inst, offset, isFixed) {
742
+ var pos = inst.input ? this._findPos(inst.input[0]) : null;
743
+ var browserWidth = document.documentElement.clientWidth;
744
+ var browserHeight = document.documentElement.clientHeight;
745
+ if (browserWidth == 0)
746
+ return offset;
747
+ var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
748
+ var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
749
+ // Reposition date picker horizontally if outside the browser window
750
+ if (this._get(inst, 'isRTL') ||
751
+ (offset.left + inst.dpDiv.outerWidth() - scrollX) > browserWidth)
752
+ offset.left = Math.max((isFixed ? 0 : scrollX),
753
+ pos[0] + (inst.input ? inst.input.outerWidth() : 0) -
754
+ (isFixed ? scrollX : 0) - inst.dpDiv.outerWidth() -
755
+ (isFixed && $.browser.opera ? document.documentElement.scrollLeft : 0));
756
+ else
757
+ offset.left -= (isFixed ? scrollX : 0);
758
+ // Reposition date picker vertically if outside the browser window
759
+ if ((offset.top + inst.dpDiv.outerHeight() - scrollY) > browserHeight)
760
+ offset.top = Math.max((isFixed ? 0 : scrollY),
761
+ pos[1] - (isFixed ? scrollY : 0) -
762
+ (this._inDialog ? 0 : inst.dpDiv.outerHeight()) -
763
+ (isFixed && $.browser.opera ? document.documentElement.scrollTop : 0));
764
+ else
765
+ offset.top -= (isFixed ? scrollY : 0);
766
+ return offset;
767
+ },
768
+
769
+ /* Find an element's position on the screen.
770
+ @param elem (element) the element to check
771
+ @return (number[2]) the x- and y-coordinates for the object */
772
+ _findPos: function(elem) {
773
+ while (elem && (elem.type == 'hidden' || elem.nodeType != 1)) {
774
+ elem = elem.nextSibling;
775
+ }
776
+ var position = $(elem).offset();
777
+ return [position.left, position.top];
778
+ },
779
+
780
+ /* Hide the date picker from view.
781
+ @param input (element) the input field attached to the date picker
782
+ @param duration (string) the duration over which to close the date picker */
783
+ _hideDatepick: function(input, duration) {
784
+ var inst = this._curInst;
785
+ if (!inst || (input && inst != $.data(input, PROP_NAME)))
786
+ return false;
787
+ var rangeSelect = this._get(inst, 'rangeSelect');
788
+ if (rangeSelect && inst.stayOpen)
789
+ this._updateInput('#' + inst.id);
790
+ inst.stayOpen = false;
791
+ if (this._datepickerShowing) {
792
+ duration = (duration != null ? duration : this._get(inst, 'duration'));
793
+ var showAnim = this._get(inst, 'showAnim');
794
+ var postProcess = function() {
795
+ $.datepick._tidyDialog(inst);
796
+ };
797
+ if (duration != '' && $.effects && $.effects[showAnim])
798
+ inst.dpDiv.hide(showAnim, $.datepick._get(inst, 'showOptions'),
799
+ duration, postProcess);
800
+ else
801
+ inst.dpDiv[(duration == '' ? 'hide' : (showAnim == 'slideDown' ? 'slideUp' :
802
+ (showAnim == 'fadeIn' ? 'fadeOut' : 'hide')))](duration, postProcess);
803
+ if (duration == '')
804
+ this._tidyDialog(inst);
805
+ var onClose = this._get(inst, 'onClose');
806
+ if (onClose) // Trigger custom callback
807
+ onClose.apply((inst.input ? inst.input[0] : null),
808
+ [(inst.input ? inst.input.val() : ''), this._getDate(inst), inst]);
809
+ this._datepickerShowing = false;
810
+ this._lastInput = null;
811
+ inst.settings.prompt = null;
812
+ if (this._inDialog) {
813
+ this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
814
+ if ($.blockUI) {
815
+ $.unblockUI();
816
+ $('body').append(this.dpDiv);
817
+ }
818
+ }
819
+ this._inDialog = false;
820
+ }
821
+ this._curInst = null;
822
+ return false;
823
+ },
824
+
825
+ /* Tidy up after a dialog display.
826
+ @param inst (object) the instance settings for this datepicker */
827
+ _tidyDialog: function(inst) {
828
+ inst.dpDiv.removeClass(this._dialogClass).unbind('.datepick');
829
+ $('.' + this._promptClass, inst.dpDiv).remove();
830
+ },
831
+
832
+ /* Close date picker if clicked elsewhere.
833
+ @param event (MouseEvent) the mouse click to check */
834
+ _checkExternalClick: function(event) {
835
+ if (!$.datepick._curInst)
836
+ return;
837
+ var $target = $(event.target);
838
+ if (!$target.parents().andSelf().is('#' + $.datepick._mainDivId) &&
839
+ !$target.hasClass($.datepick.markerClassName) &&
840
+ !$target.parents().andSelf().hasClass($.datepick._triggerClass) &&
841
+ $.datepick._datepickerShowing && !($.datepick._inDialog && $.blockUI))
842
+ $.datepick._hideDatepick(null, '');
843
+ },
844
+
845
+ /* Adjust one of the date sub-fields.
846
+ @param id (string) the ID of the target field
847
+ @param offset (number) the amount to change by
848
+ @param period (string) 'D' for days, 'M' for months, 'Y' for years */
849
+ _adjustDate: function(id, offset, period) {
850
+ var inst = this._getInst($(id)[0]);
851
+ this._adjustInstDate(inst, offset +
852
+ (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // Undo positioning
853
+ period);
854
+ this._updateDatepick(inst);
855
+ return false;
856
+ },
857
+
858
+ /* Show the month for today or the current selection.
859
+ @param id (string) the ID of the target field */
860
+ _gotoToday: function(id) {
861
+ var target = $(id);
862
+ var inst = this._getInst(target[0]);
863
+ if (this._get(inst, 'gotoCurrent') && inst.dates[0])
864
+ inst.cursorDate = new Date(inst.dates[0].getTime());
865
+ else
866
+ inst.cursorDate = this._daylightSavingAdjust(new Date());
867
+ inst.drawMonth = inst.cursorDate.getMonth();
868
+ inst.drawYear = inst.cursorDate.getFullYear();
869
+ this._notifyChange(inst);
870
+ this._adjustDate(target);
871
+ return false;
872
+ },
873
+
874
+ /* Selecting a new month/year.
875
+ @param id (string) the ID of the target field
876
+ @param select (element) the select being chosen from
877
+ @param period (string) 'M' for month, 'Y' for year */
878
+ _selectMonthYear: function(id, select, period) {
879
+ var target = $(id);
880
+ var inst = this._getInst(target[0]);
881
+ inst._selectingMonthYear = false;
882
+ var value = parseInt(select.options[select.selectedIndex].value, 10);
883
+ inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
884
+ inst['draw' + (period == 'M' ? 'Month' : 'Year')] = value;
885
+ inst.cursorDate.setDate(Math.min(inst.cursorDate.getDate(),
886
+ $.datepick._getDaysInMonth(inst.drawYear, inst.drawMonth)));
887
+ inst.cursorDate['set' + (period == 'M' ? 'Month' : 'FullYear')](value);
888
+ this._notifyChange(inst);
889
+ this._adjustDate(target);
890
+ },
891
+
892
+ /* Restore input focus after not changing month/year.
893
+ @param id (string) the ID of the target field */
894
+ _clickMonthYear: function(id) {
895
+ var inst = this._getInst($(id)[0]);
896
+ if (inst.input && inst._selectingMonthYear && !$.browser.msie)
897
+ inst.input.focus();
898
+ inst._selectingMonthYear = !inst._selectingMonthYear;
899
+ },
900
+
901
+ /* Action for changing the first week day.
902
+ @param id (string) the ID of the target field
903
+ @param day (number) the number of the first day, 0 = Sun, 1 = Mon, ... */
904
+ _changeFirstDay: function(id, day) {
905
+ var inst = this._getInst($(id)[0]);
906
+ inst.settings.firstDay = day;
907
+ this._updateDatepick(inst);
908
+ return false;
909
+ },
910
+
911
+ /* Hover over a particular day.
912
+ @param id (string) the ID of the target field
913
+ @param year (number) the year for this day
914
+ @param month (number) the month for this day
915
+ @param td (element) the table cell containing the selection */
916
+ _doHover: function(id, year, month, td) {
917
+ if ($(td).hasClass(this._unselectableClass))
918
+ return;
919
+ var inst = this._getInst($(id)[0]);
920
+ var onHover = this._get(inst, 'onHover');
921
+ var date = (year ?
922
+ this._daylightSavingAdjust(new Date(year, month, $(td).text())) : null);
923
+ onHover.apply((inst.input ? inst.input[0] : null),
924
+ [(date ? this._formatDate(inst, date) : ''), date, inst]);
925
+ },
926
+
927
+ /* Select a particular day.
928
+ @param id (string) the ID of the target field
929
+ @param timestamp (number) the timestamp for this day
930
+ @param td (element) the table cell containing the selection */
931
+ _selectDay: function(id, timestamp, td) {
932
+ if ($(td).hasClass(this._unselectableClass))
933
+ return false;
934
+ var inst = this._getInst($(id)[0]);
935
+ var rangeSelect = this._get(inst, 'rangeSelect');
936
+ var multiSelect = this._get(inst, 'multiSelect');
937
+ if (rangeSelect)
938
+ inst.stayOpen = !inst.stayOpen;
939
+ else if (multiSelect)
940
+ inst.stayOpen = true;
941
+ if (inst.stayOpen) {
942
+ $('.datepick td', inst.dpDiv).removeClass(this._currentClass);
943
+ $(td).addClass(this._currentClass);
944
+ }
945
+ inst.cursorDate = this._daylightSavingAdjust(new Date(timestamp));
946
+ var date = new Date(inst.cursorDate.getTime());
947
+ if (rangeSelect && !inst.stayOpen)
948
+ inst.dates[1] = date;
949
+ else if (multiSelect) {
950
+ var pos = -1;
951
+ for (var i = 0; i < inst.dates.length; i++)
952
+ if (inst.dates[i] && date.getTime() == inst.dates[i].getTime()) {
953
+ pos = i;
954
+ break;
955
+ }
956
+ if (pos > -1)
957
+ inst.dates.splice(pos, 1);
958
+ else if (inst.dates.length < multiSelect) {
959
+ if (inst.dates[0])
960
+ inst.dates.push(date);
961
+ else
962
+ inst.dates = [date];
963
+ inst.stayOpen = (inst.dates.length != multiSelect);
964
+ }
965
+ }
966
+ else
967
+ inst.dates = [date];
968
+ this._updateInput(id);
969
+ if (inst.stayOpen)
970
+ this._updateDatepick(inst);
971
+ else if ((rangeSelect || multiSelect) && inst.inline)
972
+ this._updateDatepick(inst);
973
+ return false;
974
+ },
975
+
976
+ /* Erase the input field and hide the date picker.
977
+ @param id (string) the ID of the target field */
978
+ _clearDate: function(id) {
979
+ var target = $(id);
980
+ var inst = this._getInst(target[0]);
981
+ if (this._get(inst, 'mandatory'))
982
+ return false;
983
+ inst.stayOpen = false;
984
+ inst.dates = (this._get(inst, 'showDefault') ?
985
+ [this._getDefaultDate(inst)] : []);
986
+ this._updateInput(target);
987
+ return false;
988
+ },
989
+
990
+ /* Update the input field with the selected date.
991
+ @param id (string) the ID of the target field or
992
+ (element) the target object */
993
+ _updateInput: function(id) {
994
+ var inst = this._getInst($(id)[0]);
995
+ var dateStr = this._showDate(inst);
996
+ this._updateAlternate(inst);
997
+ var onSelect = this._get(inst, 'onSelect');
998
+ if (onSelect)
999
+ onSelect.apply((inst.input ? inst.input[0] : null),
1000
+ [dateStr, this._getDate(inst), inst]); // Trigger custom callback
1001
+ else if (inst.input)
1002
+ inst.input.trigger('change'); // Fire the change event
1003
+ if (inst.inline)
1004
+ this._updateDatepick(inst);
1005
+ else if (!inst.stayOpen) {
1006
+ this._hideDatepick(null, this._get(inst, 'duration'));
1007
+ this._lastInput = inst.input[0];
1008
+ if (typeof(inst.input[0]) != 'object')
1009
+ inst.input.focus(); // Restore focus
1010
+ this._lastInput = null;
1011
+ }
1012
+ return false;
1013
+ },
1014
+
1015
+ /* Update the input field with the current date(s).
1016
+ @param inst (object) the instance settings for this datepicker
1017
+ @return (string) the formatted date(s) */
1018
+ _showDate: function(inst) {
1019
+ var dateStr = '';
1020
+ if (inst.input) {
1021
+ dateStr = (inst.dates.length == 0 ? '' : this._formatDate(inst, inst.dates[0]));
1022
+ if (dateStr) {
1023
+ if (this._get(inst, 'rangeSelect'))
1024
+ dateStr += this._get(inst, 'rangeSeparator') +
1025
+ this._formatDate(inst, inst.dates[1] || inst.dates[0]);
1026
+ else if (this._get(inst, 'multiSelect'))
1027
+ for (var i = 1; i < inst.dates.length; i++)
1028
+ dateStr += this._get(inst, 'multiSeparator') +
1029
+ this._formatDate(inst, inst.dates[i]);
1030
+ }
1031
+ inst.input.val(dateStr);
1032
+ }
1033
+ return dateStr;
1034
+ },
1035
+
1036
+ /* Update any alternate field to synchronise with the main field.
1037
+ @param inst (object) the instance settings for this datepicker */
1038
+ _updateAlternate: function(inst) {
1039
+ var altField = this._get(inst, 'altField');
1040
+ if (altField) { // Update alternate field too
1041
+ var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
1042
+ var settings = this._getFormatConfig(inst);
1043
+ var dateStr = this.formatDate(altFormat, inst.dates[0], settings);
1044
+ if (dateStr && this._get(inst, 'rangeSelect'))
1045
+ dateStr += this._get(inst, 'rangeSeparator') + this.formatDate(
1046
+ altFormat, inst.dates[1] || inst.dates[0], settings);
1047
+ else if (this._get(inst, 'multiSelect'))
1048
+ for (var i = 1; i < inst.dates.length; i++)
1049
+ dateStr += this._get(inst, 'multiSeparator') +
1050
+ this.formatDate(altFormat, inst.dates[i], settings);
1051
+ $(altField).val(dateStr);
1052
+ }
1053
+ },
1054
+
1055
+ /* Set as beforeShowDay function to prevent selection of weekends.
1056
+ @param date (Date) the date to customise
1057
+ @return ([boolean, string]) is this date selectable?, what is its CSS class? */
1058
+ noWeekends: function(date) {
1059
+ return [(date.getDay() || 7) < 6, ''];
1060
+ },
1061
+
1062
+ /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
1063
+ @param date (Date) the date to get the week for
1064
+ @return (number) the number of the week within the year that contains this date */
1065
+ iso8601Week: function(date) {
1066
+ var checkDate = new Date(date.getTime());
1067
+ // Find Thursday of this week starting on Monday
1068
+ checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
1069
+ var time = checkDate.getTime();
1070
+ checkDate.setMonth(0); // Compare with Jan 1
1071
+ checkDate.setDate(1);
1072
+ return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
1073
+ },
1074
+
1075
+ /* Provide status text for a particular date.
1076
+ @param date (Date) the date to get the status for
1077
+ @param inst (object) the current datepicker instance
1078
+ @return (string) the status display text for this date */
1079
+ dateStatus: function(date, inst) {
1080
+ return $.datepick.formatDate($.datepick._get(inst, 'dateStatus'),
1081
+ date, $.datepick._getFormatConfig(inst));
1082
+ },
1083
+
1084
+ /* Parse a string value into a date object.
1085
+ See formatDate below for the possible formats.
1086
+ @param format (string) the expected format of the date
1087
+ @param value (string) the date in the above format
1088
+ @param settings (object) attributes include:
1089
+ shortYearCutoff (number) the cutoff year for determining the century (optional)
1090
+ dayNamesShort (string[7]) abbreviated names of the days from Sunday (optional)
1091
+ dayNames (string[7]) names of the days from Sunday (optional)
1092
+ monthNamesShort (string[12]) abbreviated names of the months (optional)
1093
+ monthNames (string[12]) names of the months (optional)
1094
+ @return (Date) the extracted date value or null if value is blank */
1095
+ parseDate: function (format, value, settings) {
1096
+ if (format == null || value == null)
1097
+ throw 'Invalid arguments';
1098
+ value = (typeof value == 'object' ? value.toString() : value + '');
1099
+ if (value == '')
1100
+ return null;
1101
+ settings = settings || {};
1102
+ var shortYearCutoff = settings.shortYearCutoff || this._defaults.shortYearCutoff;
1103
+ shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
1104
+ new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
1105
+ var dayNamesShort = settings.dayNamesShort || this._defaults.dayNamesShort;
1106
+ var dayNames = settings.dayNames || this._defaults.dayNames;
1107
+ var monthNamesShort = settings.monthNamesShort || this._defaults.monthNamesShort;
1108
+ var monthNames = settings.monthNames || this._defaults.monthNames;
1109
+ var year = -1;
1110
+ var month = -1;
1111
+ var day = -1;
1112
+ var doy = -1;
1113
+ var literal = false;
1114
+ // Check whether a format character is doubled
1115
+ var lookAhead = function(match) {
1116
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
1117
+ if (matches)
1118
+ iFormat++;
1119
+ return matches;
1120
+ };
1121
+ // Extract a number from the string value
1122
+ var getNumber = function(match) {
1123
+ lookAhead(match);
1124
+ var size = (match == '@' ? 14 : (match == '!' ? 20 :
1125
+ (match == 'y' ? 4 : (match == 'o' ? 3 : 2))));
1126
+ var digits = new RegExp('^\\d{1,' + size + '}');
1127
+ var num = value.substring(iValue).match(digits);
1128
+ if (!num)
1129
+ throw 'Missing number at position ' + iValue;
1130
+ iValue += num[0].length;
1131
+ return parseInt(num[0], 10);
1132
+ };
1133
+ // Extract a name from the string value and convert to an index
1134
+ var getName = function(match, shortNames, longNames) {
1135
+ var names = (lookAhead(match) ? longNames : shortNames);
1136
+ for (var i = 0; i < names.length; i++) {
1137
+ if (value.substr(iValue, names[i].length) == names[i]) {
1138
+ iValue += names[i].length;
1139
+ return i + 1;
1140
+ }
1141
+ }
1142
+ throw 'Unknown name at position ' + iValue;
1143
+ };
1144
+ // Confirm that a literal character matches the string value
1145
+ var checkLiteral = function() {
1146
+ if (value.charAt(iValue) != format.charAt(iFormat))
1147
+ throw 'Unexpected literal at position ' + iValue;
1148
+ iValue++;
1149
+ };
1150
+ var iValue = 0;
1151
+ for (var iFormat = 0; iFormat < format.length; iFormat++) {
1152
+ if (literal)
1153
+ if (format.charAt(iFormat) == "'" && !lookAhead("'"))
1154
+ literal = false;
1155
+ else
1156
+ checkLiteral();
1157
+ else
1158
+ switch (format.charAt(iFormat)) {
1159
+ case 'd':
1160
+ day = getNumber('d');
1161
+ break;
1162
+ case 'D':
1163
+ getName('D', dayNamesShort, dayNames);
1164
+ break;
1165
+ case 'o':
1166
+ doy = getNumber('o');
1167
+ break;
1168
+ case 'm':
1169
+ month = getNumber('m');
1170
+ break;
1171
+ case 'M':
1172
+ month = getName('M', monthNamesShort, monthNames);
1173
+ break;
1174
+ case 'y':
1175
+ year = getNumber('y');
1176
+ break;
1177
+ case '@':
1178
+ var date = new Date(getNumber('@'));
1179
+ year = date.getFullYear();
1180
+ month = date.getMonth() + 1;
1181
+ day = date.getDate();
1182
+ break;
1183
+ case '!':
1184
+ var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
1185
+ year = date.getFullYear();
1186
+ month = date.getMonth() + 1;
1187
+ day = date.getDate();
1188
+ break;
1189
+ case "'":
1190
+ if (lookAhead("'"))
1191
+ checkLiteral();
1192
+ else
1193
+ literal = true;
1194
+ break;
1195
+ default:
1196
+ checkLiteral();
1197
+ }
1198
+ }
1199
+ if (iValue < value.length)
1200
+ throw 'Additional text found at end';
1201
+ if (year == -1)
1202
+ year = new Date().getFullYear();
1203
+ else if (year < 100)
1204
+ year += (shortYearCutoff == -1 ? 1900 : new Date().getFullYear() -
1205
+ new Date().getFullYear() % 100 - (year <= shortYearCutoff ? 0 : 100));
1206
+ if (doy > -1) {
1207
+ month = 1;
1208
+ day = doy;
1209
+ do {
1210
+ var dim = this._getDaysInMonth(year, month - 1);
1211
+ if (day <= dim)
1212
+ break;
1213
+ month++;
1214
+ day -= dim;
1215
+ } while (true);
1216
+ }
1217
+ var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
1218
+ if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
1219
+ throw 'Invalid date'; // E.g. 31/02/*
1220
+ return date;
1221
+ },
1222
+
1223
+ /* Standard date formats. */
1224
+ ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
1225
+ COOKIE: 'D, dd M yy',
1226
+ ISO_8601: 'yy-mm-dd',
1227
+ RFC_822: 'D, d M y',
1228
+ RFC_850: 'DD, dd-M-y',
1229
+ RFC_1036: 'D, d M y',
1230
+ RFC_1123: 'D, d M yy',
1231
+ RFC_2822: 'D, d M yy',
1232
+ RSS: 'D, d M y', // RFC 822
1233
+ TICKS: '!',
1234
+ TIMESTAMP: '@',
1235
+ W3C: 'yy-mm-dd', // ISO 8601
1236
+
1237
+ _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
1238
+ Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
1239
+
1240
+ /* Format a date object into a string value.
1241
+ The format can be combinations of the following:
1242
+ d - day of month (no leading zero)
1243
+ dd - day of month (two digit)
1244
+ o - day of year (no leading zeros)
1245
+ oo - day of year (three digit)
1246
+ D - day name short
1247
+ DD - day name long
1248
+ m - month of year (no leading zero)
1249
+ mm - month of year (two digit)
1250
+ M - month name short
1251
+ MM - month name long
1252
+ y - year (two digit)
1253
+ yy - year (four digit)
1254
+ @ - Unix timestamp (ms since 01/01/1970)
1255
+ ! - Windows ticks (100ns since 01/01/0001)
1256
+ '...' - literal text
1257
+ '' - single quote
1258
+ @param format (string) the desired format of the date
1259
+ @param date (Date) the date value to format
1260
+ @param settings (object) attributes include:
1261
+ dayNamesShort (string[7]) abbreviated names of the days from Sunday (optional)
1262
+ dayNames (string[7]) names of the days from Sunday (optional)
1263
+ monthNamesShort (string[12]) abbreviated names of the months (optional)
1264
+ monthNames (string[12]) names of the months (optional)
1265
+ @return (string) the date in the above format */
1266
+ formatDate: function (format, date, settings) {
1267
+ if (!date)
1268
+ return '';
1269
+ var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
1270
+ var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
1271
+ var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
1272
+ var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
1273
+ // Check whether a format character is doubled
1274
+ var lookAhead = function(match) {
1275
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
1276
+ if (matches)
1277
+ iFormat++;
1278
+ return matches;
1279
+ };
1280
+ // Format a number, with leading zero if necessary
1281
+ var formatNumber = function(match, value, len) {
1282
+ var num = '' + value;
1283
+ if (lookAhead(match))
1284
+ while (num.length < len)
1285
+ num = '0' + num;
1286
+ return num;
1287
+ };
1288
+ // Format a name, short or long as requested
1289
+ var formatName = function(match, value, shortNames, longNames) {
1290
+ return (lookAhead(match) ? longNames[value] : shortNames[value]);
1291
+ };
1292
+ var output = '';
1293
+ var literal = false;
1294
+ if (date)
1295
+ for (var iFormat = 0; iFormat < format.length; iFormat++) {
1296
+ if (literal)
1297
+ if (format.charAt(iFormat) == "'" && !lookAhead("'"))
1298
+ literal = false;
1299
+ else
1300
+ output += format.charAt(iFormat);
1301
+ else
1302
+ switch (format.charAt(iFormat)) {
1303
+ case 'd':
1304
+ output += formatNumber('d', date.getDate(), 2);
1305
+ break;
1306
+ case 'D':
1307
+ output += formatName('D', date.getDay(), dayNamesShort, dayNames);
1308
+ break;
1309
+ case 'o':
1310
+ output += formatNumber('o',
1311
+ (date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
1312
+ break;
1313
+ case 'm':
1314
+ output += formatNumber('m', date.getMonth() + 1, 2);
1315
+ break;
1316
+ case 'M':
1317
+ output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
1318
+ break;
1319
+ case 'y':
1320
+ output += (lookAhead('y') ? date.getFullYear() :
1321
+ (date.getFullYear() % 100 < 10 ? '0' : '') + date.getFullYear() % 100);
1322
+ break;
1323
+ case '@':
1324
+ output += date.getTime();
1325
+ break;
1326
+ case '!':
1327
+ output += date.getTime() * 10000 + this._ticksTo1970;
1328
+ break;
1329
+ case "'":
1330
+ if (lookAhead("'"))
1331
+ output += "'";
1332
+ else
1333
+ literal = true;
1334
+ break;
1335
+ default:
1336
+ output += format.charAt(iFormat);
1337
+ }
1338
+ }
1339
+ return output;
1340
+ },
1341
+
1342
+ /* Get a setting value, defaulting if necessary.
1343
+ @param inst (object) the instance settings for this datepicker
1344
+ @param name (string) the name of the property
1345
+ @return (any) the property's value */
1346
+ _get: function(inst, name) {
1347
+ return inst.settings[name] !== undefined ?
1348
+ inst.settings[name] : this._defaults[name];
1349
+ },
1350
+
1351
+ /* Parse existing date and initialise date picker.
1352
+ @param inst (object) the instance settings for this datepicker */
1353
+ _setDateFromField: function(inst) {
1354
+ var dateFormat = this._get(inst, 'dateFormat');
1355
+ var rangeSelect = this._get(inst, 'rangeSelect');
1356
+ var multiSelect = this._get(inst, 'multiSelect');
1357
+ var dates = (inst.input ? inst.input.val() : '');
1358
+ dates = (rangeSelect ? dates.split(this._get(inst, 'rangeSeparator')) :
1359
+ (multiSelect ? dates.split(this._get(inst, 'multiSeparator')) : [dates]));
1360
+ inst.dates = [];
1361
+ var settings = this._getFormatConfig(inst);
1362
+ for (var i = 0; i < dates.length; i++)
1363
+ try {
1364
+ inst.dates[i] = this.parseDate(dateFormat, dates[i], settings);
1365
+ }
1366
+ catch (event) {
1367
+ inst.dates[i] = null;
1368
+ }
1369
+ for (var i = inst.dates.length - 1; i >= 0; i--)
1370
+ if (!inst.dates[i])
1371
+ inst.dates.splice(i, 1);
1372
+ if (rangeSelect && inst.dates.length < 2)
1373
+ inst.dates[1] = inst.dates[0];
1374
+ if (multiSelect && inst.dates.length > multiSelect)
1375
+ inst.dates.splice(multiSelect, inst.dates.length);
1376
+ inst.cursorDate = new Date((inst.dates[0] || this._getDefaultDate(inst)).getTime());
1377
+ inst.drawMonth = inst.cursorDate.getMonth();
1378
+ inst.drawYear = inst.cursorDate.getFullYear();
1379
+ this._adjustInstDate(inst);
1380
+ },
1381
+
1382
+ /* Retrieve the default date shown on opening.
1383
+ @param inst (object) the instance settings for this datepicker
1384
+ @return (Date) the default date */
1385
+ _getDefaultDate: function(inst) {
1386
+ return this._restrictMinMax(inst,
1387
+ this._determineDate(this._get(inst, 'defaultDate'), new Date()));
1388
+ },
1389
+
1390
+ /* A date may be specified as an exact value or a relative one.
1391
+ @param date (Date or number or string) the date or offset
1392
+ @param defaultDate (Date) the date to use if no other supplied
1393
+ @return (Date) the decoded date */
1394
+ _determineDate: function(date, defaultDate) {
1395
+ var offsetNumeric = function(offset) {
1396
+ var date = new Date();
1397
+ date.setDate(date.getDate() + offset);
1398
+ return date;
1399
+ };
1400
+ var offsetString = function(offset) {
1401
+ var date = new Date();
1402
+ var year = date.getFullYear();
1403
+ var month = date.getMonth();
1404
+ var day = date.getDate();
1405
+ var pattern = /([+-]?[0-9]+)\s*(d|w|m|y)?/g;
1406
+ var matches = pattern.exec(offset.toLowerCase());
1407
+ while (matches) {
1408
+ switch (matches[2] || 'd') {
1409
+ case 'd':
1410
+ day += parseInt(matches[1], 10); break;
1411
+ case 'w':
1412
+ day += parseInt(matches[1], 10) * 7; break;
1413
+ case 'm':
1414
+ month += parseInt(matches[1], 10);
1415
+ day = Math.min(day, $.datepick._getDaysInMonth(year, month));
1416
+ break;
1417
+ case 'y':
1418
+ year += parseInt(matches[1], 10);
1419
+ day = Math.min(day, $.datepick._getDaysInMonth(year, month));
1420
+ break;
1421
+ }
1422
+ matches = pattern.exec(offset.toLowerCase());
1423
+ }
1424
+ return new Date(year, month, day);
1425
+ };
1426
+ date = (date == null ? defaultDate : (typeof date == 'string' ? offsetString(date) :
1427
+ (typeof date == 'number' ? (isNaN(date) || date == Infinity || date == -Infinity ?
1428
+ defaultDate : offsetNumeric(date)) : date)));
1429
+ date = (date && (date.toString() == 'Invalid Date' ||
1430
+ date.toString() == 'NaN') ? defaultDate : date);
1431
+ if (date) {
1432
+ date.setHours(0);
1433
+ date.setMinutes(0);
1434
+ date.setSeconds(0);
1435
+ date.setMilliseconds(0);
1436
+ }
1437
+ return this._daylightSavingAdjust(date);
1438
+ },
1439
+
1440
+ /* Handle switch to/from daylight saving.
1441
+ Hours may be non-zero on daylight saving cut-over:
1442
+ > 12 when midnight changeover, but then cannot generate
1443
+ midnight datetime, so jump to 1AM, otherwise reset.
1444
+ @param date (Date) the date to check
1445
+ @return (Date) the corrected date */
1446
+ _daylightSavingAdjust: function(date) {
1447
+ if (!date) return null;
1448
+ date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
1449
+ return date;
1450
+ },
1451
+
1452
+ /* Set the date(s) directly.
1453
+ @param inst (object) the instance settings for this datepicker
1454
+ @param date (Date or Date[] or number or string) the new date or start of a range
1455
+ @param endDate (Date or number or string) the end of a range */
1456
+ _setDate: function(inst, date, endDate) {
1457
+ date = (!date ? [] : (isArray(date) ? date : [date]));
1458
+ if (endDate)
1459
+ date.push(endDate);
1460
+ var clear = (date.length == 0);
1461
+ var origMonth = inst.cursorDate.getMonth();
1462
+ var origYear = inst.cursorDate.getFullYear();
1463
+ inst.dates = [];
1464
+ inst.dates[0] = this._restrictMinMax(inst, this._determineDate(date[0], new Date()));
1465
+ inst.cursorDate = new Date(inst.dates[0].getTime());
1466
+ inst.drawMonth = inst.cursorDate.getMonth();
1467
+ inst.drawYear = inst.cursorDate.getFullYear();
1468
+ if (this._get(inst, 'rangeSelect'))
1469
+ inst.dates[1] = (date.length < 1 ? inst.dates[0] :
1470
+ this._restrictMinMax(inst, this._determineDate(date[1], null)));
1471
+ else if (this._get(inst, 'multiSelect'))
1472
+ for (var i = 1; i < date.length; i++)
1473
+ inst.dates[i] = this._restrictMinMax(inst, this._determineDate(date[i], null));
1474
+ if (origMonth != inst.cursorDate.getMonth() || origYear != inst.cursorDate.getFullYear())
1475
+ this._notifyChange(inst);
1476
+ this._adjustInstDate(inst);
1477
+ this._showDate(inst);
1478
+ },
1479
+
1480
+ /* Retrieve the date(s) directly.
1481
+ @param inst (object) the instance settings for this datepicker
1482
+ @return (Date or Date[2] or Date[]) the current date or dates
1483
+ (for a range or multiples) */
1484
+ _getDate: function(inst) {
1485
+ var startDate = (inst.input && inst.input.val() == '' ? null : inst.dates[0]);
1486
+ if (this._get(inst, 'rangeSelect'))
1487
+ return (startDate ? [inst.dates[0], inst.dates[1] || inst.dates[0]] : [null, null]);
1488
+ else if (this._get(inst, 'multiSelect'))
1489
+ return inst.dates.slice(0, inst.dates.length);
1490
+ else
1491
+ return startDate;
1492
+ },
1493
+
1494
+ /* Generate the HTML for the current state of the date picker.
1495
+ @param inst (object) the instance settings for this datepicker
1496
+ @return (string) the new HTML for the datepicker */
1497
+ _generateHTML: function(inst) {
1498
+ var today = new Date();
1499
+ today = this._daylightSavingAdjust(
1500
+ new Date(today.getFullYear(), today.getMonth(), today.getDate())); // Clear time
1501
+ var showStatus = this._get(inst, 'showStatus');
1502
+ var initStatus = this._get(inst, 'initStatus') || '&#xa0;';
1503
+ var isRTL = this._get(inst, 'isRTL');
1504
+ // Build the date picker HTML
1505
+ var clear = (this._get(inst, 'mandatory') ? '' :
1506
+ '<div class="datepick-clear"><a href="javascript:void(0)" onclick="jQuery.datepick._clearDate(\'#' + inst.id + '\');"' +
1507
+ this._addStatus(showStatus, inst.id, this._get(inst, 'clearStatus'), initStatus) + '>' +
1508
+ this._get(inst, 'clearText') + '</a></div>');
1509
+ var controls = '<div class="datepick-control">' + (isRTL ? '' : clear) +
1510
+ '<div class="datepick-close"><a href="javascript:void(0)" onclick="jQuery.datepick._hideDatepick();"' +
1511
+ this._addStatus(showStatus, inst.id, this._get(inst, 'closeStatus'), initStatus) + '>' +
1512
+ this._get(inst, 'closeText') + '</a></div>' + (isRTL ? clear : '') + '</div>';
1513
+ var prompt = this._get(inst, 'prompt');
1514
+ var closeAtTop = this._get(inst, 'closeAtTop');
1515
+ var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
1516
+ var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
1517
+ var showBigPrevNext = this._get(inst, 'showBigPrevNext');
1518
+ var numMonths = this._getNumberOfMonths(inst);
1519
+ var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
1520
+ var stepMonths = this._get(inst, 'stepMonths');
1521
+ var stepBigMonths = this._get(inst, 'stepBigMonths');
1522
+ var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
1523
+ var minDate = this._getMinMaxDate(inst, 'min', true);
1524
+ var maxDate = this._getMinMaxDate(inst, 'max');
1525
+ var drawMonth = inst.drawMonth - showCurrentAtPos;
1526
+ var drawYear = inst.drawYear;
1527
+ if (drawMonth < 0) {
1528
+ drawMonth += 12;
1529
+ drawYear--;
1530
+ }
1531
+ if (maxDate) { // Don't show past maximum unless also restricted by minimum
1532
+ var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
1533
+ maxDate.getMonth() - numMonths[1] + 1, maxDate.getDate()));
1534
+ maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
1535
+ while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
1536
+ drawMonth--;
1537
+ if (drawMonth < 0) {
1538
+ drawMonth = 11;
1539
+ drawYear--;
1540
+ }
1541
+ }
1542
+ }
1543
+ inst.drawMonth = drawMonth;
1544
+ inst.drawYear = drawYear;
1545
+ // Controls and links
1546
+ var prevText = this._get(inst, 'prevText');
1547
+ prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
1548
+ this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
1549
+ this._getFormatConfig(inst)));
1550
+ var prevBigText = (showBigPrevNext ? this._get(inst, 'prevBigText') : '');
1551
+ prevBigText = (!navigationAsDateFormat ? prevBigText : this.formatDate(prevBigText,
1552
+ this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepBigMonths, 1)),
1553
+ this._getFormatConfig(inst)));
1554
+ var prev = '<div class="datepick-prev">' + (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
1555
+ (showBigPrevNext ? '<a href="javascript:void(0)" onclick="jQuery.datepick._adjustDate(\'#' + inst.id + '\', -' + stepBigMonths + ', \'M\');"' +
1556
+ this._addStatus(showStatus, inst.id, this._get(inst, 'prevBigStatus'), initStatus) + '>' + prevBigText + '</a>' : '') +
1557
+ '<a href="javascript:void(0)" onclick="jQuery.datepick._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
1558
+ this._addStatus(showStatus, inst.id, this._get(inst, 'prevStatus'), initStatus) + '>' + prevText + '</a>' :
1559
+ (hideIfNoPrevNext ? '&#xa0;' : (showBigPrevNext ? '<label>' + prevBigText + '</label>' : '') +
1560
+ '<label>' + prevText + '</label>')) + '</div>';
1561
+ var nextText = this._get(inst, 'nextText');
1562
+ nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
1563
+ this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
1564
+ this._getFormatConfig(inst)));
1565
+ var nextBigText = (showBigPrevNext ? this._get(inst, 'nextBigText') : '');
1566
+ nextBigText = (!navigationAsDateFormat ? nextBigText : this.formatDate(nextBigText,
1567
+ this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepBigMonths, 1)),
1568
+ this._getFormatConfig(inst)));
1569
+ var next = '<div class="datepick-next">' + (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
1570
+ '<a href="javascript:void(0)" onclick="jQuery.datepick._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
1571
+ this._addStatus(showStatus, inst.id, this._get(inst, 'nextStatus'), initStatus) + '>' + nextText + '</a>' +
1572
+ (showBigPrevNext ? '<a href="javascript:void(0)" onclick="jQuery.datepick._adjustDate(\'#' + inst.id + '\', +' + stepBigMonths + ', \'M\');"' +
1573
+ this._addStatus(showStatus, inst.id, this._get(inst, 'nextBigStatus'), initStatus) + '>' + nextBigText + '</a>' : '') :
1574
+ (hideIfNoPrevNext ? '&#xa0;' : '<label>' + nextText + '</label>' +
1575
+ (showBigPrevNext ? '<label>' + nextBigText + '</label>' : ''))) + '</div>';
1576
+ var currentText = this._get(inst, 'currentText');
1577
+ var gotoDate = (this._get(inst, 'gotoCurrent') && inst.dates[0] ? inst.dates[0] : today);
1578
+ currentText = (!navigationAsDateFormat ? currentText :
1579
+ this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
1580
+ var html = (closeAtTop && !inst.inline ? controls : '') +
1581
+ '<div class="datepick-links">' + (isRTL ? next : prev) +
1582
+ (this._isInRange(inst, gotoDate) ? '<div class="datepick-current">' +
1583
+ '<a href="javascript:void(0)" onclick="jQuery.datepick._gotoToday(\'#' + inst.id + '\');"' +
1584
+ this._addStatus(showStatus, inst.id, this._get(inst, 'currentStatus'), initStatus) + '>' +
1585
+ currentText + '</a></div>' : '') + (isRTL ? prev : next) + '</div>' +
1586
+ (prompt ? '<div class="' + this._promptClass + '"><span>' + prompt + '</span></div>' : '');
1587
+ var firstDay = parseInt(this._get(inst, 'firstDay'), 10);
1588
+ firstDay = (isNaN(firstDay) ? 0 : firstDay);
1589
+ var changeFirstDay = this._get(inst, 'changeFirstDay');
1590
+ var dayNames = this._get(inst, 'dayNames');
1591
+ var dayNamesShort = this._get(inst, 'dayNamesShort');
1592
+ var dayNamesMin = this._get(inst, 'dayNamesMin');
1593
+ var monthNames = this._get(inst, 'monthNames');
1594
+ var beforeShowDay = this._get(inst, 'beforeShowDay');
1595
+ var highlightWeek = this._get(inst, 'highlightWeek');
1596
+ var showOtherMonths = this._get(inst, 'showOtherMonths');
1597
+ var selectOtherMonths = this._get(inst, 'selectOtherMonths');
1598
+ var showWeeks = this._get(inst, 'showWeeks');
1599
+ var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
1600
+ var weekStatus = this._get(inst, 'weekStatus');
1601
+ var status = (showStatus ? this._get(inst, 'dayStatus') || initStatus : '');
1602
+ var dateStatus = this._get(inst, 'statusForDate') || this.dateStatus;
1603
+ var onHover = this._get(inst, 'onHover');
1604
+ var defaultDate = this._getDefaultDate(inst);
1605
+ for (var row = 0; row < numMonths[0]; row++)
1606
+ for (var col = 0; col < numMonths[1]; col++) {
1607
+ var cursorDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.cursorDate.getDate()));
1608
+ html += '<div class="' + this._oneMonthClass + (col == 0 ? ' datepick-new-row' : '') + '">' +
1609
+ this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
1610
+ cursorDate, row > 0 || col > 0, showStatus, initStatus, monthNames) + // Draw month headers
1611
+ '<table class="datepick" cellpadding="0" cellspacing="0"><thead>' +
1612
+ '<tr class="datepick-title-row">' +
1613
+ (showWeeks ? '<th' + this._addStatus(showStatus, inst.id, weekStatus, initStatus) + '>' +
1614
+ this._get(inst, 'weekHeader') + '</th>' : '');
1615
+ for (var dow = 0; dow < 7; dow++) { // Days of the week
1616
+ var day = (dow + firstDay) % 7;
1617
+ var dayStatus = (!showStatus || !changeFirstDay ? '' :
1618
+ status.replace(/DD/, dayNames[day]).replace(/D/, dayNamesShort[day]));
1619
+ html += '<th' + ((dow + firstDay + 6) % 7 < 5 ? '' : ' class="datepick-week-end-cell"') + '>' +
1620
+ (!changeFirstDay ? '<span' + this._addStatus(showStatus, inst.id, dayNames[day], initStatus) :
1621
+ '<a href="javascript:void(0)" onclick="jQuery.datepick._changeFirstDay(\'#' + inst.id + '\', ' + day + ');"' +
1622
+ this._addStatus(showStatus, inst.id, dayStatus, initStatus)) + ' title="' + dayNames[day] + '">' +
1623
+ dayNamesMin[day] + (changeFirstDay ? '</a>' : '</span>') + '</th>';
1624
+ }
1625
+ html += '</tr></thead><tbody>';
1626
+ var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
1627
+ if (drawYear == inst.cursorDate.getFullYear() && drawMonth == inst.cursorDate.getMonth())
1628
+ inst.cursorDate.setDate(Math.min(inst.cursorDate.getDate(), daysInMonth));
1629
+ var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
1630
+ var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // Calculate the number of rows to generate
1631
+ var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
1632
+ for (var dRow = 0; dRow < numRows; dRow++) { // Create date picker rows
1633
+ html += '<tr class="datepick-days-row">' +
1634
+ (showWeeks ? '<td class="datepick-week-col"' +
1635
+ this._addStatus(showStatus, inst.id, weekStatus, initStatus) + '>' +
1636
+ calculateWeek(printDate) + '</td>' : '');
1637
+ for (var dow = 0; dow < 7; dow++) { // Create date picker days
1638
+ var daySettings = (beforeShowDay ?
1639
+ beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
1640
+ var otherMonth = (printDate.getMonth() != drawMonth);
1641
+ var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
1642
+ (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
1643
+ var current = (this._get(inst, 'rangeSelect') && inst.dates[0] &&
1644
+ printDate.getTime() >= inst.dates[0].getTime() &&
1645
+ printDate.getTime() <= (inst.dates[1] || inst.dates[0]).getTime());
1646
+ for (var i = 0; i < inst.dates.length; i++)
1647
+ current = current || (inst.dates[i] &&
1648
+ printDate.getTime() == inst.dates[i].getTime());
1649
+ var empty = otherMonth && !showOtherMonths;
1650
+ html += '<td class="datepick-days-cell' +
1651
+ ((dow + firstDay + 6) % 7 >= 5 ? ' datepick-week-end-cell' : '') + // Highlight weekends
1652
+ (otherMonth ? ' datepick-other-month' : '') + // Highlight days from other months
1653
+ ((printDate.getTime() == cursorDate.getTime() &&
1654
+ drawMonth == inst.cursorDate.getMonth() && inst._keyEvent) || // User pressed key
1655
+ (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == cursorDate.getTime()) ?
1656
+ // Or defaultDate is current printedDate and defaultDate is cursorDate
1657
+ ' ' + $.datepick._dayOverClass : '') + // Highlight selected day
1658
+ (unselectable ? ' ' + this._unselectableClass : '') + // Highlight unselectable days
1659
+ (empty ? '' : ' ' + daySettings[1] + // Highlight custom dates
1660
+ (current ? ' ' + this._currentClass : '') + // Currently selected
1661
+ (printDate.getTime() == today.getTime() ? ' datepick-today' : '')) + '"' + // Highlight today (if different)
1662
+ (!empty && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // Cell title
1663
+ ' onmouseover="' + (unselectable ? '' : 'jQuery(this).parents(\'tbody\').' +
1664
+ 'find(\'td\').removeClass(\'' + this._dayOverClass + '\').end().end().' +
1665
+ 'addClass(\'' + this._dayOverClass + '\');') + // Cursor
1666
+ (highlightWeek ? 'jQuery(this).parent().parent().' +
1667
+ 'find(\'tr\').removeClass(\'' + this._weekOverClass + '\').end().end().' +
1668
+ 'addClass(\'' + this._weekOverClass + '\');' : '') + // Highlight week
1669
+ (!showStatus || empty ? '' : 'jQuery(\'#datepick-status-' + inst.id + '\').html(\'' + // Show status
1670
+ (dateStatus.apply((inst.input ? inst.input[0] : null), [printDate, inst]) || initStatus) +'\');') +
1671
+ (onHover && !empty ? 'jQuery.datepick._doHover(\'#' + // onHover
1672
+ inst.id + '\',' + printDate.getFullYear() + ',' + printDate.getMonth() + ', this);' : '') + '"' +
1673
+ ' onmouseout="' + (unselectable ? '' :
1674
+ 'jQuery(this).removeClass(\'' + this._dayOverClass + '\');') + // Remove cursor
1675
+ (!showStatus || empty ? '' : 'jQuery(\'#datepick-status-' +
1676
+ inst.id + '\').' + 'html(\'' + initStatus + '\');') +
1677
+ (onHover && !empty ? 'jQuery.datepick._doHover(\'#' + inst.id + '\');' : '') + '"' + // onHover
1678
+ (unselectable ? '' : ' onclick="jQuery.datepick._selectDay(\'#' + // Select
1679
+ inst.id + '\'' + ',' + printDate.getTime() + ',this);"') + '>' +
1680
+ (empty ? '&#xa0;' : // Not showing other months
1681
+ (unselectable ? printDate.getDate() : '<a>' + printDate.getDate() + '</a>')) + '</td>'; // Display for this month
1682
+ printDate.setDate(printDate.getDate() + 1);
1683
+ printDate = this._daylightSavingAdjust(printDate);
1684
+ }
1685
+ html += '</tr>';
1686
+ }
1687
+ drawMonth++;
1688
+ if (drawMonth > 11) {
1689
+ drawMonth = 0;
1690
+ drawYear++;
1691
+ }
1692
+ html += '</tbody></table></div>';
1693
+ }
1694
+ html += (showStatus ? '<div style="clear: both;"></div><div id="datepick-status-' + inst.id +
1695
+ '" class="datepick-status">' + initStatus + '</div>' : '') +
1696
+ (!closeAtTop && !inst.inline ? controls : '') +
1697
+ '<div style="clear: both;"></div>' +
1698
+ ($.browser.msie && parseInt($.browser.version, 10) < 7 && !inst.inline ?
1699
+ '<iframe src="javascript:false;" class="' + this._coverClass + '"></iframe>' : '');
1700
+ inst._keyEvent = false;
1701
+ return html;
1702
+ },
1703
+
1704
+ /* Generate the month and year header.
1705
+ @param inst (object) the instance settings for this datepicker
1706
+ @param drawMonth (number) the current month
1707
+ @param drawYear (number) the current year
1708
+ @param minDate (Date) the minimum allowed date or null if none
1709
+ @param maxDate (Date) the maximum allowed date or null if none
1710
+ @return (string) the HTML for the month and year */
1711
+ _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
1712
+ cursorDate, secondary, showStatus, initStatus, monthNames) {
1713
+ var minDraw = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1));
1714
+ minDate = (minDate < minDraw ? minDate : minDraw);
1715
+ var changeMonth = this._get(inst, 'changeMonth');
1716
+ var changeYear = this._get(inst, 'changeYear');
1717
+ var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
1718
+ var html = '<div class="datepick-header">';
1719
+ var monthHtml = '';
1720
+ // Month selection
1721
+ if (secondary || !changeMonth)
1722
+ monthHtml += '<span>' + monthNames[drawMonth] + '</span>';
1723
+ else {
1724
+ var inMinYear = (minDate && minDate.getFullYear() == drawYear);
1725
+ var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
1726
+ monthHtml += '<select class="datepick-new-month" ' +
1727
+ 'onchange="jQuery.datepick._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
1728
+ 'onclick="jQuery.datepick._clickMonthYear(\'#' + inst.id + '\');"' +
1729
+ this._addStatus(showStatus, inst.id, this._get(inst, 'monthStatus'), initStatus) + '>';
1730
+ for (var month = 0; month < 12; month++) {
1731
+ if ((!inMinYear || month >= minDate.getMonth()) &&
1732
+ (!inMaxYear || month <= maxDate.getMonth()))
1733
+ monthHtml += '<option value="' + month + '"' +
1734
+ (month == drawMonth ? ' selected="selected"' : '') +
1735
+ '>' + monthNames[month] + '</option>';
1736
+ }
1737
+ monthHtml += '</select>';
1738
+ }
1739
+ if (!showMonthAfterYear)
1740
+ html += monthHtml + (secondary || !changeMonth || !changeYear ? '&#xa0;' : '');
1741
+ // Year selection
1742
+ if (secondary || !changeYear)
1743
+ html += '<span>' + drawYear + '</span>';
1744
+ else {
1745
+ // Determine range of years to display
1746
+ var years = this._get(inst, 'yearRange').split(':');
1747
+ var year = 0;
1748
+ var endYear = 0;
1749
+ if (years.length != 2) {
1750
+ year = drawYear - 10;
1751
+ endYear = drawYear + 10;
1752
+ } else if (years[0].charAt(0) == '+' || years[0].charAt(0) == '-') {
1753
+ year = drawYear + parseInt(years[0], 10);
1754
+ endYear = drawYear + parseInt(years[1], 10);
1755
+ } else {
1756
+ year = parseInt(years[0], 10);
1757
+ endYear = parseInt(years[1], 10);
1758
+ }
1759
+ year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
1760
+ endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
1761
+ html += '<select class="datepick-new-year" ' +
1762
+ 'onchange="jQuery.datepick._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
1763
+ 'onclick="jQuery.datepick._clickMonthYear(\'#' + inst.id + '\');"' +
1764
+ this._addStatus(showStatus, inst.id, this._get(inst, 'yearStatus'), initStatus) + '>';
1765
+ for (; year <= endYear; year++) {
1766
+ html += '<option value="' + year + '"' +
1767
+ (year == drawYear ? ' selected="selected"' : '') +
1768
+ '>' + year + '</option>';
1769
+ }
1770
+ html += '</select>';
1771
+ }
1772
+ html += this._get(inst, 'yearSuffix');
1773
+ if (showMonthAfterYear)
1774
+ html += (secondary || !changeMonth || !changeYear ? '&#xa0;' : '') + monthHtml;
1775
+ html += '</div>'; // Close datepicker_header
1776
+ return html;
1777
+ },
1778
+
1779
+ /* Provide code to set and clear the status panel.
1780
+ @param showStatus (boolean) true if the status bar is shown
1781
+ @param id (string) the ID of the datepicker instance
1782
+ @param text (string) the status text to display
1783
+ @param initStatus (string) the default status message
1784
+ @return (string) hover actions for the status messages */
1785
+ _addStatus: function(showStatus, id, text, initStatus) {
1786
+ return (showStatus ? ' onmouseover="jQuery(\'#datepick-status-' + id +
1787
+ '\').html(\'' + (text || initStatus) + '\');" ' +
1788
+ 'onmouseout="jQuery(\'#datepick-status-' + id +
1789
+ '\').html(\'' + initStatus + '\');"' : '');
1790
+ },
1791
+
1792
+ /* Adjust one of the date sub-fields.
1793
+ @param inst (object) the instance settings for this datepicker
1794
+ @param offset (number) the change to apply
1795
+ @param period (string) 'D' for days, 'M' for months, 'Y' for years */
1796
+ _adjustInstDate: function(inst, offset, period) {
1797
+ var year = inst.drawYear + (period == 'Y' ? offset : 0);
1798
+ var month = inst.drawMonth + (period == 'M' ? offset : 0);
1799
+ var day = Math.min(inst.cursorDate.getDate(), this._getDaysInMonth(year, month)) +
1800
+ (period == 'D' ? offset : 0);
1801
+ inst.cursorDate = this._restrictMinMax(inst,
1802
+ this._daylightSavingAdjust(new Date(year, month, day)));
1803
+ inst.drawMonth = inst.cursorDate.getMonth();
1804
+ inst.drawYear = inst.cursorDate.getFullYear();
1805
+ if (period == 'M' || period == 'Y')
1806
+ this._notifyChange(inst);
1807
+ },
1808
+
1809
+ /* Ensure a date is within any min/max bounds.
1810
+ @param inst (object) the instance settings for this datepicker
1811
+ @param date (Date) the date to check
1812
+ @return (Date) the restricted date */
1813
+ _restrictMinMax: function(inst, date) {
1814
+ var minDate = this._getMinMaxDate(inst, 'min', true);
1815
+ var maxDate = this._getMinMaxDate(inst, 'max');
1816
+ date = (minDate && date < minDate ? minDate : date);
1817
+ date = (maxDate && date > maxDate ? maxDate : date);
1818
+ return date;
1819
+ },
1820
+
1821
+ /* Notify change of month/year.
1822
+ @param inst (object) the instance settings for this datepicker */
1823
+ _notifyChange: function(inst) {
1824
+ var onChange = this._get(inst, 'onChangeMonthYear');
1825
+ if (onChange)
1826
+ onChange.apply((inst.input ? inst.input[0] : null),
1827
+ [inst.cursorDate.getFullYear(), inst.cursorDate.getMonth() + 1,
1828
+ this._daylightSavingAdjust(new Date(
1829
+ inst.cursorDate.getFullYear(), inst.cursorDate.getMonth(), 1)), inst]);
1830
+ },
1831
+
1832
+ /* Determine the number of months to show.
1833
+ @param inst (object) the instance settings for this datepicker
1834
+ @return (number[2]) the number of rows and columns to display */
1835
+ _getNumberOfMonths: function(inst) {
1836
+ var numMonths = this._get(inst, 'numberOfMonths');
1837
+ return (numMonths == null ? [1, 1] :
1838
+ (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
1839
+ },
1840
+
1841
+ /* Determine the current minimum/maximum date.
1842
+ Ensure no time components are set. May be overridden for a range.
1843
+ @param inst (object) the instance settings for this datepicker
1844
+ @param minMax (string) 'min' or 'max' for required date
1845
+ @param checkRange (boolean) true to allow override for a range minimum
1846
+ @return (Date) the minimum/maximum date or null if none */
1847
+ _getMinMaxDate: function(inst, minMax, checkRange) {
1848
+ var date = this._determineDate(this._get(inst, minMax + 'Date'), null);
1849
+ var rangeMin = this._getRangeMin(inst);
1850
+ return (checkRange && rangeMin && (!date || rangeMin > date) ? rangeMin : date);
1851
+ },
1852
+
1853
+ /* Retrieve the temporary range minimum when in the process of selecting.
1854
+ @param inst (object) the instance settings for this datepicker
1855
+ @return (Date) the temporary minimum or null */
1856
+ _getRangeMin: function(inst) {
1857
+ return (this._get(inst, 'rangeSelect') && inst.dates[0] &&
1858
+ !inst.dates[1] ? inst.dates[0] : null);
1859
+ },
1860
+
1861
+ /* Find the number of days in a given month.
1862
+ @param year (number) the full year
1863
+ @param month (number) the month (0 to 11)
1864
+ @return (number) the number of days in this month */
1865
+ _getDaysInMonth: function(year, month) {
1866
+ return 32 - new Date(year, month, 32).getDate();
1867
+ },
1868
+
1869
+ /* Find the day of the week of the first of a month.
1870
+ @param year (number) the full year
1871
+ @param month (number) the month (0 to 11)
1872
+ @return (number) 0 = Sunday, 1 = Monday, ... */
1873
+ _getFirstDayOfMonth: function(year, month) {
1874
+ return new Date(year, month, 1).getDay();
1875
+ },
1876
+
1877
+ /* Determines if we should allow a "prev/next" month display change.
1878
+ @param inst (object) the instance settings for this datepicker
1879
+ @param offset (number) the number of months to change by
1880
+ @param curYear (number) the full current year
1881
+ @param curMonth (number) the current month (0 to 11)
1882
+ @return (boolean) true if prev/next allowed, false if not */
1883
+ _canAdjustMonth: function(inst, offset, curYear, curMonth) {
1884
+ var numMonths = this._getNumberOfMonths(inst);
1885
+ var date = this._daylightSavingAdjust(new Date(
1886
+ curYear, curMonth + (offset < 0 ? offset : numMonths[1]), 1));
1887
+ if (offset < 0)
1888
+ date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
1889
+ return this._isInRange(inst, date);
1890
+ },
1891
+
1892
+ /* Is the given date in the accepted range?
1893
+ @param inst (object) the instance settings for this datepicker
1894
+ @param date (Date) the date to check
1895
+ @return (boolean) true if the date is in the allowed minimum/maximum, false if not */
1896
+ _isInRange: function(inst, date) {
1897
+ // During range selection, use minimum of selected date and range start
1898
+ var minDate = this._getRangeMin(inst) || this._getMinMaxDate(inst, 'min');
1899
+ var maxDate = this._getMinMaxDate(inst, 'max');
1900
+ return ((!minDate || date >= minDate) && (!maxDate || date <= maxDate));
1901
+ },
1902
+
1903
+ /* Provide the configuration settings for formatting/parsing.
1904
+ @param inst (object) the instance settings for this datepicker
1905
+ @return (object) the settings subset */
1906
+ _getFormatConfig: function(inst) {
1907
+ return {shortYearCutoff: this._get(inst, 'shortYearCutoff'),
1908
+ dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
1909
+ monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
1910
+ },
1911
+
1912
+ /* Format the given date for display.
1913
+ @param inst (object) the instance settings for this datepicker
1914
+ @param year (number, optional) the full year
1915
+ @param month (number, optional) the month of the year (0 to 11)
1916
+ @param day (number, optional) the day of the month
1917
+ @return (string) formatted date */
1918
+ _formatDate: function(inst, year, month, day) {
1919
+ if (!year)
1920
+ inst.dates[0] = new Date(inst.cursorDate.getTime());
1921
+ var date = (year ? (typeof year == 'object' ? year :
1922
+ this._daylightSavingAdjust(new Date(year, month, day))) : inst.dates[0]);
1923
+ return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
1924
+ }
1925
+ });
1926
+
1927
+ /* jQuery extend now ignores nulls!
1928
+ @param target (object) the object to extend
1929
+ @param props (object) the new settings
1930
+ @return (object) the updated object */
1931
+ function extendRemove(target, props) {
1932
+ $.extend(target, props);
1933
+ for (var name in props)
1934
+ if (props[name] == null || props[name] == undefined)
1935
+ target[name] = props[name];
1936
+ return target;
1937
+ };
1938
+
1939
+ /* Determine whether an object is an array.
1940
+ @param a (object) the object to test
1941
+ @return (boolean) true if an array, false if not */
1942
+ function isArray(a) {
1943
+ return (a && a.constructor == Array);
1944
+ };
1945
+
1946
+ /* Invoke the datepicker functionality.
1947
+ @param options (string) a command, optionally followed by additional parameters or
1948
+ (object) settings for attaching new datepicker functionality
1949
+ @return (jQuery) jQuery object */
1950
+ $.fn.datepick = function(options){
1951
+ var otherArgs = Array.prototype.slice.call(arguments, 1);
1952
+ if (typeof options == 'string' && (options == 'isDisabled' ||
1953
+ options == 'getDate' || options == 'settings'))
1954
+ return $.datepick['_' + options + 'Datepick'].
1955
+ apply($.datepick, [this[0]].concat(otherArgs));
1956
+ if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
1957
+ return $.datepick['_' + options + 'Datepick'].
1958
+ apply($.datepick, [this[0]].concat(otherArgs));
1959
+ return this.each(function() {
1960
+ typeof options == 'string' ?
1961
+ $.datepick['_' + options + 'Datepick'].
1962
+ apply($.datepick, [this].concat(otherArgs)) :
1963
+ $.datepick._attachDatepick(this, options);
1964
+ });
1965
+ };
1966
+
1967
+ $.datepick = new Datepick(); // Singleton instance
1968
+
1969
+ $(function() {
1970
+ $(document).mousedown($.datepick._checkExternalClick).
1971
+ find('body').append($.datepick.dpDiv);
1972
+ });
1973
+
1974
+ })(jQuery);