iqvoc 3.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (376) hide show
  1. data/Gemfile +69 -0
  2. data/Gemfile.lock +134 -0
  3. data/LICENSE +13 -0
  4. data/README.md +68 -0
  5. data/Rakefile +23 -0
  6. data/app/controllers/application_controller.rb +125 -0
  7. data/app/controllers/collections/hierarchical_controller.rb +44 -0
  8. data/app/controllers/collections_controller.rb +124 -0
  9. data/app/controllers/concepts/alphabetical_controller.rb +39 -0
  10. data/app/controllers/concepts/hierarchical_controller.rb +74 -0
  11. data/app/controllers/concepts/untranslated_controller.rb +38 -0
  12. data/app/controllers/concepts/versions_controller.rb +119 -0
  13. data/app/controllers/concepts_controller.rb +174 -0
  14. data/app/controllers/dashboard_controller.rb +43 -0
  15. data/app/controllers/pages_controller.rb +22 -0
  16. data/app/controllers/rdf_controller.rb +43 -0
  17. data/app/controllers/search_results_controller.rb +101 -0
  18. data/app/controllers/triple_store_syncs_controller.rb +45 -0
  19. data/app/controllers/user_sessions_controller.rb +48 -0
  20. data/app/controllers/users_controller.rb +81 -0
  21. data/app/helpers/application_helper.rb +60 -0
  22. data/app/helpers/concepts_helper.rb +86 -0
  23. data/app/helpers/dashboard_helper.rb +46 -0
  24. data/app/helpers/rdf_helper.rb +63 -0
  25. data/app/helpers/search_results_helper.rb +32 -0
  26. data/app/models/collection/base.rb +161 -0
  27. data/app/models/collection/member/base.rb +23 -0
  28. data/app/models/collection/member/collection.rb +33 -0
  29. data/app/models/collection/member/concept.rb +33 -0
  30. data/app/models/collection/unordered.rb +18 -0
  31. data/app/models/concept/base.rb +418 -0
  32. data/app/models/concept/relation/base.rb +95 -0
  33. data/app/models/concept/relation/reverse_relation_extension.rb +49 -0
  34. data/app/models/concept/relation/skos/base.rb +37 -0
  35. data/app/models/concept/relation/skos/broader/base.rb +41 -0
  36. data/app/models/concept/relation/skos/broader/mono.rb +28 -0
  37. data/app/models/concept/relation/skos/broader/poly.rb +23 -0
  38. data/app/models/concept/relation/skos/narrower/base.rb +37 -0
  39. data/app/models/concept/relation/skos/related.rb +21 -0
  40. data/app/models/concept/skos/base.rb +28 -0
  41. data/app/models/label/base.rb +98 -0
  42. data/app/models/label/skos/base.rb +27 -0
  43. data/app/models/labeling/base.rb +81 -0
  44. data/app/models/labeling/skos/alt_label.rb +21 -0
  45. data/app/models/labeling/skos/base.rb +99 -0
  46. data/app/models/labeling/skos/hidden_label.rb +25 -0
  47. data/app/models/labeling/skos/pref_label.rb +30 -0
  48. data/app/models/match/base.rb +57 -0
  49. data/app/models/match/skos/base.rb +23 -0
  50. data/app/models/match/skos/broad_match.rb +21 -0
  51. data/app/models/match/skos/close_match.rb +21 -0
  52. data/app/models/match/skos/exact_match.rb +21 -0
  53. data/app/models/match/skos/mapping_relation.rb +21 -0
  54. data/app/models/match/skos/narrow_match.rb +21 -0
  55. data/app/models/match/skos/related_match.rb +21 -0
  56. data/app/models/note/annotated/base.rb +29 -0
  57. data/app/models/note/base.rb +127 -0
  58. data/app/models/note/skos/base.rb +52 -0
  59. data/app/models/note/skos/change_note.rb +38 -0
  60. data/app/models/note/skos/definition.rb +33 -0
  61. data/app/models/note/skos/editorial_note.rb +21 -0
  62. data/app/models/note/skos/example.rb +21 -0
  63. data/app/models/note/skos/history_note.rb +21 -0
  64. data/app/models/note/skos/scope_note.rb +21 -0
  65. data/app/models/origin_mapping.rb +58 -0
  66. data/app/models/rdf_store.rb +96 -0
  67. data/app/models/search_extension.rb +58 -0
  68. data/app/models/user.rb +49 -0
  69. data/app/models/user_session.rb +23 -0
  70. data/app/views/collections/_collection.html.erb +10 -0
  71. data/app/views/collections/_form.html.erb +47 -0
  72. data/app/views/collections/edit.html.erb +11 -0
  73. data/app/views/collections/index.html.erb +12 -0
  74. data/app/views/collections/new.html.erb +7 -0
  75. data/app/views/collections/show.html.erb +53 -0
  76. data/app/views/collections/show.iqrdf +22 -0
  77. data/app/views/concepts/_base_data.html.erb +72 -0
  78. data/app/views/concepts/_close_match.html.erb +16 -0
  79. data/app/views/concepts/_show_head.html.erb +23 -0
  80. data/app/views/concepts/_visualization.html.erb +9 -0
  81. data/app/views/concepts/alphabetical/_pref_labeling.html.erb +6 -0
  82. data/app/views/concepts/alphabetical/index.html.erb +17 -0
  83. data/app/views/concepts/edit.html.erb +32 -0
  84. data/app/views/concepts/hierarchical/_treeview.html.erb +20 -0
  85. data/app/views/concepts/hierarchical/index.html.erb +5 -0
  86. data/app/views/concepts/index.iqrdf +24 -0
  87. data/app/views/concepts/new.html.erb +3 -0
  88. data/app/views/concepts/show_published.html.erb +16 -0
  89. data/app/views/concepts/show_unpublished.html.erb +43 -0
  90. data/app/views/concepts/untranslated/index.html.erb +23 -0
  91. data/app/views/dashboard/index.html.erb +47 -0
  92. data/app/views/errors/access_denied.html.erb +3 -0
  93. data/app/views/errors/multiple_choices.html.erb +11 -0
  94. data/app/views/errors/not_found.html.erb +8 -0
  95. data/app/views/kaminari/_page.html.erb +6 -0
  96. data/app/views/kaminari/_paginator.html.erb +15 -0
  97. data/app/views/layouts/_controls.html.erb +37 -0
  98. data/app/views/layouts/_header.html.erb +1 -0
  99. data/app/views/layouts/_navigation.html.erb +27 -0
  100. data/app/views/layouts/_sections.html.erb +8 -0
  101. data/app/views/layouts/application.html.erb +83 -0
  102. data/app/views/pages/about.html.erb +77 -0
  103. data/app/views/partials/_rdf_logo.html.erb +4 -0
  104. data/app/views/partials/collection/_member.html.erb +14 -0
  105. data/app/views/partials/collection_label/_search_result.html.erb +5 -0
  106. data/app/views/partials/concept/_edit_link_base.html.erb +4 -0
  107. data/app/views/partials/concept/_inline_base.html.erb +4 -0
  108. data/app/views/partials/concept/_new_link_base.html.erb +4 -0
  109. data/app/views/partials/concept/relation/_base.html.erb +8 -0
  110. data/app/views/partials/concept/relation/_edit_base.html.erb +15 -0
  111. data/app/views/partials/concept/relation/skos/_narrower.html.erb +12 -0
  112. data/app/views/partials/concept/relation/skos/broader/_mono.html.erb +28 -0
  113. data/app/views/partials/concept/relation/skos/broader/_poly.html.erb +14 -0
  114. data/app/views/partials/labeling/skos/_base.html.erb +17 -0
  115. data/app/views/partials/labeling/skos/_edit_base.html.erb +7 -0
  116. data/app/views/partials/labeling/skos/_search_result.html.erb +12 -0
  117. data/app/views/partials/match/_base.html.erb +13 -0
  118. data/app/views/partials/match/_edit_base.html.erb +6 -0
  119. data/app/views/partials/note/_base.html.erb +15 -0
  120. data/app/views/partials/note/_edit_base.html.erb +28 -0
  121. data/app/views/partials/note/_note.html.erb +14 -0
  122. data/app/views/partials/note/_search_result.html.erb +8 -0
  123. data/app/views/partials/note/skos/_edit_change_note.html.erb +47 -0
  124. data/app/views/partials/note/skos/definition/_search_result.html.erb +8 -0
  125. data/app/views/rdf/show_concept.iqrdf +5 -0
  126. data/app/views/search_results/_head_contents.html.erb +4 -0
  127. data/app/views/search_results/_rdf_links.html.erb +4 -0
  128. data/app/views/search_results/index.html.erb +92 -0
  129. data/app/views/search_results/index.iqrdf +33 -0
  130. data/app/views/triple_store_syncs/new.html.erb +7 -0
  131. data/app/views/user_sessions/new.html.erb +11 -0
  132. data/app/views/users/_form.html.erb +45 -0
  133. data/app/views/users/_user_preference.html.erb +12 -0
  134. data/app/views/users/edit.html.erb +14 -0
  135. data/app/views/users/index.html.erb +29 -0
  136. data/app/views/users/new.html.erb +13 -0
  137. data/config/application.rb +82 -0
  138. data/config/boot.rb +29 -0
  139. data/config/database.template.yml +43 -0
  140. data/config/database.yml +40 -0
  141. data/config/deploy/common.rb +79 -0
  142. data/config/deploy/ec2.rb +43 -0
  143. data/config/deploy/history.rb +29 -0
  144. data/config/deploy/innoq.rb +37 -0
  145. data/config/deploy.rb +72 -0
  146. data/config/engine.rb +25 -0
  147. data/config/environment.rb +21 -0
  148. data/config/environments/development.rb +74 -0
  149. data/config/environments/production.rb +65 -0
  150. data/config/environments/production.template.rb +65 -0
  151. data/config/environments/production_internal.rb +65 -0
  152. data/config/environments/test.rb +51 -0
  153. data/config/initializers/action_view.rb +23 -0
  154. data/config/initializers/active_record.rb +18 -0
  155. data/config/initializers/backtrace_silencers.rb +23 -0
  156. data/config/initializers/inflections.rb +26 -0
  157. data/config/initializers/iqvoc.rb +50 -0
  158. data/config/initializers/jdbc.rb +23 -0
  159. data/config/initializers/kaminari_config.rb +8 -0
  160. data/config/initializers/language.rb +6 -0
  161. data/config/initializers/mime_types.rb +24 -0
  162. data/config/initializers/secret_token.rb +29 -0
  163. data/config/initializers/secret_token.rb.template +29 -0
  164. data/config/initializers/session_store.rb +24 -0
  165. data/config/locales/activerecord.de.yml +135 -0
  166. data/config/locales/activerecord.en.yml +135 -0
  167. data/config/locales/authlogic.de.yml +38 -0
  168. data/config/locales/authlogic.en.yml +38 -0
  169. data/config/locales/de.yml +326 -0
  170. data/config/locales/defaults.de.yml +153 -0
  171. data/config/locales/en.yml +332 -0
  172. data/config/routes.rb +53 -0
  173. data/config/warble.rb +158 -0
  174. data/db/iqvoc_test.sqlite3 +0 -0
  175. data/db/migrate/20100927101502_create_schema.rb +174 -0
  176. data/db/migrate/20101125141218_add_collection_tables.rb +32 -0
  177. data/db/migrate/20101129161528_add_type_to_collections.rb +24 -0
  178. data/db/migrate/20101202094602_add_origin_to_collections.rb +25 -0
  179. data/db/migrate/20101202135420_rename_collection_contents_to_collection_members.rb +25 -0
  180. data/db/migrate/20101208103531_add_type_to_collection_contents.rb +27 -0
  181. data/db/migrate/20101210153916_add_indexes_to_collections.rb +25 -0
  182. data/db/migrate/20110204121244_create_collection_labels.rb +32 -0
  183. data/db/migrate/20110208084250_change_origin_lengths.rb +27 -0
  184. data/db/migrate/20110328124300_discard_collection_specifics.rb +27 -0
  185. data/db/migrate/20110408120357_remove_classifications_and_classifiers.rb +32 -0
  186. data/db/migrate/20110408120740_remove_xl_specfic_stuff.rb +39 -0
  187. data/db/migrate/20110420133640_change_value_in_notes.rb +8 -0
  188. data/db/migrate/20110427120534_add_published_at_to_labels.rb +9 -0
  189. data/db/migrate/20110510162719_use_mono_hierarchy_instead_of_poly_hierarchy.rb +13 -0
  190. data/db/migrate/20110512132624_extend_notes_value_field_length.rb +8 -0
  191. data/db/migrate/20110525103100_separate_note_annotation_predicates.rb +38 -0
  192. data/db/migrate/20110615134040_change_umt_note_annotations_to_dct.rb +9 -0
  193. data/db/schema.rb +127 -0
  194. data/db/seeds.rb +37 -0
  195. data/iqvoc.gemspec +27 -0
  196. data/lib/engine_tasks/assets.rake +49 -0
  197. data/lib/engine_tasks/db.rake +18 -0
  198. data/lib/engine_tasks/release.rake +118 -0
  199. data/lib/iqvoc/ability.rb +44 -0
  200. data/lib/iqvoc/data_helper.rb +27 -0
  201. data/lib/iqvoc/deep_cloning.rb +92 -0
  202. data/lib/iqvoc/rdf_helper.rb +67 -0
  203. data/lib/iqvoc/skos_importer.rb +144 -0
  204. data/lib/iqvoc/version.rb +19 -0
  205. data/lib/iqvoc/versioning.rb +151 -0
  206. data/lib/iqvoc.rb +228 -0
  207. data/lib/maker.rb +144 -0
  208. data/lib/ojdbc14.jar +0 -0
  209. data/lib/string.rb +23 -0
  210. data/lib/tasks/importer.rake +16 -0
  211. data/lib/tasks/jdbc.rake +24 -0
  212. data/public/404.html +26 -0
  213. data/public/422.html +26 -0
  214. data/public/500.html +26 -0
  215. data/public/favicon.ico +0 -0
  216. data/public/images/iqvoc/add.png +0 -0
  217. data/public/images/iqvoc/arrow_down.gif +0 -0
  218. data/public/images/iqvoc/arrow_up.gif +0 -0
  219. data/public/images/iqvoc/footer.png +0 -0
  220. data/public/images/iqvoc/go_there.png +0 -0
  221. data/public/images/iqvoc/header.png +0 -0
  222. data/public/images/iqvoc/header_long.png +0 -0
  223. data/public/images/iqvoc/iqvoc.png +0 -0
  224. data/public/images/iqvoc/note_add.png +0 -0
  225. data/public/images/iqvoc/note_delete.png +0 -0
  226. data/public/images/iqvoc/note_edit.png +0 -0
  227. data/public/images/iqvoc/ok.png +0 -0
  228. data/public/images/iqvoc/rails.png +0 -0
  229. data/public/images/iqvoc/rdf_flyer.gif +0 -0
  230. data/public/images/iqvoc/red_arrow.png +0 -0
  231. data/public/images/iqvoc/remove.png +0 -0
  232. data/public/images/iqvoc/shadow.png +0 -0
  233. data/public/images/iqvoc/spinner.gif +0 -0
  234. data/public/images/iqvoc/tokenizer_delete.png +0 -0
  235. data/public/images/iqvoc/tokenizer_pencile.png +0 -0
  236. data/public/images/iqvoc/tokenizer_show.png +0 -0
  237. data/public/images/iqvoc/unfinished.png +0 -0
  238. data/public/javascripts/iqvoc/application.js +123 -0
  239. data/public/javascripts/iqvoc/entityselect.js +121 -0
  240. data/public/javascripts/iqvoc/excanvas.js +35 -0
  241. data/public/javascripts/iqvoc/iqvoc.js +118 -0
  242. data/public/javascripts/iqvoc/jit_rgraph.js +153 -0
  243. data/public/javascripts/iqvoc/jquery-1.6.2.min.js +18 -0
  244. data/public/javascripts/iqvoc/jquery-treeview/changelog.txt +29 -0
  245. data/public/javascripts/iqvoc/jquery-treeview/demo/async.html +44 -0
  246. data/public/javascripts/iqvoc/jquery-treeview/demo/bg.gif +0 -0
  247. data/public/javascripts/iqvoc/jquery-treeview/demo/demo.js +43 -0
  248. data/public/javascripts/iqvoc/jquery-treeview/demo/images.html +56 -0
  249. data/public/javascripts/iqvoc/jquery-treeview/demo/index.html +340 -0
  250. data/public/javascripts/iqvoc/jquery-treeview/demo/large.html +559 -0
  251. data/public/javascripts/iqvoc/jquery-treeview/demo/prerendered.html +621 -0
  252. data/public/javascripts/iqvoc/jquery-treeview/demo/screen.css +24 -0
  253. data/public/javascripts/iqvoc/jquery-treeview/demo/simple.html +82 -0
  254. data/public/javascripts/iqvoc/jquery-treeview/demo/source.php +87 -0
  255. data/public/javascripts/iqvoc/jquery-treeview/demo/source.phps +87 -0
  256. data/public/javascripts/iqvoc/jquery-treeview/images/ajax-loader.gif +0 -0
  257. data/public/javascripts/iqvoc/jquery-treeview/images/file.gif +0 -0
  258. data/public/javascripts/iqvoc/jquery-treeview/images/folder-closed.gif +0 -0
  259. data/public/javascripts/iqvoc/jquery-treeview/images/folder.gif +0 -0
  260. data/public/javascripts/iqvoc/jquery-treeview/images/minus.gif +0 -0
  261. data/public/javascripts/iqvoc/jquery-treeview/images/plus.gif +0 -0
  262. data/public/javascripts/iqvoc/jquery-treeview/images/treeview-black-line.gif +0 -0
  263. data/public/javascripts/iqvoc/jquery-treeview/images/treeview-black.gif +0 -0
  264. data/public/javascripts/iqvoc/jquery-treeview/images/treeview-default-line.gif +0 -0
  265. data/public/javascripts/iqvoc/jquery-treeview/images/treeview-default.gif +0 -0
  266. data/public/javascripts/iqvoc/jquery-treeview/images/treeview-famfamfam-line.gif +0 -0
  267. data/public/javascripts/iqvoc/jquery-treeview/images/treeview-famfamfam.gif +0 -0
  268. data/public/javascripts/iqvoc/jquery-treeview/images/treeview-gray-line.gif +0 -0
  269. data/public/javascripts/iqvoc/jquery-treeview/images/treeview-gray.gif +0 -0
  270. data/public/javascripts/iqvoc/jquery-treeview/images/treeview-red-line.gif +0 -0
  271. data/public/javascripts/iqvoc/jquery-treeview/images/treeview-red.gif +0 -0
  272. data/public/javascripts/iqvoc/jquery-treeview/jquery.treeview.async.js +82 -0
  273. data/public/javascripts/iqvoc/jquery-treeview/jquery.treeview.css +75 -0
  274. data/public/javascripts/iqvoc/jquery-treeview/jquery.treeview.js +251 -0
  275. data/public/javascripts/iqvoc/jquery-treeview/jquery.treeview.min.js +15 -0
  276. data/public/javascripts/iqvoc/jquery-treeview/jquery.treeview.pack.js +16 -0
  277. data/public/javascripts/iqvoc/jquery-treeview/lib/jquery.cookie.js +92 -0
  278. data/public/javascripts/iqvoc/jquery-treeview/lib/jquery.js +3363 -0
  279. data/public/javascripts/iqvoc/jquery-treeview/todo +8 -0
  280. data/public/javascripts/iqvoc/jquery-ui-1.8.13.custom.js +3229 -0
  281. data/public/javascripts/iqvoc/jquery-ui-1.8.13.custom.min.js +163 -0
  282. data/public/javascripts/iqvoc/jquery-ui.datepicker-de.js +22 -0
  283. data/public/javascripts/iqvoc/json2.js +480 -0
  284. data/public/javascripts/iqvoc/langselect.js +73 -0
  285. data/public/javascripts/iqvoc/rails.js +132 -0
  286. data/public/javascripts/iqvoc/storage.js +122 -0
  287. data/public/javascripts/iqvoc/visualization.js +321 -0
  288. data/public/robots.txt +5 -0
  289. data/public/stylesheets/iqvoc/blueprint/ie.css +35 -0
  290. data/public/stylesheets/iqvoc/blueprint/plugins/buttons/icons/cross.png +0 -0
  291. data/public/stylesheets/iqvoc/blueprint/plugins/buttons/icons/key.png +0 -0
  292. data/public/stylesheets/iqvoc/blueprint/plugins/buttons/icons/tick.png +0 -0
  293. data/public/stylesheets/iqvoc/blueprint/plugins/buttons/readme.txt +32 -0
  294. data/public/stylesheets/iqvoc/blueprint/plugins/buttons/screen.css +97 -0
  295. data/public/stylesheets/iqvoc/blueprint/plugins/fancy-type/readme.txt +14 -0
  296. data/public/stylesheets/iqvoc/blueprint/plugins/fancy-type/screen.css +71 -0
  297. data/public/stylesheets/iqvoc/blueprint/plugins/link-icons/icons/doc.png +0 -0
  298. data/public/stylesheets/iqvoc/blueprint/plugins/link-icons/icons/email.png +0 -0
  299. data/public/stylesheets/iqvoc/blueprint/plugins/link-icons/icons/external.png +0 -0
  300. data/public/stylesheets/iqvoc/blueprint/plugins/link-icons/icons/feed.png +0 -0
  301. data/public/stylesheets/iqvoc/blueprint/plugins/link-icons/icons/im.png +0 -0
  302. data/public/stylesheets/iqvoc/blueprint/plugins/link-icons/icons/pdf.png +0 -0
  303. data/public/stylesheets/iqvoc/blueprint/plugins/link-icons/icons/visited.png +0 -0
  304. data/public/stylesheets/iqvoc/blueprint/plugins/link-icons/icons/xls.png +0 -0
  305. data/public/stylesheets/iqvoc/blueprint/plugins/link-icons/readme.txt +18 -0
  306. data/public/stylesheets/iqvoc/blueprint/plugins/link-icons/screen.css +40 -0
  307. data/public/stylesheets/iqvoc/blueprint/plugins/rtl/readme.txt +10 -0
  308. data/public/stylesheets/iqvoc/blueprint/plugins/rtl/screen.css +110 -0
  309. data/public/stylesheets/iqvoc/blueprint/print.css +29 -0
  310. data/public/stylesheets/iqvoc/blueprint/screen.css +258 -0
  311. data/public/stylesheets/iqvoc/blueprint/src/forms.css +65 -0
  312. data/public/stylesheets/iqvoc/blueprint/src/grid.css +280 -0
  313. data/public/stylesheets/iqvoc/blueprint/src/grid.png +0 -0
  314. data/public/stylesheets/iqvoc/blueprint/src/ie.css +76 -0
  315. data/public/stylesheets/iqvoc/blueprint/src/print.css +85 -0
  316. data/public/stylesheets/iqvoc/blueprint/src/reset.css +45 -0
  317. data/public/stylesheets/iqvoc/blueprint/src/typography.css +106 -0
  318. data/public/stylesheets/iqvoc/forms.css +71 -0
  319. data/public/stylesheets/iqvoc/images/back.png +0 -0
  320. data/public/stylesheets/iqvoc/images/branch.png +0 -0
  321. data/public/stylesheets/iqvoc/images/categ.png +0 -0
  322. data/public/stylesheets/iqvoc/images/categ_open.png +0 -0
  323. data/public/stylesheets/iqvoc/images/go_there.png +0 -0
  324. data/public/stylesheets/iqvoc/images/iqvoc.png +0 -0
  325. data/public/stylesheets/iqvoc/images/leaf_end.png +0 -0
  326. data/public/stylesheets/iqvoc/images/leaf_end_filled.png +0 -0
  327. data/public/stylesheets/iqvoc/images/leaf_mid.png +0 -0
  328. data/public/stylesheets/iqvoc/images/leaf_mid_filled.png +0 -0
  329. data/public/stylesheets/iqvoc/images/leaf_nothing.png +0 -0
  330. data/public/stylesheets/iqvoc/images/leaf_only.png +0 -0
  331. data/public/stylesheets/iqvoc/images/leaf_only_filled.png +0 -0
  332. data/public/stylesheets/iqvoc/images/leaf_top.png +0 -0
  333. data/public/stylesheets/iqvoc/images/leaf_top_filled.png +0 -0
  334. data/public/stylesheets/iqvoc/images/nothing.png +0 -0
  335. data/public/stylesheets/iqvoc/images/top_01.png +0 -0
  336. data/public/stylesheets/iqvoc/images/trunk.png +0 -0
  337. data/public/stylesheets/iqvoc/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  338. data/public/stylesheets/iqvoc/images/ui-bg_flat_55_fbec88_40x100.png +0 -0
  339. data/public/stylesheets/iqvoc/images/ui-bg_glass_75_d0e5f5_1x400.png +0 -0
  340. data/public/stylesheets/iqvoc/images/ui-bg_glass_85_dfeffc_1x400.png +0 -0
  341. data/public/stylesheets/iqvoc/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  342. data/public/stylesheets/iqvoc/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png +0 -0
  343. data/public/stylesheets/iqvoc/images/ui-bg_inset-hard_100_f5f8f9_1x100.png +0 -0
  344. data/public/stylesheets/iqvoc/images/ui-bg_inset-hard_100_fcfdfd_1x100.png +0 -0
  345. data/public/stylesheets/iqvoc/images/ui-icons_217bc0_256x240.png +0 -0
  346. data/public/stylesheets/iqvoc/images/ui-icons_2e83ff_256x240.png +0 -0
  347. data/public/stylesheets/iqvoc/images/ui-icons_469bdd_256x240.png +0 -0
  348. data/public/stylesheets/iqvoc/images/ui-icons_6da8d5_256x240.png +0 -0
  349. data/public/stylesheets/iqvoc/images/ui-icons_cd0a0a_256x240.png +0 -0
  350. data/public/stylesheets/iqvoc/images/ui-icons_d8e7f3_256x240.png +0 -0
  351. data/public/stylesheets/iqvoc/images/ui-icons_f9bd01_256x240.png +0 -0
  352. data/public/stylesheets/iqvoc/iqvoc.css +477 -0
  353. data/public/stylesheets/iqvoc/jquery-ui-1.8.13.custom.css +415 -0
  354. data/public/stylesheets/iqvoc/widgets.css +81 -0
  355. data/test/factories.rb +74 -0
  356. data/test/integration/alphabetical_test.rb +53 -0
  357. data/test/integration/authentication_test.rb +41 -0
  358. data/test/integration/browse_concepts_and_labels_test.rb +61 -0
  359. data/test/integration/browse_static_pages_test.rb +29 -0
  360. data/test/integration/client_augmentation_test.rb +42 -0
  361. data/test/integration/client_edit_concept_test.rb +72 -0
  362. data/test/integration/collection_circularity_test.rb +110 -0
  363. data/test/integration/concept_test.rb +61 -0
  364. data/test/integration/edit_concepts_test.rb +40 -0
  365. data/test/integration/note_annotations_test.rb +86 -0
  366. data/test/integration/search_test.rb +205 -0
  367. data/test/integration/tree_test.rb +31 -0
  368. data/test/integration/untranslated_test.rb +60 -0
  369. data/test/integration_test_helper.rb +45 -0
  370. data/test/performance/browsing_test.rb +25 -0
  371. data/test/test_helper.rb +29 -0
  372. data/test/unit/concept_test.rb +93 -0
  373. data/test/unit/note_test.rb +32 -0
  374. data/test/unit/origin_mapping_test.rb +70 -0
  375. data/test/unit/skos_import_test.rb +100 -0
  376. metadata +522 -0
@@ -0,0 +1,3229 @@
1
+ /*!
2
+ * jQuery UI 1.8.13
3
+ *
4
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5
+ * Dual licensed under the MIT or GPL Version 2 licenses.
6
+ * http://jquery.org/license
7
+ *
8
+ * http://docs.jquery.com/UI
9
+ */
10
+ (function( $, undefined ) {
11
+
12
+ // prevent duplicate loading
13
+ // this is only a problem because we proxy existing functions
14
+ // and we don't want to double proxy them
15
+ $.ui = $.ui || {};
16
+ if ( $.ui.version ) {
17
+ return;
18
+ }
19
+
20
+ $.extend( $.ui, {
21
+ version: "1.8.13",
22
+
23
+ keyCode: {
24
+ ALT: 18,
25
+ BACKSPACE: 8,
26
+ CAPS_LOCK: 20,
27
+ COMMA: 188,
28
+ COMMAND: 91,
29
+ COMMAND_LEFT: 91, // COMMAND
30
+ COMMAND_RIGHT: 93,
31
+ CONTROL: 17,
32
+ DELETE: 46,
33
+ DOWN: 40,
34
+ END: 35,
35
+ ENTER: 13,
36
+ ESCAPE: 27,
37
+ HOME: 36,
38
+ INSERT: 45,
39
+ LEFT: 37,
40
+ MENU: 93, // COMMAND_RIGHT
41
+ NUMPAD_ADD: 107,
42
+ NUMPAD_DECIMAL: 110,
43
+ NUMPAD_DIVIDE: 111,
44
+ NUMPAD_ENTER: 108,
45
+ NUMPAD_MULTIPLY: 106,
46
+ NUMPAD_SUBTRACT: 109,
47
+ PAGE_DOWN: 34,
48
+ PAGE_UP: 33,
49
+ PERIOD: 190,
50
+ RIGHT: 39,
51
+ SHIFT: 16,
52
+ SPACE: 32,
53
+ TAB: 9,
54
+ UP: 38,
55
+ WINDOWS: 91 // COMMAND
56
+ }
57
+ });
58
+
59
+ // plugins
60
+ $.fn.extend({
61
+ _focus: $.fn.focus,
62
+ focus: function( delay, fn ) {
63
+ return typeof delay === "number" ?
64
+ this.each(function() {
65
+ var elem = this;
66
+ setTimeout(function() {
67
+ $( elem ).focus();
68
+ if ( fn ) {
69
+ fn.call( elem );
70
+ }
71
+ }, delay );
72
+ }) :
73
+ this._focus.apply( this, arguments );
74
+ },
75
+
76
+ scrollParent: function() {
77
+ var scrollParent;
78
+ if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
79
+ scrollParent = this.parents().filter(function() {
80
+ return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
81
+ }).eq(0);
82
+ } else {
83
+ scrollParent = this.parents().filter(function() {
84
+ return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
85
+ }).eq(0);
86
+ }
87
+
88
+ return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
89
+ },
90
+
91
+ zIndex: function( zIndex ) {
92
+ if ( zIndex !== undefined ) {
93
+ return this.css( "zIndex", zIndex );
94
+ }
95
+
96
+ if ( this.length ) {
97
+ var elem = $( this[ 0 ] ), position, value;
98
+ while ( elem.length && elem[ 0 ] !== document ) {
99
+ // Ignore z-index if position is set to a value where z-index is ignored by the browser
100
+ // This makes behavior of this function consistent across browsers
101
+ // WebKit always returns auto if the element is positioned
102
+ position = elem.css( "position" );
103
+ if ( position === "absolute" || position === "relative" || position === "fixed" ) {
104
+ // IE returns 0 when zIndex is not specified
105
+ // other browsers return a string
106
+ // we ignore the case of nested elements with an explicit value of 0
107
+ // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
108
+ value = parseInt( elem.css( "zIndex" ), 10 );
109
+ if ( !isNaN( value ) && value !== 0 ) {
110
+ return value;
111
+ }
112
+ }
113
+ elem = elem.parent();
114
+ }
115
+ }
116
+
117
+ return 0;
118
+ },
119
+
120
+ disableSelection: function() {
121
+ return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
122
+ ".ui-disableSelection", function( event ) {
123
+ event.preventDefault();
124
+ });
125
+ },
126
+
127
+ enableSelection: function() {
128
+ return this.unbind( ".ui-disableSelection" );
129
+ }
130
+ });
131
+
132
+ $.each( [ "Width", "Height" ], function( i, name ) {
133
+ var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
134
+ type = name.toLowerCase(),
135
+ orig = {
136
+ innerWidth: $.fn.innerWidth,
137
+ innerHeight: $.fn.innerHeight,
138
+ outerWidth: $.fn.outerWidth,
139
+ outerHeight: $.fn.outerHeight
140
+ };
141
+
142
+ function reduce( elem, size, border, margin ) {
143
+ $.each( side, function() {
144
+ size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
145
+ if ( border ) {
146
+ size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
147
+ }
148
+ if ( margin ) {
149
+ size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
150
+ }
151
+ });
152
+ return size;
153
+ }
154
+
155
+ $.fn[ "inner" + name ] = function( size ) {
156
+ if ( size === undefined ) {
157
+ return orig[ "inner" + name ].call( this );
158
+ }
159
+
160
+ return this.each(function() {
161
+ $( this ).css( type, reduce( this, size ) + "px" );
162
+ });
163
+ };
164
+
165
+ $.fn[ "outer" + name] = function( size, margin ) {
166
+ if ( typeof size !== "number" ) {
167
+ return orig[ "outer" + name ].call( this, size );
168
+ }
169
+
170
+ return this.each(function() {
171
+ $( this).css( type, reduce( this, size, true, margin ) + "px" );
172
+ });
173
+ };
174
+ });
175
+
176
+ // selectors
177
+ function focusable( element, isTabIndexNotNaN ) {
178
+ var nodeName = element.nodeName.toLowerCase();
179
+ if ( "area" === nodeName ) {
180
+ var map = element.parentNode,
181
+ mapName = map.name,
182
+ img;
183
+ if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
184
+ return false;
185
+ }
186
+ img = $( "img[usemap=#" + mapName + "]" )[0];
187
+ return !!img && visible( img );
188
+ }
189
+ return ( /input|select|textarea|button|object/.test( nodeName )
190
+ ? !element.disabled
191
+ : "a" == nodeName
192
+ ? element.href || isTabIndexNotNaN
193
+ : isTabIndexNotNaN)
194
+ // the element and all of its ancestors must be visible
195
+ && visible( element );
196
+ }
197
+
198
+ function visible( element ) {
199
+ return !$( element ).parents().andSelf().filter(function() {
200
+ return $.curCSS( this, "visibility" ) === "hidden" ||
201
+ $.expr.filters.hidden( this );
202
+ }).length;
203
+ }
204
+
205
+ $.extend( $.expr[ ":" ], {
206
+ data: function( elem, i, match ) {
207
+ return !!$.data( elem, match[ 3 ] );
208
+ },
209
+
210
+ focusable: function( element ) {
211
+ return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
212
+ },
213
+
214
+ tabbable: function( element ) {
215
+ var tabIndex = $.attr( element, "tabindex" ),
216
+ isTabIndexNaN = isNaN( tabIndex );
217
+ return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
218
+ }
219
+ });
220
+
221
+ // support
222
+ $(function() {
223
+ var body = document.body,
224
+ div = body.appendChild( div = document.createElement( "div" ) );
225
+
226
+ $.extend( div.style, {
227
+ minHeight: "100px",
228
+ height: "auto",
229
+ padding: 0,
230
+ borderWidth: 0
231
+ });
232
+
233
+ $.support.minHeight = div.offsetHeight === 100;
234
+ $.support.selectstart = "onselectstart" in div;
235
+
236
+ // set display to none to avoid a layout bug in IE
237
+ // http://dev.jquery.com/ticket/4014
238
+ body.removeChild( div ).style.display = "none";
239
+ });
240
+
241
+
242
+
243
+
244
+
245
+ // deprecated
246
+ $.extend( $.ui, {
247
+ // $.ui.plugin is deprecated. Use the proxy pattern instead.
248
+ plugin: {
249
+ add: function( module, option, set ) {
250
+ var proto = $.ui[ module ].prototype;
251
+ for ( var i in set ) {
252
+ proto.plugins[ i ] = proto.plugins[ i ] || [];
253
+ proto.plugins[ i ].push( [ option, set[ i ] ] );
254
+ }
255
+ },
256
+ call: function( instance, name, args ) {
257
+ var set = instance.plugins[ name ];
258
+ if ( !set || !instance.element[ 0 ].parentNode ) {
259
+ return;
260
+ }
261
+
262
+ for ( var i = 0; i < set.length; i++ ) {
263
+ if ( instance.options[ set[ i ][ 0 ] ] ) {
264
+ set[ i ][ 1 ].apply( instance.element, args );
265
+ }
266
+ }
267
+ }
268
+ },
269
+
270
+ // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
271
+ contains: function( a, b ) {
272
+ return document.compareDocumentPosition ?
273
+ a.compareDocumentPosition( b ) & 16 :
274
+ a !== b && a.contains( b );
275
+ },
276
+
277
+ // only used by resizable
278
+ hasScroll: function( el, a ) {
279
+
280
+ //If overflow is hidden, the element might have extra content, but the user wants to hide it
281
+ if ( $( el ).css( "overflow" ) === "hidden") {
282
+ return false;
283
+ }
284
+
285
+ var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
286
+ has = false;
287
+
288
+ if ( el[ scroll ] > 0 ) {
289
+ return true;
290
+ }
291
+
292
+ // TODO: determine which cases actually cause this to happen
293
+ // if the element doesn't have the scroll set, see if it's possible to
294
+ // set the scroll
295
+ el[ scroll ] = 1;
296
+ has = ( el[ scroll ] > 0 );
297
+ el[ scroll ] = 0;
298
+ return has;
299
+ },
300
+
301
+ // these are odd functions, fix the API or move into individual plugins
302
+ isOverAxis: function( x, reference, size ) {
303
+ //Determines when x coordinate is over "b" element axis
304
+ return ( x > reference ) && ( x < ( reference + size ) );
305
+ },
306
+ isOver: function( y, x, top, left, height, width ) {
307
+ //Determines when x, y coordinates is over "b" element
308
+ return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
309
+ }
310
+ });
311
+
312
+ })( jQuery );
313
+ /*!
314
+ * jQuery UI Widget 1.8.13
315
+ *
316
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
317
+ * Dual licensed under the MIT or GPL Version 2 licenses.
318
+ * http://jquery.org/license
319
+ *
320
+ * http://docs.jquery.com/UI/Widget
321
+ */
322
+ (function( $, undefined ) {
323
+
324
+ // jQuery 1.4+
325
+ if ( $.cleanData ) {
326
+ var _cleanData = $.cleanData;
327
+ $.cleanData = function( elems ) {
328
+ for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
329
+ $( elem ).triggerHandler( "remove" );
330
+ }
331
+ _cleanData( elems );
332
+ };
333
+ } else {
334
+ var _remove = $.fn.remove;
335
+ $.fn.remove = function( selector, keepData ) {
336
+ return this.each(function() {
337
+ if ( !keepData ) {
338
+ if ( !selector || $.filter( selector, [ this ] ).length ) {
339
+ $( "*", this ).add( [ this ] ).each(function() {
340
+ $( this ).triggerHandler( "remove" );
341
+ });
342
+ }
343
+ }
344
+ return _remove.call( $(this), selector, keepData );
345
+ });
346
+ };
347
+ }
348
+
349
+ $.widget = function( name, base, prototype ) {
350
+ var namespace = name.split( "." )[ 0 ],
351
+ fullName;
352
+ name = name.split( "." )[ 1 ];
353
+ fullName = namespace + "-" + name;
354
+
355
+ if ( !prototype ) {
356
+ prototype = base;
357
+ base = $.Widget;
358
+ }
359
+
360
+ // create selector for plugin
361
+ $.expr[ ":" ][ fullName ] = function( elem ) {
362
+ return !!$.data( elem, name );
363
+ };
364
+
365
+ $[ namespace ] = $[ namespace ] || {};
366
+ $[ namespace ][ name ] = function( options, element ) {
367
+ // allow instantiation without initializing for simple inheritance
368
+ if ( arguments.length ) {
369
+ this._createWidget( options, element );
370
+ }
371
+ };
372
+
373
+ var basePrototype = new base();
374
+ // we need to make the options hash a property directly on the new instance
375
+ // otherwise we'll modify the options hash on the prototype that we're
376
+ // inheriting from
377
+ // $.each( basePrototype, function( key, val ) {
378
+ // if ( $.isPlainObject(val) ) {
379
+ // basePrototype[ key ] = $.extend( {}, val );
380
+ // }
381
+ // });
382
+ basePrototype.options = $.extend( true, {}, basePrototype.options );
383
+ $[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
384
+ namespace: namespace,
385
+ widgetName: name,
386
+ widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
387
+ widgetBaseClass: fullName
388
+ }, prototype );
389
+
390
+ $.widget.bridge( name, $[ namespace ][ name ] );
391
+ };
392
+
393
+ $.widget.bridge = function( name, object ) {
394
+ $.fn[ name ] = function( options ) {
395
+ var isMethodCall = typeof options === "string",
396
+ args = Array.prototype.slice.call( arguments, 1 ),
397
+ returnValue = this;
398
+
399
+ // allow multiple hashes to be passed on init
400
+ options = !isMethodCall && args.length ?
401
+ $.extend.apply( null, [ true, options ].concat(args) ) :
402
+ options;
403
+
404
+ // prevent calls to internal methods
405
+ if ( isMethodCall && options.charAt( 0 ) === "_" ) {
406
+ return returnValue;
407
+ }
408
+
409
+ if ( isMethodCall ) {
410
+ this.each(function() {
411
+ var instance = $.data( this, name ),
412
+ methodValue = instance && $.isFunction( instance[options] ) ?
413
+ instance[ options ].apply( instance, args ) :
414
+ instance;
415
+ // TODO: add this back in 1.9 and use $.error() (see #5972)
416
+ // if ( !instance ) {
417
+ // throw "cannot call methods on " + name + " prior to initialization; " +
418
+ // "attempted to call method '" + options + "'";
419
+ // }
420
+ // if ( !$.isFunction( instance[options] ) ) {
421
+ // throw "no such method '" + options + "' for " + name + " widget instance";
422
+ // }
423
+ // var methodValue = instance[ options ].apply( instance, args );
424
+ if ( methodValue !== instance && methodValue !== undefined ) {
425
+ returnValue = methodValue;
426
+ return false;
427
+ }
428
+ });
429
+ } else {
430
+ this.each(function() {
431
+ var instance = $.data( this, name );
432
+ if ( instance ) {
433
+ instance.option( options || {} )._init();
434
+ } else {
435
+ $.data( this, name, new object( options, this ) );
436
+ }
437
+ });
438
+ }
439
+
440
+ return returnValue;
441
+ };
442
+ };
443
+
444
+ $.Widget = function( options, element ) {
445
+ // allow instantiation without initializing for simple inheritance
446
+ if ( arguments.length ) {
447
+ this._createWidget( options, element );
448
+ }
449
+ };
450
+
451
+ $.Widget.prototype = {
452
+ widgetName: "widget",
453
+ widgetEventPrefix: "",
454
+ options: {
455
+ disabled: false
456
+ },
457
+ _createWidget: function( options, element ) {
458
+ // $.widget.bridge stores the plugin instance, but we do it anyway
459
+ // so that it's stored even before the _create function runs
460
+ $.data( element, this.widgetName, this );
461
+ this.element = $( element );
462
+ this.options = $.extend( true, {},
463
+ this.options,
464
+ this._getCreateOptions(),
465
+ options );
466
+
467
+ var self = this;
468
+ this.element.bind( "remove." + this.widgetName, function() {
469
+ self.destroy();
470
+ });
471
+
472
+ this._create();
473
+ this._trigger( "create" );
474
+ this._init();
475
+ },
476
+ _getCreateOptions: function() {
477
+ return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
478
+ },
479
+ _create: function() {},
480
+ _init: function() {},
481
+
482
+ destroy: function() {
483
+ this.element
484
+ .unbind( "." + this.widgetName )
485
+ .removeData( this.widgetName );
486
+ this.widget()
487
+ .unbind( "." + this.widgetName )
488
+ .removeAttr( "aria-disabled" )
489
+ .removeClass(
490
+ this.widgetBaseClass + "-disabled " +
491
+ "ui-state-disabled" );
492
+ },
493
+
494
+ widget: function() {
495
+ return this.element;
496
+ },
497
+
498
+ option: function( key, value ) {
499
+ var options = key;
500
+
501
+ if ( arguments.length === 0 ) {
502
+ // don't return a reference to the internal hash
503
+ return $.extend( {}, this.options );
504
+ }
505
+
506
+ if (typeof key === "string" ) {
507
+ if ( value === undefined ) {
508
+ return this.options[ key ];
509
+ }
510
+ options = {};
511
+ options[ key ] = value;
512
+ }
513
+
514
+ this._setOptions( options );
515
+
516
+ return this;
517
+ },
518
+ _setOptions: function( options ) {
519
+ var self = this;
520
+ $.each( options, function( key, value ) {
521
+ self._setOption( key, value );
522
+ });
523
+
524
+ return this;
525
+ },
526
+ _setOption: function( key, value ) {
527
+ this.options[ key ] = value;
528
+
529
+ if ( key === "disabled" ) {
530
+ this.widget()
531
+ [ value ? "addClass" : "removeClass"](
532
+ this.widgetBaseClass + "-disabled" + " " +
533
+ "ui-state-disabled" )
534
+ .attr( "aria-disabled", value );
535
+ }
536
+
537
+ return this;
538
+ },
539
+
540
+ enable: function() {
541
+ return this._setOption( "disabled", false );
542
+ },
543
+ disable: function() {
544
+ return this._setOption( "disabled", true );
545
+ },
546
+
547
+ _trigger: function( type, event, data ) {
548
+ var callback = this.options[ type ];
549
+
550
+ event = $.Event( event );
551
+ event.type = ( type === this.widgetEventPrefix ?
552
+ type :
553
+ this.widgetEventPrefix + type ).toLowerCase();
554
+ data = data || {};
555
+
556
+ // copy original event properties over to the new event
557
+ // this would happen if we could call $.event.fix instead of $.Event
558
+ // but we don't have a way to force an event to be fixed multiple times
559
+ if ( event.originalEvent ) {
560
+ for ( var i = $.event.props.length, prop; i; ) {
561
+ prop = $.event.props[ --i ];
562
+ event[ prop ] = event.originalEvent[ prop ];
563
+ }
564
+ }
565
+
566
+ this.element.trigger( event, data );
567
+
568
+ return !( $.isFunction(callback) &&
569
+ callback.call( this.element[0], event, data ) === false ||
570
+ event.isDefaultPrevented() );
571
+ }
572
+ };
573
+
574
+ })( jQuery );
575
+ /*
576
+ * jQuery UI Position 1.8.13
577
+ *
578
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
579
+ * Dual licensed under the MIT or GPL Version 2 licenses.
580
+ * http://jquery.org/license
581
+ *
582
+ * http://docs.jquery.com/UI/Position
583
+ */
584
+ (function( $, undefined ) {
585
+
586
+ $.ui = $.ui || {};
587
+
588
+ var horizontalPositions = /left|center|right/,
589
+ verticalPositions = /top|center|bottom/,
590
+ center = "center",
591
+ _position = $.fn.position,
592
+ _offset = $.fn.offset;
593
+
594
+ $.fn.position = function( options ) {
595
+ if ( !options || !options.of ) {
596
+ return _position.apply( this, arguments );
597
+ }
598
+
599
+ // make a copy, we don't want to modify arguments
600
+ options = $.extend( {}, options );
601
+
602
+ var target = $( options.of ),
603
+ targetElem = target[0],
604
+ collision = ( options.collision || "flip" ).split( " " ),
605
+ offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
606
+ targetWidth,
607
+ targetHeight,
608
+ basePosition;
609
+
610
+ if ( targetElem.nodeType === 9 ) {
611
+ targetWidth = target.width();
612
+ targetHeight = target.height();
613
+ basePosition = { top: 0, left: 0 };
614
+ // TODO: use $.isWindow() in 1.9
615
+ } else if ( targetElem.setTimeout ) {
616
+ targetWidth = target.width();
617
+ targetHeight = target.height();
618
+ basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
619
+ } else if ( targetElem.preventDefault ) {
620
+ // force left top to allow flipping
621
+ options.at = "left top";
622
+ targetWidth = targetHeight = 0;
623
+ basePosition = { top: options.of.pageY, left: options.of.pageX };
624
+ } else {
625
+ targetWidth = target.outerWidth();
626
+ targetHeight = target.outerHeight();
627
+ basePosition = target.offset();
628
+ }
629
+
630
+ // force my and at to have valid horizontal and veritcal positions
631
+ // if a value is missing or invalid, it will be converted to center
632
+ $.each( [ "my", "at" ], function() {
633
+ var pos = ( options[this] || "" ).split( " " );
634
+ if ( pos.length === 1) {
635
+ pos = horizontalPositions.test( pos[0] ) ?
636
+ pos.concat( [center] ) :
637
+ verticalPositions.test( pos[0] ) ?
638
+ [ center ].concat( pos ) :
639
+ [ center, center ];
640
+ }
641
+ pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
642
+ pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
643
+ options[ this ] = pos;
644
+ });
645
+
646
+ // normalize collision option
647
+ if ( collision.length === 1 ) {
648
+ collision[ 1 ] = collision[ 0 ];
649
+ }
650
+
651
+ // normalize offset option
652
+ offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
653
+ if ( offset.length === 1 ) {
654
+ offset[ 1 ] = offset[ 0 ];
655
+ }
656
+ offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
657
+
658
+ if ( options.at[0] === "right" ) {
659
+ basePosition.left += targetWidth;
660
+ } else if ( options.at[0] === center ) {
661
+ basePosition.left += targetWidth / 2;
662
+ }
663
+
664
+ if ( options.at[1] === "bottom" ) {
665
+ basePosition.top += targetHeight;
666
+ } else if ( options.at[1] === center ) {
667
+ basePosition.top += targetHeight / 2;
668
+ }
669
+
670
+ basePosition.left += offset[ 0 ];
671
+ basePosition.top += offset[ 1 ];
672
+
673
+ return this.each(function() {
674
+ var elem = $( this ),
675
+ elemWidth = elem.outerWidth(),
676
+ elemHeight = elem.outerHeight(),
677
+ marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
678
+ marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
679
+ collisionWidth = elemWidth + marginLeft +
680
+ ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ),
681
+ collisionHeight = elemHeight + marginTop +
682
+ ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ),
683
+ position = $.extend( {}, basePosition ),
684
+ collisionPosition;
685
+
686
+ if ( options.my[0] === "right" ) {
687
+ position.left -= elemWidth;
688
+ } else if ( options.my[0] === center ) {
689
+ position.left -= elemWidth / 2;
690
+ }
691
+
692
+ if ( options.my[1] === "bottom" ) {
693
+ position.top -= elemHeight;
694
+ } else if ( options.my[1] === center ) {
695
+ position.top -= elemHeight / 2;
696
+ }
697
+
698
+ // prevent fractions (see #5280)
699
+ position.left = Math.round( position.left );
700
+ position.top = Math.round( position.top );
701
+
702
+ collisionPosition = {
703
+ left: position.left - marginLeft,
704
+ top: position.top - marginTop
705
+ };
706
+
707
+ $.each( [ "left", "top" ], function( i, dir ) {
708
+ if ( $.ui.position[ collision[i] ] ) {
709
+ $.ui.position[ collision[i] ][ dir ]( position, {
710
+ targetWidth: targetWidth,
711
+ targetHeight: targetHeight,
712
+ elemWidth: elemWidth,
713
+ elemHeight: elemHeight,
714
+ collisionPosition: collisionPosition,
715
+ collisionWidth: collisionWidth,
716
+ collisionHeight: collisionHeight,
717
+ offset: offset,
718
+ my: options.my,
719
+ at: options.at
720
+ });
721
+ }
722
+ });
723
+
724
+ if ( $.fn.bgiframe ) {
725
+ elem.bgiframe();
726
+ }
727
+ elem.offset( $.extend( position, { using: options.using } ) );
728
+ });
729
+ };
730
+
731
+ $.ui.position = {
732
+ fit: {
733
+ left: function( position, data ) {
734
+ var win = $( window ),
735
+ over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
736
+ position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
737
+ },
738
+ top: function( position, data ) {
739
+ var win = $( window ),
740
+ over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
741
+ position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
742
+ }
743
+ },
744
+
745
+ flip: {
746
+ left: function( position, data ) {
747
+ if ( data.at[0] === center ) {
748
+ return;
749
+ }
750
+ var win = $( window ),
751
+ over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
752
+ myOffset = data.my[ 0 ] === "left" ?
753
+ -data.elemWidth :
754
+ data.my[ 0 ] === "right" ?
755
+ data.elemWidth :
756
+ 0,
757
+ atOffset = data.at[ 0 ] === "left" ?
758
+ data.targetWidth :
759
+ -data.targetWidth,
760
+ offset = -2 * data.offset[ 0 ];
761
+ position.left += data.collisionPosition.left < 0 ?
762
+ myOffset + atOffset + offset :
763
+ over > 0 ?
764
+ myOffset + atOffset + offset :
765
+ 0;
766
+ },
767
+ top: function( position, data ) {
768
+ if ( data.at[1] === center ) {
769
+ return;
770
+ }
771
+ var win = $( window ),
772
+ over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
773
+ myOffset = data.my[ 1 ] === "top" ?
774
+ -data.elemHeight :
775
+ data.my[ 1 ] === "bottom" ?
776
+ data.elemHeight :
777
+ 0,
778
+ atOffset = data.at[ 1 ] === "top" ?
779
+ data.targetHeight :
780
+ -data.targetHeight,
781
+ offset = -2 * data.offset[ 1 ];
782
+ position.top += data.collisionPosition.top < 0 ?
783
+ myOffset + atOffset + offset :
784
+ over > 0 ?
785
+ myOffset + atOffset + offset :
786
+ 0;
787
+ }
788
+ }
789
+ };
790
+
791
+ // offset setter from jQuery 1.4
792
+ if ( !$.offset.setOffset ) {
793
+ $.offset.setOffset = function( elem, options ) {
794
+ // set position first, in-case top/left are set even on static elem
795
+ if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
796
+ elem.style.position = "relative";
797
+ }
798
+ var curElem = $( elem ),
799
+ curOffset = curElem.offset(),
800
+ curTop = parseInt( $.curCSS( elem, "top", true ), 10 ) || 0,
801
+ curLeft = parseInt( $.curCSS( elem, "left", true ), 10) || 0,
802
+ props = {
803
+ top: (options.top - curOffset.top) + curTop,
804
+ left: (options.left - curOffset.left) + curLeft
805
+ };
806
+
807
+ if ( 'using' in options ) {
808
+ options.using.call( elem, props );
809
+ } else {
810
+ curElem.css( props );
811
+ }
812
+ };
813
+
814
+ $.fn.offset = function( options ) {
815
+ var elem = this[ 0 ];
816
+ if ( !elem || !elem.ownerDocument ) { return null; }
817
+ if ( options ) {
818
+ return this.each(function() {
819
+ $.offset.setOffset( this, options );
820
+ });
821
+ }
822
+ return _offset.call( this );
823
+ };
824
+ }
825
+
826
+ }( jQuery ));
827
+ /*
828
+ * jQuery UI Autocomplete 1.8.13
829
+ *
830
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
831
+ * Dual licensed under the MIT or GPL Version 2 licenses.
832
+ * http://jquery.org/license
833
+ *
834
+ * http://docs.jquery.com/UI/Autocomplete
835
+ *
836
+ * Depends:
837
+ * jquery.ui.core.js
838
+ * jquery.ui.widget.js
839
+ * jquery.ui.position.js
840
+ */
841
+ (function( $, undefined ) {
842
+
843
+ // used to prevent race conditions with remote data sources
844
+ var requestIndex = 0;
845
+
846
+ $.widget( "ui.autocomplete", {
847
+ options: {
848
+ appendTo: "body",
849
+ autoFocus: false,
850
+ delay: 300,
851
+ minLength: 1,
852
+ position: {
853
+ my: "left top",
854
+ at: "left bottom",
855
+ collision: "none"
856
+ },
857
+ source: null
858
+ },
859
+
860
+ pending: 0,
861
+
862
+ _create: function() {
863
+ var self = this,
864
+ doc = this.element[ 0 ].ownerDocument,
865
+ suppressKeyPress;
866
+
867
+ this.element
868
+ .addClass( "ui-autocomplete-input" )
869
+ .attr( "autocomplete", "off" )
870
+ // TODO verify these actually work as intended
871
+ .attr({
872
+ role: "textbox",
873
+ "aria-autocomplete": "list",
874
+ "aria-haspopup": "true"
875
+ })
876
+ .bind( "keydown.autocomplete", function( event ) {
877
+ if ( self.options.disabled || self.element.attr( "readonly" ) ) {
878
+ return;
879
+ }
880
+
881
+ suppressKeyPress = false;
882
+ var keyCode = $.ui.keyCode;
883
+ switch( event.keyCode ) {
884
+ case keyCode.PAGE_UP:
885
+ self._move( "previousPage", event );
886
+ break;
887
+ case keyCode.PAGE_DOWN:
888
+ self._move( "nextPage", event );
889
+ break;
890
+ case keyCode.UP:
891
+ self._move( "previous", event );
892
+ // prevent moving cursor to beginning of text field in some browsers
893
+ event.preventDefault();
894
+ break;
895
+ case keyCode.DOWN:
896
+ self._move( "next", event );
897
+ // prevent moving cursor to end of text field in some browsers
898
+ event.preventDefault();
899
+ break;
900
+ case keyCode.ENTER:
901
+ case keyCode.NUMPAD_ENTER:
902
+ // when menu is open and has focus
903
+ if ( self.menu.active ) {
904
+ // #6055 - Opera still allows the keypress to occur
905
+ // which causes forms to submit
906
+ suppressKeyPress = true;
907
+ event.preventDefault();
908
+ }
909
+ //passthrough - ENTER and TAB both select the current element
910
+ case keyCode.TAB:
911
+ if ( !self.menu.active ) {
912
+ return;
913
+ }
914
+ self.menu.select( event );
915
+ break;
916
+ case keyCode.ESCAPE:
917
+ self.element.val( self.term );
918
+ self.close( event );
919
+ break;
920
+ default:
921
+ // keypress is triggered before the input value is changed
922
+ clearTimeout( self.searching );
923
+ self.searching = setTimeout(function() {
924
+ // only search if the value has changed
925
+ if ( self.term != self.element.val() ) {
926
+ self.selectedItem = null;
927
+ self.search( null, event );
928
+ }
929
+ }, self.options.delay );
930
+ break;
931
+ }
932
+ })
933
+ .bind( "keypress.autocomplete", function( event ) {
934
+ if ( suppressKeyPress ) {
935
+ suppressKeyPress = false;
936
+ event.preventDefault();
937
+ }
938
+ })
939
+ .bind( "focus.autocomplete", function() {
940
+ if ( self.options.disabled ) {
941
+ return;
942
+ }
943
+
944
+ self.selectedItem = null;
945
+ self.previous = self.element.val();
946
+ })
947
+ .bind( "blur.autocomplete", function( event ) {
948
+ if ( self.options.disabled ) {
949
+ return;
950
+ }
951
+
952
+ clearTimeout( self.searching );
953
+ // clicks on the menu (or a button to trigger a search) will cause a blur event
954
+ self.closing = setTimeout(function() {
955
+ self.close( event );
956
+ self._change( event );
957
+ }, 150 );
958
+ });
959
+ this._initSource();
960
+ this.response = function() {
961
+ return self._response.apply( self, arguments );
962
+ };
963
+ this.menu = $( "<ul></ul>" )
964
+ .addClass( "ui-autocomplete" )
965
+ .appendTo( $( this.options.appendTo || "body", doc )[0] )
966
+ // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
967
+ .mousedown(function( event ) {
968
+ // clicking on the scrollbar causes focus to shift to the body
969
+ // but we can't detect a mouseup or a click immediately afterward
970
+ // so we have to track the next mousedown and close the menu if
971
+ // the user clicks somewhere outside of the autocomplete
972
+ var menuElement = self.menu.element[ 0 ];
973
+ if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
974
+ setTimeout(function() {
975
+ $( document ).one( 'mousedown', function( event ) {
976
+ if ( event.target !== self.element[ 0 ] &&
977
+ event.target !== menuElement &&
978
+ !$.ui.contains( menuElement, event.target ) ) {
979
+ self.close();
980
+ }
981
+ });
982
+ }, 1 );
983
+ }
984
+
985
+ // use another timeout to make sure the blur-event-handler on the input was already triggered
986
+ setTimeout(function() {
987
+ clearTimeout( self.closing );
988
+ }, 13);
989
+ })
990
+ .menu({
991
+ focus: function( event, ui ) {
992
+ var item = ui.item.data( "item.autocomplete" );
993
+ if ( false !== self._trigger( "focus", event, { item: item } ) ) {
994
+ // use value to match what will end up in the input, if it was a key event
995
+ if ( /^key/.test(event.originalEvent.type) ) {
996
+ self.element.val( item.value );
997
+ }
998
+ }
999
+ },
1000
+ selected: function( event, ui ) {
1001
+ var item = ui.item.data( "item.autocomplete" ),
1002
+ previous = self.previous;
1003
+
1004
+ // only trigger when focus was lost (click on menu)
1005
+ if ( self.element[0] !== doc.activeElement ) {
1006
+ self.element.focus();
1007
+ self.previous = previous;
1008
+ // #6109 - IE triggers two focus events and the second
1009
+ // is asynchronous, so we need to reset the previous
1010
+ // term synchronously and asynchronously :-(
1011
+ setTimeout(function() {
1012
+ self.previous = previous;
1013
+ self.selectedItem = item;
1014
+ }, 1);
1015
+ }
1016
+
1017
+ if ( false !== self._trigger( "select", event, { item: item } ) ) {
1018
+ self.element.val( item.value );
1019
+ }
1020
+ // reset the term after the select event
1021
+ // this allows custom select handling to work properly
1022
+ self.term = self.element.val();
1023
+
1024
+ self.close( event );
1025
+ self.selectedItem = item;
1026
+ },
1027
+ blur: function( event, ui ) {
1028
+ // don't set the value of the text field if it's already correct
1029
+ // this prevents moving the cursor unnecessarily
1030
+ if ( self.menu.element.is(":visible") &&
1031
+ ( self.element.val() !== self.term ) ) {
1032
+ self.element.val( self.term );
1033
+ }
1034
+ }
1035
+ })
1036
+ .zIndex( this.element.zIndex() + 1 )
1037
+ // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
1038
+ .css({ top: 0, left: 0 })
1039
+ .hide()
1040
+ .data( "menu" );
1041
+ if ( $.fn.bgiframe ) {
1042
+ this.menu.element.bgiframe();
1043
+ }
1044
+ },
1045
+
1046
+ destroy: function() {
1047
+ this.element
1048
+ .removeClass( "ui-autocomplete-input" )
1049
+ .removeAttr( "autocomplete" )
1050
+ .removeAttr( "role" )
1051
+ .removeAttr( "aria-autocomplete" )
1052
+ .removeAttr( "aria-haspopup" );
1053
+ this.menu.element.remove();
1054
+ $.Widget.prototype.destroy.call( this );
1055
+ },
1056
+
1057
+ _setOption: function( key, value ) {
1058
+ $.Widget.prototype._setOption.apply( this, arguments );
1059
+ if ( key === "source" ) {
1060
+ this._initSource();
1061
+ }
1062
+ if ( key === "appendTo" ) {
1063
+ this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
1064
+ }
1065
+ if ( key === "disabled" && value && this.xhr ) {
1066
+ this.xhr.abort();
1067
+ }
1068
+ },
1069
+
1070
+ _initSource: function() {
1071
+ var self = this,
1072
+ array,
1073
+ url;
1074
+ if ( $.isArray(this.options.source) ) {
1075
+ array = this.options.source;
1076
+ this.source = function( request, response ) {
1077
+ response( $.ui.autocomplete.filter(array, request.term) );
1078
+ };
1079
+ } else if ( typeof this.options.source === "string" ) {
1080
+ url = this.options.source;
1081
+ this.source = function( request, response ) {
1082
+ if ( self.xhr ) {
1083
+ self.xhr.abort();
1084
+ }
1085
+ self.xhr = $.ajax({
1086
+ url: url,
1087
+ data: request,
1088
+ dataType: "json",
1089
+ autocompleteRequest: ++requestIndex,
1090
+ success: function( data, status ) {
1091
+ if ( this.autocompleteRequest === requestIndex ) {
1092
+ response( data );
1093
+ }
1094
+ },
1095
+ error: function() {
1096
+ if ( this.autocompleteRequest === requestIndex ) {
1097
+ response( [] );
1098
+ }
1099
+ }
1100
+ });
1101
+ };
1102
+ } else {
1103
+ this.source = this.options.source;
1104
+ }
1105
+ },
1106
+
1107
+ search: function( value, event ) {
1108
+ value = value != null ? value : this.element.val();
1109
+
1110
+ // always save the actual value, not the one passed as an argument
1111
+ this.term = this.element.val();
1112
+
1113
+ if ( value.length < this.options.minLength ) {
1114
+ return this.close( event );
1115
+ }
1116
+
1117
+ clearTimeout( this.closing );
1118
+ if ( this._trigger( "search", event ) === false ) {
1119
+ return;
1120
+ }
1121
+
1122
+ return this._search( value );
1123
+ },
1124
+
1125
+ _search: function( value ) {
1126
+ this.pending++;
1127
+ this.element.addClass( "ui-autocomplete-loading" );
1128
+
1129
+ this.source( { term: value }, this.response );
1130
+ },
1131
+
1132
+ _response: function( content ) {
1133
+ if ( !this.options.disabled && content && content.length ) {
1134
+ content = this._normalize( content );
1135
+ this._suggest( content );
1136
+ this._trigger( "open" );
1137
+ } else {
1138
+ this.close();
1139
+ }
1140
+ this.pending--;
1141
+ if ( !this.pending ) {
1142
+ this.element.removeClass( "ui-autocomplete-loading" );
1143
+ }
1144
+ },
1145
+
1146
+ close: function( event ) {
1147
+ clearTimeout( this.closing );
1148
+ if ( this.menu.element.is(":visible") ) {
1149
+ this.menu.element.hide();
1150
+ this.menu.deactivate();
1151
+ this._trigger( "close", event );
1152
+ }
1153
+ },
1154
+
1155
+ _change: function( event ) {
1156
+ if ( this.previous !== this.element.val() ) {
1157
+ this._trigger( "change", event, { item: this.selectedItem } );
1158
+ }
1159
+ },
1160
+
1161
+ _normalize: function( items ) {
1162
+ // assume all items have the right format when the first item is complete
1163
+ if ( items.length && items[0].label && items[0].value ) {
1164
+ return items;
1165
+ }
1166
+ return $.map( items, function(item) {
1167
+ if ( typeof item === "string" ) {
1168
+ return {
1169
+ label: item,
1170
+ value: item
1171
+ };
1172
+ }
1173
+ return $.extend({
1174
+ label: item.label || item.value,
1175
+ value: item.value || item.label
1176
+ }, item );
1177
+ });
1178
+ },
1179
+
1180
+ _suggest: function( items ) {
1181
+ var ul = this.menu.element
1182
+ .empty()
1183
+ .zIndex( this.element.zIndex() + 1 );
1184
+ this._renderMenu( ul, items );
1185
+ // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
1186
+ this.menu.deactivate();
1187
+ this.menu.refresh();
1188
+
1189
+ // size and position menu
1190
+ ul.show();
1191
+ this._resizeMenu();
1192
+ ul.position( $.extend({
1193
+ of: this.element
1194
+ }, this.options.position ));
1195
+
1196
+ if ( this.options.autoFocus ) {
1197
+ this.menu.next( new $.Event("mouseover") );
1198
+ }
1199
+ },
1200
+
1201
+ _resizeMenu: function() {
1202
+ var ul = this.menu.element;
1203
+ ul.outerWidth( Math.max(
1204
+ ul.width( "" ).outerWidth(),
1205
+ this.element.outerWidth()
1206
+ ) );
1207
+ },
1208
+
1209
+ _renderMenu: function( ul, items ) {
1210
+ var self = this;
1211
+ $.each( items, function( index, item ) {
1212
+ self._renderItem( ul, item );
1213
+ });
1214
+ },
1215
+
1216
+ _renderItem: function( ul, item) {
1217
+ return $( "<li></li>" )
1218
+ .data( "item.autocomplete", item )
1219
+ .append( $( "<a></a>" ).text( item.label ) )
1220
+ .appendTo( ul );
1221
+ },
1222
+
1223
+ _move: function( direction, event ) {
1224
+ if ( !this.menu.element.is(":visible") ) {
1225
+ this.search( null, event );
1226
+ return;
1227
+ }
1228
+ if ( this.menu.first() && /^previous/.test(direction) ||
1229
+ this.menu.last() && /^next/.test(direction) ) {
1230
+ this.element.val( this.term );
1231
+ this.menu.deactivate();
1232
+ return;
1233
+ }
1234
+ this.menu[ direction ]( event );
1235
+ },
1236
+
1237
+ widget: function() {
1238
+ return this.menu.element;
1239
+ }
1240
+ });
1241
+
1242
+ $.extend( $.ui.autocomplete, {
1243
+ escapeRegex: function( value ) {
1244
+ return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
1245
+ },
1246
+ filter: function(array, term) {
1247
+ var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
1248
+ return $.grep( array, function(value) {
1249
+ return matcher.test( value.label || value.value || value );
1250
+ });
1251
+ }
1252
+ });
1253
+
1254
+ }( jQuery ));
1255
+
1256
+ /*
1257
+ * jQuery UI Menu (not officially released)
1258
+ *
1259
+ * This widget isn't yet finished and the API is subject to change. We plan to finish
1260
+ * it for the next release. You're welcome to give it a try anyway and give us feedback,
1261
+ * as long as you're okay with migrating your code later on. We can help with that, too.
1262
+ *
1263
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
1264
+ * Dual licensed under the MIT or GPL Version 2 licenses.
1265
+ * http://jquery.org/license
1266
+ *
1267
+ * http://docs.jquery.com/UI/Menu
1268
+ *
1269
+ * Depends:
1270
+ * jquery.ui.core.js
1271
+ * jquery.ui.widget.js
1272
+ */
1273
+ (function($) {
1274
+
1275
+ $.widget("ui.menu", {
1276
+ _create: function() {
1277
+ var self = this;
1278
+ this.element
1279
+ .addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
1280
+ .attr({
1281
+ role: "listbox",
1282
+ "aria-activedescendant": "ui-active-menuitem"
1283
+ })
1284
+ .click(function( event ) {
1285
+ if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
1286
+ return;
1287
+ }
1288
+ // temporary
1289
+ event.preventDefault();
1290
+ self.select( event );
1291
+ });
1292
+ this.refresh();
1293
+ },
1294
+
1295
+ refresh: function() {
1296
+ var self = this;
1297
+
1298
+ // don't refresh list items that are already adapted
1299
+ var items = this.element.children("li:not(.ui-menu-item):has(a)")
1300
+ .addClass("ui-menu-item")
1301
+ .attr("role", "menuitem");
1302
+
1303
+ items.children("a")
1304
+ .addClass("ui-corner-all")
1305
+ .attr("tabindex", -1)
1306
+ // mouseenter doesn't work with event delegation
1307
+ .mouseenter(function( event ) {
1308
+ self.activate( event, $(this).parent() );
1309
+ })
1310
+ .mouseleave(function() {
1311
+ self.deactivate();
1312
+ });
1313
+ },
1314
+
1315
+ activate: function( event, item ) {
1316
+ this.deactivate();
1317
+ if (this.hasScroll()) {
1318
+ var offset = item.offset().top - this.element.offset().top,
1319
+ scroll = this.element.scrollTop(),
1320
+ elementHeight = this.element.height();
1321
+ if (offset < 0) {
1322
+ this.element.scrollTop( scroll + offset);
1323
+ } else if (offset >= elementHeight) {
1324
+ this.element.scrollTop( scroll + offset - elementHeight + item.height());
1325
+ }
1326
+ }
1327
+ this.active = item.eq(0)
1328
+ .children("a")
1329
+ .addClass("ui-state-hover")
1330
+ .attr("id", "ui-active-menuitem")
1331
+ .end();
1332
+ this._trigger("focus", event, { item: item });
1333
+ },
1334
+
1335
+ deactivate: function() {
1336
+ if (!this.active) { return; }
1337
+
1338
+ this.active.children("a")
1339
+ .removeClass("ui-state-hover")
1340
+ .removeAttr("id");
1341
+ this._trigger("blur");
1342
+ this.active = null;
1343
+ },
1344
+
1345
+ next: function(event) {
1346
+ this.move("next", ".ui-menu-item:first", event);
1347
+ },
1348
+
1349
+ previous: function(event) {
1350
+ this.move("prev", ".ui-menu-item:last", event);
1351
+ },
1352
+
1353
+ first: function() {
1354
+ return this.active && !this.active.prevAll(".ui-menu-item").length;
1355
+ },
1356
+
1357
+ last: function() {
1358
+ return this.active && !this.active.nextAll(".ui-menu-item").length;
1359
+ },
1360
+
1361
+ move: function(direction, edge, event) {
1362
+ if (!this.active) {
1363
+ this.activate(event, this.element.children(edge));
1364
+ return;
1365
+ }
1366
+ var next = this.active[direction + "All"](".ui-menu-item").eq(0);
1367
+ if (next.length) {
1368
+ this.activate(event, next);
1369
+ } else {
1370
+ this.activate(event, this.element.children(edge));
1371
+ }
1372
+ },
1373
+
1374
+ // TODO merge with previousPage
1375
+ nextPage: function(event) {
1376
+ if (this.hasScroll()) {
1377
+ // TODO merge with no-scroll-else
1378
+ if (!this.active || this.last()) {
1379
+ this.activate(event, this.element.children(".ui-menu-item:first"));
1380
+ return;
1381
+ }
1382
+ var base = this.active.offset().top,
1383
+ height = this.element.height(),
1384
+ result = this.element.children(".ui-menu-item").filter(function() {
1385
+ var close = $(this).offset().top - base - height + $(this).height();
1386
+ // TODO improve approximation
1387
+ return close < 10 && close > -10;
1388
+ });
1389
+
1390
+ // TODO try to catch this earlier when scrollTop indicates the last page anyway
1391
+ if (!result.length) {
1392
+ result = this.element.children(".ui-menu-item:last");
1393
+ }
1394
+ this.activate(event, result);
1395
+ } else {
1396
+ this.activate(event, this.element.children(".ui-menu-item")
1397
+ .filter(!this.active || this.last() ? ":first" : ":last"));
1398
+ }
1399
+ },
1400
+
1401
+ // TODO merge with nextPage
1402
+ previousPage: function(event) {
1403
+ if (this.hasScroll()) {
1404
+ // TODO merge with no-scroll-else
1405
+ if (!this.active || this.first()) {
1406
+ this.activate(event, this.element.children(".ui-menu-item:last"));
1407
+ return;
1408
+ }
1409
+
1410
+ var base = this.active.offset().top,
1411
+ height = this.element.height();
1412
+ result = this.element.children(".ui-menu-item").filter(function() {
1413
+ var close = $(this).offset().top - base + height - $(this).height();
1414
+ // TODO improve approximation
1415
+ return close < 10 && close > -10;
1416
+ });
1417
+
1418
+ // TODO try to catch this earlier when scrollTop indicates the last page anyway
1419
+ if (!result.length) {
1420
+ result = this.element.children(".ui-menu-item:first");
1421
+ }
1422
+ this.activate(event, result);
1423
+ } else {
1424
+ this.activate(event, this.element.children(".ui-menu-item")
1425
+ .filter(!this.active || this.first() ? ":last" : ":first"));
1426
+ }
1427
+ },
1428
+
1429
+ hasScroll: function() {
1430
+ return this.element.height() < this.element[ $.fn.prop ? "prop" : "attr" ]("scrollHeight");
1431
+ },
1432
+
1433
+ select: function( event ) {
1434
+ this._trigger("selected", event, { item: this.active });
1435
+ }
1436
+ });
1437
+
1438
+ }(jQuery));
1439
+ /*
1440
+ * jQuery UI Datepicker 1.8.13
1441
+ *
1442
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
1443
+ * Dual licensed under the MIT or GPL Version 2 licenses.
1444
+ * http://jquery.org/license
1445
+ *
1446
+ * http://docs.jquery.com/UI/Datepicker
1447
+ *
1448
+ * Depends:
1449
+ * jquery.ui.core.js
1450
+ */
1451
+ (function( $, undefined ) {
1452
+
1453
+ $.extend($.ui, { datepicker: { version: "1.8.13" } });
1454
+
1455
+ var PROP_NAME = 'datepicker';
1456
+ var dpuuid = new Date().getTime();
1457
+ var instActive;
1458
+
1459
+ /* Date picker manager.
1460
+ Use the singleton instance of this class, $.datepicker, to interact with the date picker.
1461
+ Settings for (groups of) date pickers are maintained in an instance object,
1462
+ allowing multiple different settings on the same page. */
1463
+
1464
+ function Datepicker() {
1465
+ this.debug = false; // Change this to true to start debugging
1466
+ this._curInst = null; // The current instance in use
1467
+ this._keyEvent = false; // If the last event was a key event
1468
+ this._disabledInputs = []; // List of date picker inputs that have been disabled
1469
+ this._datepickerShowing = false; // True if the popup picker is showing , false if not
1470
+ this._inDialog = false; // True if showing within a "dialog", false if not
1471
+ this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
1472
+ this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
1473
+ this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
1474
+ this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
1475
+ this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
1476
+ this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
1477
+ this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
1478
+ this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
1479
+ this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
1480
+ this.regional = []; // Available regional settings, indexed by language code
1481
+ this.regional[''] = { // Default regional settings
1482
+ closeText: 'Done', // Display text for close link
1483
+ prevText: 'Prev', // Display text for previous month link
1484
+ nextText: 'Next', // Display text for next month link
1485
+ currentText: 'Today', // Display text for current month link
1486
+ monthNames: ['January','February','March','April','May','June',
1487
+ 'July','August','September','October','November','December'], // Names of months for drop-down and formatting
1488
+ monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
1489
+ dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
1490
+ dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
1491
+ dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
1492
+ weekHeader: 'Wk', // Column header for week of the year
1493
+ dateFormat: 'mm/dd/yy', // See format options on parseDate
1494
+ firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
1495
+ isRTL: false, // True if right-to-left language, false if left-to-right
1496
+ showMonthAfterYear: false, // True if the year select precedes month, false for month then year
1497
+ yearSuffix: '' // Additional text to append to the year in the month headers
1498
+ };
1499
+ this._defaults = { // Global defaults for all the date picker instances
1500
+ showOn: 'focus', // 'focus' for popup on focus,
1501
+ // 'button' for trigger button, or 'both' for either
1502
+ showAnim: 'fadeIn', // Name of jQuery animation for popup
1503
+ showOptions: {}, // Options for enhanced animations
1504
+ defaultDate: null, // Used when field is blank: actual date,
1505
+ // +/-number for offset from today, null for today
1506
+ appendText: '', // Display text following the input box, e.g. showing the format
1507
+ buttonText: '...', // Text for trigger button
1508
+ buttonImage: '', // URL for trigger button image
1509
+ buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
1510
+ hideIfNoPrevNext: false, // True to hide next/previous month links
1511
+ // if not applicable, false to just disable them
1512
+ navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
1513
+ gotoCurrent: false, // True if today link goes back to current selection instead
1514
+ changeMonth: false, // True if month can be selected directly, false if only prev/next
1515
+ changeYear: false, // True if year can be selected directly, false if only prev/next
1516
+ yearRange: 'c-10:c+10', // Range of years to display in drop-down,
1517
+ // either relative to today's year (-nn:+nn), relative to currently displayed year
1518
+ // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
1519
+ showOtherMonths: false, // True to show dates in other months, false to leave blank
1520
+ selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
1521
+ showWeek: false, // True to show week of the year, false to not show it
1522
+ calculateWeek: this.iso8601Week, // How to calculate the week of the year,
1523
+ // takes a Date and returns the number of the week for it
1524
+ shortYearCutoff: '+10', // Short year values < this are in the current century,
1525
+ // > this are in the previous century,
1526
+ // string value starting with '+' for current year + value
1527
+ minDate: null, // The earliest selectable date, or null for no limit
1528
+ maxDate: null, // The latest selectable date, or null for no limit
1529
+ duration: 'fast', // Duration of display/closure
1530
+ beforeShowDay: null, // Function that takes a date and returns an array with
1531
+ // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
1532
+ // [2] = cell title (optional), e.g. $.datepicker.noWeekends
1533
+ beforeShow: null, // Function that takes an input field and
1534
+ // returns a set of custom settings for the date picker
1535
+ onSelect: null, // Define a callback function when a date is selected
1536
+ onChangeMonthYear: null, // Define a callback function when the month or year is changed
1537
+ onClose: null, // Define a callback function when the datepicker is closed
1538
+ numberOfMonths: 1, // Number of months to show at a time
1539
+ showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
1540
+ stepMonths: 1, // Number of months to step back/forward
1541
+ stepBigMonths: 12, // Number of months to step back/forward for the big links
1542
+ altField: '', // Selector for an alternate field to store selected dates into
1543
+ altFormat: '', // The date format to use for the alternate field
1544
+ constrainInput: true, // The input is constrained by the current date format
1545
+ showButtonPanel: false, // True to show button panel, false to not show it
1546
+ autoSize: false // True to size the input for the date format, false to leave as is
1547
+ };
1548
+ $.extend(this._defaults, this.regional['']);
1549
+ this.dpDiv = bindHover($('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'));
1550
+ }
1551
+
1552
+ $.extend(Datepicker.prototype, {
1553
+ /* Class name added to elements to indicate already configured with a date picker. */
1554
+ markerClassName: 'hasDatepicker',
1555
+
1556
+ /* Debug logging (if enabled). */
1557
+ log: function () {
1558
+ if (this.debug)
1559
+ console.log.apply('', arguments);
1560
+ },
1561
+
1562
+ // TODO rename to "widget" when switching to widget factory
1563
+ _widgetDatepicker: function() {
1564
+ return this.dpDiv;
1565
+ },
1566
+
1567
+ /* Override the default settings for all instances of the date picker.
1568
+ @param settings object - the new settings to use as defaults (anonymous object)
1569
+ @return the manager object */
1570
+ setDefaults: function(settings) {
1571
+ extendRemove(this._defaults, settings || {});
1572
+ return this;
1573
+ },
1574
+
1575
+ /* Attach the date picker to a jQuery selection.
1576
+ @param target element - the target input field or division or span
1577
+ @param settings object - the new settings to use for this date picker instance (anonymous) */
1578
+ _attachDatepicker: function(target, settings) {
1579
+ // check for settings on the control itself - in namespace 'date:'
1580
+ var inlineSettings = null;
1581
+ for (var attrName in this._defaults) {
1582
+ var attrValue = target.getAttribute('date:' + attrName);
1583
+ if (attrValue) {
1584
+ inlineSettings = inlineSettings || {};
1585
+ try {
1586
+ inlineSettings[attrName] = eval(attrValue);
1587
+ } catch (err) {
1588
+ inlineSettings[attrName] = attrValue;
1589
+ }
1590
+ }
1591
+ }
1592
+ var nodeName = target.nodeName.toLowerCase();
1593
+ var inline = (nodeName == 'div' || nodeName == 'span');
1594
+ if (!target.id) {
1595
+ this.uuid += 1;
1596
+ target.id = 'dp' + this.uuid;
1597
+ }
1598
+ var inst = this._newInst($(target), inline);
1599
+ inst.settings = $.extend({}, settings || {}, inlineSettings || {});
1600
+ if (nodeName == 'input') {
1601
+ this._connectDatepicker(target, inst);
1602
+ } else if (inline) {
1603
+ this._inlineDatepicker(target, inst);
1604
+ }
1605
+ },
1606
+
1607
+ /* Create a new instance object. */
1608
+ _newInst: function(target, inline) {
1609
+ var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
1610
+ return {id: id, input: target, // associated target
1611
+ selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
1612
+ drawMonth: 0, drawYear: 0, // month being drawn
1613
+ inline: inline, // is datepicker inline or not
1614
+ dpDiv: (!inline ? this.dpDiv : // presentation div
1615
+ bindHover($('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')))};
1616
+ },
1617
+
1618
+ /* Attach the date picker to an input field. */
1619
+ _connectDatepicker: function(target, inst) {
1620
+ var input = $(target);
1621
+ inst.append = $([]);
1622
+ inst.trigger = $([]);
1623
+ if (input.hasClass(this.markerClassName))
1624
+ return;
1625
+ this._attachments(input, inst);
1626
+ input.addClass(this.markerClassName).keydown(this._doKeyDown).
1627
+ keypress(this._doKeyPress).keyup(this._doKeyUp).
1628
+ bind("setData.datepicker", function(event, key, value) {
1629
+ inst.settings[key] = value;
1630
+ }).bind("getData.datepicker", function(event, key) {
1631
+ return this._get(inst, key);
1632
+ });
1633
+ this._autoSize(inst);
1634
+ $.data(target, PROP_NAME, inst);
1635
+ },
1636
+
1637
+ /* Make attachments based on settings. */
1638
+ _attachments: function(input, inst) {
1639
+ var appendText = this._get(inst, 'appendText');
1640
+ var isRTL = this._get(inst, 'isRTL');
1641
+ if (inst.append)
1642
+ inst.append.remove();
1643
+ if (appendText) {
1644
+ inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
1645
+ input[isRTL ? 'before' : 'after'](inst.append);
1646
+ }
1647
+ input.unbind('focus', this._showDatepicker);
1648
+ if (inst.trigger)
1649
+ inst.trigger.remove();
1650
+ var showOn = this._get(inst, 'showOn');
1651
+ if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
1652
+ input.focus(this._showDatepicker);
1653
+ if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
1654
+ var buttonText = this._get(inst, 'buttonText');
1655
+ var buttonImage = this._get(inst, 'buttonImage');
1656
+ inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
1657
+ $('<img/>').addClass(this._triggerClass).
1658
+ attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
1659
+ $('<button type="button"></button>').addClass(this._triggerClass).
1660
+ html(buttonImage == '' ? buttonText : $('<img/>').attr(
1661
+ { src:buttonImage, alt:buttonText, title:buttonText })));
1662
+ input[isRTL ? 'before' : 'after'](inst.trigger);
1663
+ inst.trigger.click(function() {
1664
+ if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
1665
+ $.datepicker._hideDatepicker();
1666
+ else
1667
+ $.datepicker._showDatepicker(input[0]);
1668
+ return false;
1669
+ });
1670
+ }
1671
+ },
1672
+
1673
+ /* Apply the maximum length for the date format. */
1674
+ _autoSize: function(inst) {
1675
+ if (this._get(inst, 'autoSize') && !inst.inline) {
1676
+ var date = new Date(2009, 12 - 1, 20); // Ensure double digits
1677
+ var dateFormat = this._get(inst, 'dateFormat');
1678
+ if (dateFormat.match(/[DM]/)) {
1679
+ var findMax = function(names) {
1680
+ var max = 0;
1681
+ var maxI = 0;
1682
+ for (var i = 0; i < names.length; i++) {
1683
+ if (names[i].length > max) {
1684
+ max = names[i].length;
1685
+ maxI = i;
1686
+ }
1687
+ }
1688
+ return maxI;
1689
+ };
1690
+ date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
1691
+ 'monthNames' : 'monthNamesShort'))));
1692
+ date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
1693
+ 'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
1694
+ }
1695
+ inst.input.attr('size', this._formatDate(inst, date).length);
1696
+ }
1697
+ },
1698
+
1699
+ /* Attach an inline date picker to a div. */
1700
+ _inlineDatepicker: function(target, inst) {
1701
+ var divSpan = $(target);
1702
+ if (divSpan.hasClass(this.markerClassName))
1703
+ return;
1704
+ divSpan.addClass(this.markerClassName).append(inst.dpDiv).
1705
+ bind("setData.datepicker", function(event, key, value){
1706
+ inst.settings[key] = value;
1707
+ }).bind("getData.datepicker", function(event, key){
1708
+ return this._get(inst, key);
1709
+ });
1710
+ $.data(target, PROP_NAME, inst);
1711
+ this._setDate(inst, this._getDefaultDate(inst), true);
1712
+ this._updateDatepicker(inst);
1713
+ this._updateAlternate(inst);
1714
+ inst.dpDiv.show();
1715
+ },
1716
+
1717
+ /* Pop-up the date picker in a "dialog" box.
1718
+ @param input element - ignored
1719
+ @param date string or Date - the initial date to display
1720
+ @param onSelect function - the function to call when a date is selected
1721
+ @param settings object - update the dialog date picker instance's settings (anonymous object)
1722
+ @param pos int[2] - coordinates for the dialog's position within the screen or
1723
+ event - with x/y coordinates or
1724
+ leave empty for default (screen centre)
1725
+ @return the manager object */
1726
+ _dialogDatepicker: function(input, date, onSelect, settings, pos) {
1727
+ var inst = this._dialogInst; // internal instance
1728
+ if (!inst) {
1729
+ this.uuid += 1;
1730
+ var id = 'dp' + this.uuid;
1731
+ this._dialogInput = $('<input type="text" id="' + id +
1732
+ '" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
1733
+ this._dialogInput.keydown(this._doKeyDown);
1734
+ $('body').append(this._dialogInput);
1735
+ inst = this._dialogInst = this._newInst(this._dialogInput, false);
1736
+ inst.settings = {};
1737
+ $.data(this._dialogInput[0], PROP_NAME, inst);
1738
+ }
1739
+ extendRemove(inst.settings, settings || {});
1740
+ date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
1741
+ this._dialogInput.val(date);
1742
+
1743
+ this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
1744
+ if (!this._pos) {
1745
+ var browserWidth = document.documentElement.clientWidth;
1746
+ var browserHeight = document.documentElement.clientHeight;
1747
+ var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
1748
+ var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
1749
+ this._pos = // should use actual width/height below
1750
+ [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
1751
+ }
1752
+
1753
+ // move input on screen for focus, but hidden behind dialog
1754
+ this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
1755
+ inst.settings.onSelect = onSelect;
1756
+ this._inDialog = true;
1757
+ this.dpDiv.addClass(this._dialogClass);
1758
+ this._showDatepicker(this._dialogInput[0]);
1759
+ if ($.blockUI)
1760
+ $.blockUI(this.dpDiv);
1761
+ $.data(this._dialogInput[0], PROP_NAME, inst);
1762
+ return this;
1763
+ },
1764
+
1765
+ /* Detach a datepicker from its control.
1766
+ @param target element - the target input field or division or span */
1767
+ _destroyDatepicker: function(target) {
1768
+ var $target = $(target);
1769
+ var inst = $.data(target, PROP_NAME);
1770
+ if (!$target.hasClass(this.markerClassName)) {
1771
+ return;
1772
+ }
1773
+ var nodeName = target.nodeName.toLowerCase();
1774
+ $.removeData(target, PROP_NAME);
1775
+ if (nodeName == 'input') {
1776
+ inst.append.remove();
1777
+ inst.trigger.remove();
1778
+ $target.removeClass(this.markerClassName).
1779
+ unbind('focus', this._showDatepicker).
1780
+ unbind('keydown', this._doKeyDown).
1781
+ unbind('keypress', this._doKeyPress).
1782
+ unbind('keyup', this._doKeyUp);
1783
+ } else if (nodeName == 'div' || nodeName == 'span')
1784
+ $target.removeClass(this.markerClassName).empty();
1785
+ },
1786
+
1787
+ /* Enable the date picker to a jQuery selection.
1788
+ @param target element - the target input field or division or span */
1789
+ _enableDatepicker: function(target) {
1790
+ var $target = $(target);
1791
+ var inst = $.data(target, PROP_NAME);
1792
+ if (!$target.hasClass(this.markerClassName)) {
1793
+ return;
1794
+ }
1795
+ var nodeName = target.nodeName.toLowerCase();
1796
+ if (nodeName == 'input') {
1797
+ target.disabled = false;
1798
+ inst.trigger.filter('button').
1799
+ each(function() { this.disabled = false; }).end().
1800
+ filter('img').css({opacity: '1.0', cursor: ''});
1801
+ }
1802
+ else if (nodeName == 'div' || nodeName == 'span') {
1803
+ var inline = $target.children('.' + this._inlineClass);
1804
+ inline.children().removeClass('ui-state-disabled');
1805
+ inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
1806
+ removeAttr("disabled");
1807
+ }
1808
+ this._disabledInputs = $.map(this._disabledInputs,
1809
+ function(value) { return (value == target ? null : value); }); // delete entry
1810
+ },
1811
+
1812
+ /* Disable the date picker to a jQuery selection.
1813
+ @param target element - the target input field or division or span */
1814
+ _disableDatepicker: function(target) {
1815
+ var $target = $(target);
1816
+ var inst = $.data(target, PROP_NAME);
1817
+ if (!$target.hasClass(this.markerClassName)) {
1818
+ return;
1819
+ }
1820
+ var nodeName = target.nodeName.toLowerCase();
1821
+ if (nodeName == 'input') {
1822
+ target.disabled = true;
1823
+ inst.trigger.filter('button').
1824
+ each(function() { this.disabled = true; }).end().
1825
+ filter('img').css({opacity: '0.5', cursor: 'default'});
1826
+ }
1827
+ else if (nodeName == 'div' || nodeName == 'span') {
1828
+ var inline = $target.children('.' + this._inlineClass);
1829
+ inline.children().addClass('ui-state-disabled');
1830
+ inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
1831
+ attr("disabled", "disabled");
1832
+ }
1833
+ this._disabledInputs = $.map(this._disabledInputs,
1834
+ function(value) { return (value == target ? null : value); }); // delete entry
1835
+ this._disabledInputs[this._disabledInputs.length] = target;
1836
+ },
1837
+
1838
+ /* Is the first field in a jQuery collection disabled as a datepicker?
1839
+ @param target element - the target input field or division or span
1840
+ @return boolean - true if disabled, false if enabled */
1841
+ _isDisabledDatepicker: function(target) {
1842
+ if (!target) {
1843
+ return false;
1844
+ }
1845
+ for (var i = 0; i < this._disabledInputs.length; i++) {
1846
+ if (this._disabledInputs[i] == target)
1847
+ return true;
1848
+ }
1849
+ return false;
1850
+ },
1851
+
1852
+ /* Retrieve the instance data for the target control.
1853
+ @param target element - the target input field or division or span
1854
+ @return object - the associated instance data
1855
+ @throws error if a jQuery problem getting data */
1856
+ _getInst: function(target) {
1857
+ try {
1858
+ return $.data(target, PROP_NAME);
1859
+ }
1860
+ catch (err) {
1861
+ throw 'Missing instance data for this datepicker';
1862
+ }
1863
+ },
1864
+
1865
+ /* Update or retrieve the settings for a date picker attached to an input field or division.
1866
+ @param target element - the target input field or division or span
1867
+ @param name object - the new settings to update or
1868
+ string - the name of the setting to change or retrieve,
1869
+ when retrieving also 'all' for all instance settings or
1870
+ 'defaults' for all global defaults
1871
+ @param value any - the new value for the setting
1872
+ (omit if above is an object or to retrieve a value) */
1873
+ _optionDatepicker: function(target, name, value) {
1874
+ var inst = this._getInst(target);
1875
+ if (arguments.length == 2 && typeof name == 'string') {
1876
+ return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
1877
+ (inst ? (name == 'all' ? $.extend({}, inst.settings) :
1878
+ this._get(inst, name)) : null));
1879
+ }
1880
+ var settings = name || {};
1881
+ if (typeof name == 'string') {
1882
+ settings = {};
1883
+ settings[name] = value;
1884
+ }
1885
+ if (inst) {
1886
+ if (this._curInst == inst) {
1887
+ this._hideDatepicker();
1888
+ }
1889
+ var date = this._getDateDatepicker(target, true);
1890
+ var minDate = this._getMinMaxDate(inst, 'min');
1891
+ var maxDate = this._getMinMaxDate(inst, 'max');
1892
+ extendRemove(inst.settings, settings);
1893
+ // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
1894
+ if (minDate !== null && settings['dateFormat'] !== undefined && settings['minDate'] === undefined)
1895
+ inst.settings.minDate = this._formatDate(inst, minDate);
1896
+ if (maxDate !== null && settings['dateFormat'] !== undefined && settings['maxDate'] === undefined)
1897
+ inst.settings.maxDate = this._formatDate(inst, maxDate);
1898
+ this._attachments($(target), inst);
1899
+ this._autoSize(inst);
1900
+ this._setDate(inst, date);
1901
+ this._updateAlternate(inst);
1902
+ this._updateDatepicker(inst);
1903
+ }
1904
+ },
1905
+
1906
+ // change method deprecated
1907
+ _changeDatepicker: function(target, name, value) {
1908
+ this._optionDatepicker(target, name, value);
1909
+ },
1910
+
1911
+ /* Redraw the date picker attached to an input field or division.
1912
+ @param target element - the target input field or division or span */
1913
+ _refreshDatepicker: function(target) {
1914
+ var inst = this._getInst(target);
1915
+ if (inst) {
1916
+ this._updateDatepicker(inst);
1917
+ }
1918
+ },
1919
+
1920
+ /* Set the dates for a jQuery selection.
1921
+ @param target element - the target input field or division or span
1922
+ @param date Date - the new date */
1923
+ _setDateDatepicker: function(target, date) {
1924
+ var inst = this._getInst(target);
1925
+ if (inst) {
1926
+ this._setDate(inst, date);
1927
+ this._updateDatepicker(inst);
1928
+ this._updateAlternate(inst);
1929
+ }
1930
+ },
1931
+
1932
+ /* Get the date(s) for the first entry in a jQuery selection.
1933
+ @param target element - the target input field or division or span
1934
+ @param noDefault boolean - true if no default date is to be used
1935
+ @return Date - the current date */
1936
+ _getDateDatepicker: function(target, noDefault) {
1937
+ var inst = this._getInst(target);
1938
+ if (inst && !inst.inline)
1939
+ this._setDateFromField(inst, noDefault);
1940
+ return (inst ? this._getDate(inst) : null);
1941
+ },
1942
+
1943
+ /* Handle keystrokes. */
1944
+ _doKeyDown: function(event) {
1945
+ var inst = $.datepicker._getInst(event.target);
1946
+ var handled = true;
1947
+ var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
1948
+ inst._keyEvent = true;
1949
+ if ($.datepicker._datepickerShowing)
1950
+ switch (event.keyCode) {
1951
+ case 9: $.datepicker._hideDatepicker();
1952
+ handled = false;
1953
+ break; // hide on tab out
1954
+ case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' +
1955
+ $.datepicker._currentClass + ')', inst.dpDiv);
1956
+ if (sel[0])
1957
+ $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
1958
+ else
1959
+ $.datepicker._hideDatepicker();
1960
+ return false; // don't submit the form
1961
+ break; // select the value on enter
1962
+ case 27: $.datepicker._hideDatepicker();
1963
+ break; // hide on escape
1964
+ case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
1965
+ -$.datepicker._get(inst, 'stepBigMonths') :
1966
+ -$.datepicker._get(inst, 'stepMonths')), 'M');
1967
+ break; // previous month/year on page up/+ ctrl
1968
+ case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
1969
+ +$.datepicker._get(inst, 'stepBigMonths') :
1970
+ +$.datepicker._get(inst, 'stepMonths')), 'M');
1971
+ break; // next month/year on page down/+ ctrl
1972
+ case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
1973
+ handled = event.ctrlKey || event.metaKey;
1974
+ break; // clear on ctrl or command +end
1975
+ case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
1976
+ handled = event.ctrlKey || event.metaKey;
1977
+ break; // current on ctrl or command +home
1978
+ case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
1979
+ handled = event.ctrlKey || event.metaKey;
1980
+ // -1 day on ctrl or command +left
1981
+ if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
1982
+ -$.datepicker._get(inst, 'stepBigMonths') :
1983
+ -$.datepicker._get(inst, 'stepMonths')), 'M');
1984
+ // next month/year on alt +left on Mac
1985
+ break;
1986
+ case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
1987
+ handled = event.ctrlKey || event.metaKey;
1988
+ break; // -1 week on ctrl or command +up
1989
+ case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
1990
+ handled = event.ctrlKey || event.metaKey;
1991
+ // +1 day on ctrl or command +right
1992
+ if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
1993
+ +$.datepicker._get(inst, 'stepBigMonths') :
1994
+ +$.datepicker._get(inst, 'stepMonths')), 'M');
1995
+ // next month/year on alt +right
1996
+ break;
1997
+ case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
1998
+ handled = event.ctrlKey || event.metaKey;
1999
+ break; // +1 week on ctrl or command +down
2000
+ default: handled = false;
2001
+ }
2002
+ else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
2003
+ $.datepicker._showDatepicker(this);
2004
+ else {
2005
+ handled = false;
2006
+ }
2007
+ if (handled) {
2008
+ event.preventDefault();
2009
+ event.stopPropagation();
2010
+ }
2011
+ },
2012
+
2013
+ /* Filter entered characters - based on date format. */
2014
+ _doKeyPress: function(event) {
2015
+ var inst = $.datepicker._getInst(event.target);
2016
+ if ($.datepicker._get(inst, 'constrainInput')) {
2017
+ var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
2018
+ var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
2019
+ return event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
2020
+ }
2021
+ },
2022
+
2023
+ /* Synchronise manual entry and field/alternate field. */
2024
+ _doKeyUp: function(event) {
2025
+ var inst = $.datepicker._getInst(event.target);
2026
+ if (inst.input.val() != inst.lastVal) {
2027
+ try {
2028
+ var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
2029
+ (inst.input ? inst.input.val() : null),
2030
+ $.datepicker._getFormatConfig(inst));
2031
+ if (date) { // only if valid
2032
+ $.datepicker._setDateFromField(inst);
2033
+ $.datepicker._updateAlternate(inst);
2034
+ $.datepicker._updateDatepicker(inst);
2035
+ }
2036
+ }
2037
+ catch (event) {
2038
+ $.datepicker.log(event);
2039
+ }
2040
+ }
2041
+ return true;
2042
+ },
2043
+
2044
+ /* Pop-up the date picker for a given input field.
2045
+ @param input element - the input field attached to the date picker or
2046
+ event - if triggered by focus */
2047
+ _showDatepicker: function(input) {
2048
+ input = input.target || input;
2049
+ if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
2050
+ input = $('input', input.parentNode)[0];
2051
+ if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
2052
+ return;
2053
+ var inst = $.datepicker._getInst(input);
2054
+ if ($.datepicker._curInst && $.datepicker._curInst != inst) {
2055
+ $.datepicker._curInst.dpDiv.stop(true, true);
2056
+ }
2057
+ var beforeShow = $.datepicker._get(inst, 'beforeShow');
2058
+ extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
2059
+ inst.lastVal = null;
2060
+ $.datepicker._lastInput = input;
2061
+ $.datepicker._setDateFromField(inst);
2062
+ if ($.datepicker._inDialog) // hide cursor
2063
+ input.value = '';
2064
+ if (!$.datepicker._pos) { // position below input
2065
+ $.datepicker._pos = $.datepicker._findPos(input);
2066
+ $.datepicker._pos[1] += input.offsetHeight; // add the height
2067
+ }
2068
+ var isFixed = false;
2069
+ $(input).parents().each(function() {
2070
+ isFixed |= $(this).css('position') == 'fixed';
2071
+ return !isFixed;
2072
+ });
2073
+ if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
2074
+ $.datepicker._pos[0] -= document.documentElement.scrollLeft;
2075
+ $.datepicker._pos[1] -= document.documentElement.scrollTop;
2076
+ }
2077
+ var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
2078
+ $.datepicker._pos = null;
2079
+ //to avoid flashes on Firefox
2080
+ inst.dpDiv.empty();
2081
+ // determine sizing offscreen
2082
+ inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
2083
+ $.datepicker._updateDatepicker(inst);
2084
+ // fix width for dynamic number of date pickers
2085
+ // and adjust position before showing
2086
+ offset = $.datepicker._checkOffset(inst, offset, isFixed);
2087
+ inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
2088
+ 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
2089
+ left: offset.left + 'px', top: offset.top + 'px'});
2090
+ if (!inst.inline) {
2091
+ var showAnim = $.datepicker._get(inst, 'showAnim');
2092
+ var duration = $.datepicker._get(inst, 'duration');
2093
+ var postProcess = function() {
2094
+ var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
2095
+ if( !! cover.length ){
2096
+ var borders = $.datepicker._getBorders(inst.dpDiv);
2097
+ cover.css({left: -borders[0], top: -borders[1],
2098
+ width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
2099
+ }
2100
+ };
2101
+ inst.dpDiv.zIndex($(input).zIndex()+1);
2102
+ $.datepicker._datepickerShowing = true;
2103
+ if ($.effects && $.effects[showAnim])
2104
+ inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
2105
+ else
2106
+ inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
2107
+ if (!showAnim || !duration)
2108
+ postProcess();
2109
+ if (inst.input.is(':visible') && !inst.input.is(':disabled'))
2110
+ inst.input.focus();
2111
+ $.datepicker._curInst = inst;
2112
+ }
2113
+ },
2114
+
2115
+ /* Generate the date picker content. */
2116
+ _updateDatepicker: function(inst) {
2117
+ var self = this;
2118
+ var borders = $.datepicker._getBorders(inst.dpDiv);
2119
+ instActive = inst; // for delegate hover events
2120
+ inst.dpDiv.empty().append(this._generateHTML(inst));
2121
+ var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
2122
+ if( !!cover.length ){ //avoid call to outerXXXX() when not in IE6
2123
+ cover.css({left: -borders[0], top: -borders[1], width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
2124
+ }
2125
+ inst.dpDiv.find('.' + this._dayOverClass + ' a').mouseover();
2126
+ var numMonths = this._getNumberOfMonths(inst);
2127
+ var cols = numMonths[1];
2128
+ var width = 17;
2129
+ inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
2130
+ if (cols > 1)
2131
+ inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
2132
+ inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
2133
+ 'Class']('ui-datepicker-multi');
2134
+ inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
2135
+ 'Class']('ui-datepicker-rtl');
2136
+ if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
2137
+ // #6694 - don't focus the input if it's already focused
2138
+ // this breaks the change event in IE
2139
+ inst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement)
2140
+ inst.input.focus();
2141
+ // deffered render of the years select (to avoid flashes on Firefox)
2142
+ if( inst.yearshtml ){
2143
+ var origyearshtml = inst.yearshtml;
2144
+ setTimeout(function(){
2145
+ //assure that inst.yearshtml didn't change.
2146
+ if( origyearshtml === inst.yearshtml && inst.yearshtml ){
2147
+ inst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml);
2148
+ }
2149
+ origyearshtml = inst.yearshtml = null;
2150
+ }, 0);
2151
+ }
2152
+ },
2153
+
2154
+ /* Retrieve the size of left and top borders for an element.
2155
+ @param elem (jQuery object) the element of interest
2156
+ @return (number[2]) the left and top borders */
2157
+ _getBorders: function(elem) {
2158
+ var convert = function(value) {
2159
+ return {thin: 1, medium: 2, thick: 3}[value] || value;
2160
+ };
2161
+ return [parseFloat(convert(elem.css('border-left-width'))),
2162
+ parseFloat(convert(elem.css('border-top-width')))];
2163
+ },
2164
+
2165
+ /* Check positioning to remain on screen. */
2166
+ _checkOffset: function(inst, offset, isFixed) {
2167
+ var dpWidth = inst.dpDiv.outerWidth();
2168
+ var dpHeight = inst.dpDiv.outerHeight();
2169
+ var inputWidth = inst.input ? inst.input.outerWidth() : 0;
2170
+ var inputHeight = inst.input ? inst.input.outerHeight() : 0;
2171
+ var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
2172
+ var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
2173
+
2174
+ offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
2175
+ offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
2176
+ offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
2177
+
2178
+ // now check if datepicker is showing outside window viewport - move to a better place if so.
2179
+ offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
2180
+ Math.abs(offset.left + dpWidth - viewWidth) : 0);
2181
+ offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
2182
+ Math.abs(dpHeight + inputHeight) : 0);
2183
+
2184
+ return offset;
2185
+ },
2186
+
2187
+ /* Find an object's position on the screen. */
2188
+ _findPos: function(obj) {
2189
+ var inst = this._getInst(obj);
2190
+ var isRTL = this._get(inst, 'isRTL');
2191
+ while (obj && (obj.type == 'hidden' || obj.nodeType != 1 || $.expr.filters.hidden(obj))) {
2192
+ obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
2193
+ }
2194
+ var position = $(obj).offset();
2195
+ return [position.left, position.top];
2196
+ },
2197
+
2198
+ /* Hide the date picker from view.
2199
+ @param input element - the input field attached to the date picker */
2200
+ _hideDatepicker: function(input) {
2201
+ var inst = this._curInst;
2202
+ if (!inst || (input && inst != $.data(input, PROP_NAME)))
2203
+ return;
2204
+ if (this._datepickerShowing) {
2205
+ var showAnim = this._get(inst, 'showAnim');
2206
+ var duration = this._get(inst, 'duration');
2207
+ var postProcess = function() {
2208
+ $.datepicker._tidyDialog(inst);
2209
+ this._curInst = null;
2210
+ };
2211
+ if ($.effects && $.effects[showAnim])
2212
+ inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
2213
+ else
2214
+ inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
2215
+ (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
2216
+ if (!showAnim)
2217
+ postProcess();
2218
+ var onClose = this._get(inst, 'onClose');
2219
+ if (onClose)
2220
+ onClose.apply((inst.input ? inst.input[0] : null),
2221
+ [(inst.input ? inst.input.val() : ''), inst]); // trigger custom callback
2222
+ this._datepickerShowing = false;
2223
+ this._lastInput = null;
2224
+ if (this._inDialog) {
2225
+ this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
2226
+ if ($.blockUI) {
2227
+ $.unblockUI();
2228
+ $('body').append(this.dpDiv);
2229
+ }
2230
+ }
2231
+ this._inDialog = false;
2232
+ }
2233
+ },
2234
+
2235
+ /* Tidy up after a dialog display. */
2236
+ _tidyDialog: function(inst) {
2237
+ inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
2238
+ },
2239
+
2240
+ /* Close date picker if clicked elsewhere. */
2241
+ _checkExternalClick: function(event) {
2242
+ if (!$.datepicker._curInst)
2243
+ return;
2244
+ var $target = $(event.target);
2245
+ if ($target[0].id != $.datepicker._mainDivId &&
2246
+ $target.parents('#' + $.datepicker._mainDivId).length == 0 &&
2247
+ !$target.hasClass($.datepicker.markerClassName) &&
2248
+ !$target.hasClass($.datepicker._triggerClass) &&
2249
+ $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
2250
+ $.datepicker._hideDatepicker();
2251
+ },
2252
+
2253
+ /* Adjust one of the date sub-fields. */
2254
+ _adjustDate: function(id, offset, period) {
2255
+ var target = $(id);
2256
+ var inst = this._getInst(target[0]);
2257
+ if (this._isDisabledDatepicker(target[0])) {
2258
+ return;
2259
+ }
2260
+ this._adjustInstDate(inst, offset +
2261
+ (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
2262
+ period);
2263
+ this._updateDatepicker(inst);
2264
+ },
2265
+
2266
+ /* Action for current link. */
2267
+ _gotoToday: function(id) {
2268
+ var target = $(id);
2269
+ var inst = this._getInst(target[0]);
2270
+ if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
2271
+ inst.selectedDay = inst.currentDay;
2272
+ inst.drawMonth = inst.selectedMonth = inst.currentMonth;
2273
+ inst.drawYear = inst.selectedYear = inst.currentYear;
2274
+ }
2275
+ else {
2276
+ var date = new Date();
2277
+ inst.selectedDay = date.getDate();
2278
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
2279
+ inst.drawYear = inst.selectedYear = date.getFullYear();
2280
+ }
2281
+ this._notifyChange(inst);
2282
+ this._adjustDate(target);
2283
+ },
2284
+
2285
+ /* Action for selecting a new month/year. */
2286
+ _selectMonthYear: function(id, select, period) {
2287
+ var target = $(id);
2288
+ var inst = this._getInst(target[0]);
2289
+ inst._selectingMonthYear = false;
2290
+ inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
2291
+ inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
2292
+ parseInt(select.options[select.selectedIndex].value,10);
2293
+ this._notifyChange(inst);
2294
+ this._adjustDate(target);
2295
+ },
2296
+
2297
+ /* Restore input focus after not changing month/year. */
2298
+ _clickMonthYear: function(id) {
2299
+ var target = $(id);
2300
+ var inst = this._getInst(target[0]);
2301
+ if (inst.input && inst._selectingMonthYear) {
2302
+ setTimeout(function() {
2303
+ inst.input.focus();
2304
+ }, 0);
2305
+ }
2306
+ inst._selectingMonthYear = !inst._selectingMonthYear;
2307
+ },
2308
+
2309
+ /* Action for selecting a day. */
2310
+ _selectDay: function(id, month, year, td) {
2311
+ var target = $(id);
2312
+ if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
2313
+ return;
2314
+ }
2315
+ var inst = this._getInst(target[0]);
2316
+ inst.selectedDay = inst.currentDay = $('a', td).html();
2317
+ inst.selectedMonth = inst.currentMonth = month;
2318
+ inst.selectedYear = inst.currentYear = year;
2319
+ this._selectDate(id, this._formatDate(inst,
2320
+ inst.currentDay, inst.currentMonth, inst.currentYear));
2321
+ },
2322
+
2323
+ /* Erase the input field and hide the date picker. */
2324
+ _clearDate: function(id) {
2325
+ var target = $(id);
2326
+ var inst = this._getInst(target[0]);
2327
+ this._selectDate(target, '');
2328
+ },
2329
+
2330
+ /* Update the input field with the selected date. */
2331
+ _selectDate: function(id, dateStr) {
2332
+ var target = $(id);
2333
+ var inst = this._getInst(target[0]);
2334
+ dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
2335
+ if (inst.input)
2336
+ inst.input.val(dateStr);
2337
+ this._updateAlternate(inst);
2338
+ var onSelect = this._get(inst, 'onSelect');
2339
+ if (onSelect)
2340
+ onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
2341
+ else if (inst.input)
2342
+ inst.input.trigger('change'); // fire the change event
2343
+ if (inst.inline)
2344
+ this._updateDatepicker(inst);
2345
+ else {
2346
+ this._hideDatepicker();
2347
+ this._lastInput = inst.input[0];
2348
+ if (typeof(inst.input[0]) != 'object')
2349
+ inst.input.focus(); // restore focus
2350
+ this._lastInput = null;
2351
+ }
2352
+ },
2353
+
2354
+ /* Update any alternate field to synchronise with the main field. */
2355
+ _updateAlternate: function(inst) {
2356
+ var altField = this._get(inst, 'altField');
2357
+ if (altField) { // update alternate field too
2358
+ var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
2359
+ var date = this._getDate(inst);
2360
+ var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
2361
+ $(altField).each(function() { $(this).val(dateStr); });
2362
+ }
2363
+ },
2364
+
2365
+ /* Set as beforeShowDay function to prevent selection of weekends.
2366
+ @param date Date - the date to customise
2367
+ @return [boolean, string] - is this date selectable?, what is its CSS class? */
2368
+ noWeekends: function(date) {
2369
+ var day = date.getDay();
2370
+ return [(day > 0 && day < 6), ''];
2371
+ },
2372
+
2373
+ /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
2374
+ @param date Date - the date to get the week for
2375
+ @return number - the number of the week within the year that contains this date */
2376
+ iso8601Week: function(date) {
2377
+ var checkDate = new Date(date.getTime());
2378
+ // Find Thursday of this week starting on Monday
2379
+ checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
2380
+ var time = checkDate.getTime();
2381
+ checkDate.setMonth(0); // Compare with Jan 1
2382
+ checkDate.setDate(1);
2383
+ return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
2384
+ },
2385
+
2386
+ /* Parse a string value into a date object.
2387
+ See formatDate below for the possible formats.
2388
+
2389
+ @param format string - the expected format of the date
2390
+ @param value string - the date in the above format
2391
+ @param settings Object - attributes include:
2392
+ shortYearCutoff number - the cutoff year for determining the century (optional)
2393
+ dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
2394
+ dayNames string[7] - names of the days from Sunday (optional)
2395
+ monthNamesShort string[12] - abbreviated names of the months (optional)
2396
+ monthNames string[12] - names of the months (optional)
2397
+ @return Date - the extracted date value or null if value is blank */
2398
+ parseDate: function (format, value, settings) {
2399
+ if (format == null || value == null)
2400
+ throw 'Invalid arguments';
2401
+ value = (typeof value == 'object' ? value.toString() : value + '');
2402
+ if (value == '')
2403
+ return null;
2404
+ var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
2405
+ shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
2406
+ new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
2407
+ var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
2408
+ var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
2409
+ var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
2410
+ var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
2411
+ var year = -1;
2412
+ var month = -1;
2413
+ var day = -1;
2414
+ var doy = -1;
2415
+ var literal = false;
2416
+ // Check whether a format character is doubled
2417
+ var lookAhead = function(match) {
2418
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
2419
+ if (matches)
2420
+ iFormat++;
2421
+ return matches;
2422
+ };
2423
+ // Extract a number from the string value
2424
+ var getNumber = function(match) {
2425
+ var isDoubled = lookAhead(match);
2426
+ var size = (match == '@' ? 14 : (match == '!' ? 20 :
2427
+ (match == 'y' && isDoubled ? 4 : (match == 'o' ? 3 : 2))));
2428
+ var digits = new RegExp('^\\d{1,' + size + '}');
2429
+ var num = value.substring(iValue).match(digits);
2430
+ if (!num)
2431
+ throw 'Missing number at position ' + iValue;
2432
+ iValue += num[0].length;
2433
+ return parseInt(num[0], 10);
2434
+ };
2435
+ // Extract a name from the string value and convert to an index
2436
+ var getName = function(match, shortNames, longNames) {
2437
+ var names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
2438
+ return [ [k, v] ];
2439
+ }).sort(function (a, b) {
2440
+ return -(a[1].length - b[1].length);
2441
+ });
2442
+ var index = -1;
2443
+ $.each(names, function (i, pair) {
2444
+ var name = pair[1];
2445
+ if (value.substr(iValue, name.length).toLowerCase() == name.toLowerCase()) {
2446
+ index = pair[0];
2447
+ iValue += name.length;
2448
+ return false;
2449
+ }
2450
+ });
2451
+ if (index != -1)
2452
+ return index + 1;
2453
+ else
2454
+ throw 'Unknown name at position ' + iValue;
2455
+ };
2456
+ // Confirm that a literal character matches the string value
2457
+ var checkLiteral = function() {
2458
+ if (value.charAt(iValue) != format.charAt(iFormat))
2459
+ throw 'Unexpected literal at position ' + iValue;
2460
+ iValue++;
2461
+ };
2462
+ var iValue = 0;
2463
+ for (var iFormat = 0; iFormat < format.length; iFormat++) {
2464
+ if (literal)
2465
+ if (format.charAt(iFormat) == "'" && !lookAhead("'"))
2466
+ literal = false;
2467
+ else
2468
+ checkLiteral();
2469
+ else
2470
+ switch (format.charAt(iFormat)) {
2471
+ case 'd':
2472
+ day = getNumber('d');
2473
+ break;
2474
+ case 'D':
2475
+ getName('D', dayNamesShort, dayNames);
2476
+ break;
2477
+ case 'o':
2478
+ doy = getNumber('o');
2479
+ break;
2480
+ case 'm':
2481
+ month = getNumber('m');
2482
+ break;
2483
+ case 'M':
2484
+ month = getName('M', monthNamesShort, monthNames);
2485
+ break;
2486
+ case 'y':
2487
+ year = getNumber('y');
2488
+ break;
2489
+ case '@':
2490
+ var date = new Date(getNumber('@'));
2491
+ year = date.getFullYear();
2492
+ month = date.getMonth() + 1;
2493
+ day = date.getDate();
2494
+ break;
2495
+ case '!':
2496
+ var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
2497
+ year = date.getFullYear();
2498
+ month = date.getMonth() + 1;
2499
+ day = date.getDate();
2500
+ break;
2501
+ case "'":
2502
+ if (lookAhead("'"))
2503
+ checkLiteral();
2504
+ else
2505
+ literal = true;
2506
+ break;
2507
+ default:
2508
+ checkLiteral();
2509
+ }
2510
+ }
2511
+ if (year == -1)
2512
+ year = new Date().getFullYear();
2513
+ else if (year < 100)
2514
+ year += new Date().getFullYear() - new Date().getFullYear() % 100 +
2515
+ (year <= shortYearCutoff ? 0 : -100);
2516
+ if (doy > -1) {
2517
+ month = 1;
2518
+ day = doy;
2519
+ do {
2520
+ var dim = this._getDaysInMonth(year, month - 1);
2521
+ if (day <= dim)
2522
+ break;
2523
+ month++;
2524
+ day -= dim;
2525
+ } while (true);
2526
+ }
2527
+ var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
2528
+ if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
2529
+ throw 'Invalid date'; // E.g. 31/02/00
2530
+ return date;
2531
+ },
2532
+
2533
+ /* Standard date formats. */
2534
+ ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
2535
+ COOKIE: 'D, dd M yy',
2536
+ ISO_8601: 'yy-mm-dd',
2537
+ RFC_822: 'D, d M y',
2538
+ RFC_850: 'DD, dd-M-y',
2539
+ RFC_1036: 'D, d M y',
2540
+ RFC_1123: 'D, d M yy',
2541
+ RFC_2822: 'D, d M yy',
2542
+ RSS: 'D, d M y', // RFC 822
2543
+ TICKS: '!',
2544
+ TIMESTAMP: '@',
2545
+ W3C: 'yy-mm-dd', // ISO 8601
2546
+
2547
+ _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
2548
+ Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
2549
+
2550
+ /* Format a date object into a string value.
2551
+ The format can be combinations of the following:
2552
+ d - day of month (no leading zero)
2553
+ dd - day of month (two digit)
2554
+ o - day of year (no leading zeros)
2555
+ oo - day of year (three digit)
2556
+ D - day name short
2557
+ DD - day name long
2558
+ m - month of year (no leading zero)
2559
+ mm - month of year (two digit)
2560
+ M - month name short
2561
+ MM - month name long
2562
+ y - year (two digit)
2563
+ yy - year (four digit)
2564
+ @ - Unix timestamp (ms since 01/01/1970)
2565
+ ! - Windows ticks (100ns since 01/01/0001)
2566
+ '...' - literal text
2567
+ '' - single quote
2568
+
2569
+ @param format string - the desired format of the date
2570
+ @param date Date - the date value to format
2571
+ @param settings Object - attributes include:
2572
+ dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
2573
+ dayNames string[7] - names of the days from Sunday (optional)
2574
+ monthNamesShort string[12] - abbreviated names of the months (optional)
2575
+ monthNames string[12] - names of the months (optional)
2576
+ @return string - the date in the above format */
2577
+ formatDate: function (format, date, settings) {
2578
+ if (!date)
2579
+ return '';
2580
+ var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
2581
+ var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
2582
+ var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
2583
+ var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
2584
+ // Check whether a format character is doubled
2585
+ var lookAhead = function(match) {
2586
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
2587
+ if (matches)
2588
+ iFormat++;
2589
+ return matches;
2590
+ };
2591
+ // Format a number, with leading zero if necessary
2592
+ var formatNumber = function(match, value, len) {
2593
+ var num = '' + value;
2594
+ if (lookAhead(match))
2595
+ while (num.length < len)
2596
+ num = '0' + num;
2597
+ return num;
2598
+ };
2599
+ // Format a name, short or long as requested
2600
+ var formatName = function(match, value, shortNames, longNames) {
2601
+ return (lookAhead(match) ? longNames[value] : shortNames[value]);
2602
+ };
2603
+ var output = '';
2604
+ var literal = false;
2605
+ if (date)
2606
+ for (var iFormat = 0; iFormat < format.length; iFormat++) {
2607
+ if (literal)
2608
+ if (format.charAt(iFormat) == "'" && !lookAhead("'"))
2609
+ literal = false;
2610
+ else
2611
+ output += format.charAt(iFormat);
2612
+ else
2613
+ switch (format.charAt(iFormat)) {
2614
+ case 'd':
2615
+ output += formatNumber('d', date.getDate(), 2);
2616
+ break;
2617
+ case 'D':
2618
+ output += formatName('D', date.getDay(), dayNamesShort, dayNames);
2619
+ break;
2620
+ case 'o':
2621
+ output += formatNumber('o',
2622
+ (date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
2623
+ break;
2624
+ case 'm':
2625
+ output += formatNumber('m', date.getMonth() + 1, 2);
2626
+ break;
2627
+ case 'M':
2628
+ output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
2629
+ break;
2630
+ case 'y':
2631
+ output += (lookAhead('y') ? date.getFullYear() :
2632
+ (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
2633
+ break;
2634
+ case '@':
2635
+ output += date.getTime();
2636
+ break;
2637
+ case '!':
2638
+ output += date.getTime() * 10000 + this._ticksTo1970;
2639
+ break;
2640
+ case "'":
2641
+ if (lookAhead("'"))
2642
+ output += "'";
2643
+ else
2644
+ literal = true;
2645
+ break;
2646
+ default:
2647
+ output += format.charAt(iFormat);
2648
+ }
2649
+ }
2650
+ return output;
2651
+ },
2652
+
2653
+ /* Extract all possible characters from the date format. */
2654
+ _possibleChars: function (format) {
2655
+ var chars = '';
2656
+ var literal = false;
2657
+ // Check whether a format character is doubled
2658
+ var lookAhead = function(match) {
2659
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
2660
+ if (matches)
2661
+ iFormat++;
2662
+ return matches;
2663
+ };
2664
+ for (var iFormat = 0; iFormat < format.length; iFormat++)
2665
+ if (literal)
2666
+ if (format.charAt(iFormat) == "'" && !lookAhead("'"))
2667
+ literal = false;
2668
+ else
2669
+ chars += format.charAt(iFormat);
2670
+ else
2671
+ switch (format.charAt(iFormat)) {
2672
+ case 'd': case 'm': case 'y': case '@':
2673
+ chars += '0123456789';
2674
+ break;
2675
+ case 'D': case 'M':
2676
+ return null; // Accept anything
2677
+ case "'":
2678
+ if (lookAhead("'"))
2679
+ chars += "'";
2680
+ else
2681
+ literal = true;
2682
+ break;
2683
+ default:
2684
+ chars += format.charAt(iFormat);
2685
+ }
2686
+ return chars;
2687
+ },
2688
+
2689
+ /* Get a setting value, defaulting if necessary. */
2690
+ _get: function(inst, name) {
2691
+ return inst.settings[name] !== undefined ?
2692
+ inst.settings[name] : this._defaults[name];
2693
+ },
2694
+
2695
+ /* Parse existing date and initialise date picker. */
2696
+ _setDateFromField: function(inst, noDefault) {
2697
+ if (inst.input.val() == inst.lastVal) {
2698
+ return;
2699
+ }
2700
+ var dateFormat = this._get(inst, 'dateFormat');
2701
+ var dates = inst.lastVal = inst.input ? inst.input.val() : null;
2702
+ var date, defaultDate;
2703
+ date = defaultDate = this._getDefaultDate(inst);
2704
+ var settings = this._getFormatConfig(inst);
2705
+ try {
2706
+ date = this.parseDate(dateFormat, dates, settings) || defaultDate;
2707
+ } catch (event) {
2708
+ this.log(event);
2709
+ dates = (noDefault ? '' : dates);
2710
+ }
2711
+ inst.selectedDay = date.getDate();
2712
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
2713
+ inst.drawYear = inst.selectedYear = date.getFullYear();
2714
+ inst.currentDay = (dates ? date.getDate() : 0);
2715
+ inst.currentMonth = (dates ? date.getMonth() : 0);
2716
+ inst.currentYear = (dates ? date.getFullYear() : 0);
2717
+ this._adjustInstDate(inst);
2718
+ },
2719
+
2720
+ /* Retrieve the default date shown on opening. */
2721
+ _getDefaultDate: function(inst) {
2722
+ return this._restrictMinMax(inst,
2723
+ this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
2724
+ },
2725
+
2726
+ /* A date may be specified as an exact value or a relative one. */
2727
+ _determineDate: function(inst, date, defaultDate) {
2728
+ var offsetNumeric = function(offset) {
2729
+ var date = new Date();
2730
+ date.setDate(date.getDate() + offset);
2731
+ return date;
2732
+ };
2733
+ var offsetString = function(offset) {
2734
+ try {
2735
+ return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
2736
+ offset, $.datepicker._getFormatConfig(inst));
2737
+ }
2738
+ catch (e) {
2739
+ // Ignore
2740
+ }
2741
+ var date = (offset.toLowerCase().match(/^c/) ?
2742
+ $.datepicker._getDate(inst) : null) || new Date();
2743
+ var year = date.getFullYear();
2744
+ var month = date.getMonth();
2745
+ var day = date.getDate();
2746
+ var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
2747
+ var matches = pattern.exec(offset);
2748
+ while (matches) {
2749
+ switch (matches[2] || 'd') {
2750
+ case 'd' : case 'D' :
2751
+ day += parseInt(matches[1],10); break;
2752
+ case 'w' : case 'W' :
2753
+ day += parseInt(matches[1],10) * 7; break;
2754
+ case 'm' : case 'M' :
2755
+ month += parseInt(matches[1],10);
2756
+ day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
2757
+ break;
2758
+ case 'y': case 'Y' :
2759
+ year += parseInt(matches[1],10);
2760
+ day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
2761
+ break;
2762
+ }
2763
+ matches = pattern.exec(offset);
2764
+ }
2765
+ return new Date(year, month, day);
2766
+ };
2767
+ var newDate = (date == null || date === '' ? defaultDate : (typeof date == 'string' ? offsetString(date) :
2768
+ (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
2769
+ newDate = (newDate && newDate.toString() == 'Invalid Date' ? defaultDate : newDate);
2770
+ if (newDate) {
2771
+ newDate.setHours(0);
2772
+ newDate.setMinutes(0);
2773
+ newDate.setSeconds(0);
2774
+ newDate.setMilliseconds(0);
2775
+ }
2776
+ return this._daylightSavingAdjust(newDate);
2777
+ },
2778
+
2779
+ /* Handle switch to/from daylight saving.
2780
+ Hours may be non-zero on daylight saving cut-over:
2781
+ > 12 when midnight changeover, but then cannot generate
2782
+ midnight datetime, so jump to 1AM, otherwise reset.
2783
+ @param date (Date) the date to check
2784
+ @return (Date) the corrected date */
2785
+ _daylightSavingAdjust: function(date) {
2786
+ if (!date) return null;
2787
+ date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
2788
+ return date;
2789
+ },
2790
+
2791
+ /* Set the date(s) directly. */
2792
+ _setDate: function(inst, date, noChange) {
2793
+ var clear = !date;
2794
+ var origMonth = inst.selectedMonth;
2795
+ var origYear = inst.selectedYear;
2796
+ var newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
2797
+ inst.selectedDay = inst.currentDay = newDate.getDate();
2798
+ inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
2799
+ inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
2800
+ if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
2801
+ this._notifyChange(inst);
2802
+ this._adjustInstDate(inst);
2803
+ if (inst.input) {
2804
+ inst.input.val(clear ? '' : this._formatDate(inst));
2805
+ }
2806
+ },
2807
+
2808
+ /* Retrieve the date(s) directly. */
2809
+ _getDate: function(inst) {
2810
+ var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
2811
+ this._daylightSavingAdjust(new Date(
2812
+ inst.currentYear, inst.currentMonth, inst.currentDay)));
2813
+ return startDate;
2814
+ },
2815
+
2816
+ /* Generate the HTML for the current state of the date picker. */
2817
+ _generateHTML: function(inst) {
2818
+ var today = new Date();
2819
+ today = this._daylightSavingAdjust(
2820
+ new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
2821
+ var isRTL = this._get(inst, 'isRTL');
2822
+ var showButtonPanel = this._get(inst, 'showButtonPanel');
2823
+ var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
2824
+ var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
2825
+ var numMonths = this._getNumberOfMonths(inst);
2826
+ var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
2827
+ var stepMonths = this._get(inst, 'stepMonths');
2828
+ var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
2829
+ var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
2830
+ new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
2831
+ var minDate = this._getMinMaxDate(inst, 'min');
2832
+ var maxDate = this._getMinMaxDate(inst, 'max');
2833
+ var drawMonth = inst.drawMonth - showCurrentAtPos;
2834
+ var drawYear = inst.drawYear;
2835
+ if (drawMonth < 0) {
2836
+ drawMonth += 12;
2837
+ drawYear--;
2838
+ }
2839
+ if (maxDate) {
2840
+ var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
2841
+ maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
2842
+ maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
2843
+ while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
2844
+ drawMonth--;
2845
+ if (drawMonth < 0) {
2846
+ drawMonth = 11;
2847
+ drawYear--;
2848
+ }
2849
+ }
2850
+ }
2851
+ inst.drawMonth = drawMonth;
2852
+ inst.drawYear = drawYear;
2853
+ var prevText = this._get(inst, 'prevText');
2854
+ prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
2855
+ this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
2856
+ this._getFormatConfig(inst)));
2857
+ var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
2858
+ '<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
2859
+ '.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
2860
+ ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
2861
+ (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
2862
+ var nextText = this._get(inst, 'nextText');
2863
+ nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
2864
+ this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
2865
+ this._getFormatConfig(inst)));
2866
+ var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
2867
+ '<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
2868
+ '.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
2869
+ ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
2870
+ (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
2871
+ var currentText = this._get(inst, 'currentText');
2872
+ var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
2873
+ currentText = (!navigationAsDateFormat ? currentText :
2874
+ this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
2875
+ var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
2876
+ '.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
2877
+ var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
2878
+ (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
2879
+ '.datepicker._gotoToday(\'#' + inst.id + '\');"' +
2880
+ '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
2881
+ var firstDay = parseInt(this._get(inst, 'firstDay'),10);
2882
+ firstDay = (isNaN(firstDay) ? 0 : firstDay);
2883
+ var showWeek = this._get(inst, 'showWeek');
2884
+ var dayNames = this._get(inst, 'dayNames');
2885
+ var dayNamesShort = this._get(inst, 'dayNamesShort');
2886
+ var dayNamesMin = this._get(inst, 'dayNamesMin');
2887
+ var monthNames = this._get(inst, 'monthNames');
2888
+ var monthNamesShort = this._get(inst, 'monthNamesShort');
2889
+ var beforeShowDay = this._get(inst, 'beforeShowDay');
2890
+ var showOtherMonths = this._get(inst, 'showOtherMonths');
2891
+ var selectOtherMonths = this._get(inst, 'selectOtherMonths');
2892
+ var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
2893
+ var defaultDate = this._getDefaultDate(inst);
2894
+ var html = '';
2895
+ for (var row = 0; row < numMonths[0]; row++) {
2896
+ var group = '';
2897
+ for (var col = 0; col < numMonths[1]; col++) {
2898
+ var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
2899
+ var cornerClass = ' ui-corner-all';
2900
+ var calender = '';
2901
+ if (isMultiMonth) {
2902
+ calender += '<div class="ui-datepicker-group';
2903
+ if (numMonths[1] > 1)
2904
+ switch (col) {
2905
+ case 0: calender += ' ui-datepicker-group-first';
2906
+ cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
2907
+ case numMonths[1]-1: calender += ' ui-datepicker-group-last';
2908
+ cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
2909
+ default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
2910
+ }
2911
+ calender += '">';
2912
+ }
2913
+ calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
2914
+ (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
2915
+ (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
2916
+ this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
2917
+ row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
2918
+ '</div><table class="ui-datepicker-calendar"><thead>' +
2919
+ '<tr>';
2920
+ var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
2921
+ for (var dow = 0; dow < 7; dow++) { // days of the week
2922
+ var day = (dow + firstDay) % 7;
2923
+ thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
2924
+ '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
2925
+ }
2926
+ calender += thead + '</tr></thead><tbody>';
2927
+ var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
2928
+ if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
2929
+ inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
2930
+ var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
2931
+ var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
2932
+ var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
2933
+ for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
2934
+ calender += '<tr>';
2935
+ var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
2936
+ this._get(inst, 'calculateWeek')(printDate) + '</td>');
2937
+ for (var dow = 0; dow < 7; dow++) { // create date picker days
2938
+ var daySettings = (beforeShowDay ?
2939
+ beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
2940
+ var otherMonth = (printDate.getMonth() != drawMonth);
2941
+ var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
2942
+ (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
2943
+ tbody += '<td class="' +
2944
+ ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
2945
+ (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
2946
+ ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
2947
+ (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
2948
+ // or defaultDate is current printedDate and defaultDate is selectedDate
2949
+ ' ' + this._dayOverClass : '') + // highlight selected day
2950
+ (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') + // highlight unselectable days
2951
+ (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
2952
+ (printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
2953
+ (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
2954
+ ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
2955
+ (unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
2956
+ inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
2957
+ (otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
2958
+ (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
2959
+ (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
2960
+ (printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
2961
+ (otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
2962
+ '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
2963
+ printDate.setDate(printDate.getDate() + 1);
2964
+ printDate = this._daylightSavingAdjust(printDate);
2965
+ }
2966
+ calender += tbody + '</tr>';
2967
+ }
2968
+ drawMonth++;
2969
+ if (drawMonth > 11) {
2970
+ drawMonth = 0;
2971
+ drawYear++;
2972
+ }
2973
+ calender += '</tbody></table>' + (isMultiMonth ? '</div>' +
2974
+ ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
2975
+ group += calender;
2976
+ }
2977
+ html += group;
2978
+ }
2979
+ html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
2980
+ '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
2981
+ inst._keyEvent = false;
2982
+ return html;
2983
+ },
2984
+
2985
+ /* Generate the month and year header. */
2986
+ _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
2987
+ secondary, monthNames, monthNamesShort) {
2988
+ var changeMonth = this._get(inst, 'changeMonth');
2989
+ var changeYear = this._get(inst, 'changeYear');
2990
+ var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
2991
+ var html = '<div class="ui-datepicker-title">';
2992
+ var monthHtml = '';
2993
+ // month selection
2994
+ if (secondary || !changeMonth)
2995
+ monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
2996
+ else {
2997
+ var inMinYear = (minDate && minDate.getFullYear() == drawYear);
2998
+ var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
2999
+ monthHtml += '<select class="ui-datepicker-month" ' +
3000
+ 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
3001
+ 'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
3002
+ '>';
3003
+ for (var month = 0; month < 12; month++) {
3004
+ if ((!inMinYear || month >= minDate.getMonth()) &&
3005
+ (!inMaxYear || month <= maxDate.getMonth()))
3006
+ monthHtml += '<option value="' + month + '"' +
3007
+ (month == drawMonth ? ' selected="selected"' : '') +
3008
+ '>' + monthNamesShort[month] + '</option>';
3009
+ }
3010
+ monthHtml += '</select>';
3011
+ }
3012
+ if (!showMonthAfterYear)
3013
+ html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
3014
+ // year selection
3015
+ if ( !inst.yearshtml ) {
3016
+ inst.yearshtml = '';
3017
+ if (secondary || !changeYear)
3018
+ html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
3019
+ else {
3020
+ // determine range of years to display
3021
+ var years = this._get(inst, 'yearRange').split(':');
3022
+ var thisYear = new Date().getFullYear();
3023
+ var determineYear = function(value) {
3024
+ var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
3025
+ (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
3026
+ parseInt(value, 10)));
3027
+ return (isNaN(year) ? thisYear : year);
3028
+ };
3029
+ var year = determineYear(years[0]);
3030
+ var endYear = Math.max(year, determineYear(years[1] || ''));
3031
+ year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
3032
+ endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
3033
+ inst.yearshtml += '<select class="ui-datepicker-year" ' +
3034
+ 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
3035
+ 'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
3036
+ '>';
3037
+ for (; year <= endYear; year++) {
3038
+ inst.yearshtml += '<option value="' + year + '"' +
3039
+ (year == drawYear ? ' selected="selected"' : '') +
3040
+ '>' + year + '</option>';
3041
+ }
3042
+ inst.yearshtml += '</select>';
3043
+
3044
+ html += inst.yearshtml;
3045
+ inst.yearshtml = null;
3046
+ }
3047
+ }
3048
+ html += this._get(inst, 'yearSuffix');
3049
+ if (showMonthAfterYear)
3050
+ html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
3051
+ html += '</div>'; // Close datepicker_header
3052
+ return html;
3053
+ },
3054
+
3055
+ /* Adjust one of the date sub-fields. */
3056
+ _adjustInstDate: function(inst, offset, period) {
3057
+ var year = inst.drawYear + (period == 'Y' ? offset : 0);
3058
+ var month = inst.drawMonth + (period == 'M' ? offset : 0);
3059
+ var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
3060
+ (period == 'D' ? offset : 0);
3061
+ var date = this._restrictMinMax(inst,
3062
+ this._daylightSavingAdjust(new Date(year, month, day)));
3063
+ inst.selectedDay = date.getDate();
3064
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
3065
+ inst.drawYear = inst.selectedYear = date.getFullYear();
3066
+ if (period == 'M' || period == 'Y')
3067
+ this._notifyChange(inst);
3068
+ },
3069
+
3070
+ /* Ensure a date is within any min/max bounds. */
3071
+ _restrictMinMax: function(inst, date) {
3072
+ var minDate = this._getMinMaxDate(inst, 'min');
3073
+ var maxDate = this._getMinMaxDate(inst, 'max');
3074
+ var newDate = (minDate && date < minDate ? minDate : date);
3075
+ newDate = (maxDate && newDate > maxDate ? maxDate : newDate);
3076
+ return newDate;
3077
+ },
3078
+
3079
+ /* Notify change of month/year. */
3080
+ _notifyChange: function(inst) {
3081
+ var onChange = this._get(inst, 'onChangeMonthYear');
3082
+ if (onChange)
3083
+ onChange.apply((inst.input ? inst.input[0] : null),
3084
+ [inst.selectedYear, inst.selectedMonth + 1, inst]);
3085
+ },
3086
+
3087
+ /* Determine the number of months to show. */
3088
+ _getNumberOfMonths: function(inst) {
3089
+ var numMonths = this._get(inst, 'numberOfMonths');
3090
+ return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
3091
+ },
3092
+
3093
+ /* Determine the current maximum date - ensure no time components are set. */
3094
+ _getMinMaxDate: function(inst, minMax) {
3095
+ return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
3096
+ },
3097
+
3098
+ /* Find the number of days in a given month. */
3099
+ _getDaysInMonth: function(year, month) {
3100
+ return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
3101
+ },
3102
+
3103
+ /* Find the day of the week of the first of a month. */
3104
+ _getFirstDayOfMonth: function(year, month) {
3105
+ return new Date(year, month, 1).getDay();
3106
+ },
3107
+
3108
+ /* Determines if we should allow a "next/prev" month display change. */
3109
+ _canAdjustMonth: function(inst, offset, curYear, curMonth) {
3110
+ var numMonths = this._getNumberOfMonths(inst);
3111
+ var date = this._daylightSavingAdjust(new Date(curYear,
3112
+ curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
3113
+ if (offset < 0)
3114
+ date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
3115
+ return this._isInRange(inst, date);
3116
+ },
3117
+
3118
+ /* Is the given date in the accepted range? */
3119
+ _isInRange: function(inst, date) {
3120
+ var minDate = this._getMinMaxDate(inst, 'min');
3121
+ var maxDate = this._getMinMaxDate(inst, 'max');
3122
+ return ((!minDate || date.getTime() >= minDate.getTime()) &&
3123
+ (!maxDate || date.getTime() <= maxDate.getTime()));
3124
+ },
3125
+
3126
+ /* Provide the configuration settings for formatting/parsing. */
3127
+ _getFormatConfig: function(inst) {
3128
+ var shortYearCutoff = this._get(inst, 'shortYearCutoff');
3129
+ shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
3130
+ new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
3131
+ return {shortYearCutoff: shortYearCutoff,
3132
+ dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
3133
+ monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
3134
+ },
3135
+
3136
+ /* Format the given date for display. */
3137
+ _formatDate: function(inst, day, month, year) {
3138
+ if (!day) {
3139
+ inst.currentDay = inst.selectedDay;
3140
+ inst.currentMonth = inst.selectedMonth;
3141
+ inst.currentYear = inst.selectedYear;
3142
+ }
3143
+ var date = (day ? (typeof day == 'object' ? day :
3144
+ this._daylightSavingAdjust(new Date(year, month, day))) :
3145
+ this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
3146
+ return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
3147
+ }
3148
+ });
3149
+
3150
+ /*
3151
+ * Bind hover events for datepicker elements.
3152
+ * Done via delegate so the binding only occurs once in the lifetime of the parent div.
3153
+ * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
3154
+ */
3155
+ function bindHover(dpDiv) {
3156
+ var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a';
3157
+ return dpDiv.delegate(selector, 'mouseout', function() {
3158
+ $(this).removeClass('ui-state-hover');
3159
+ if (this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
3160
+ if (this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
3161
+ })
3162
+ .delegate(selector, 'mouseover', function(){
3163
+ if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) {
3164
+ $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
3165
+ $(this).addClass('ui-state-hover');
3166
+ if (this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
3167
+ if (this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
3168
+ }
3169
+ });
3170
+ }
3171
+
3172
+ /* jQuery extend now ignores nulls! */
3173
+ function extendRemove(target, props) {
3174
+ $.extend(target, props);
3175
+ for (var name in props)
3176
+ if (props[name] == null || props[name] == undefined)
3177
+ target[name] = props[name];
3178
+ return target;
3179
+ };
3180
+
3181
+ /* Determine whether an object is an array. */
3182
+ function isArray(a) {
3183
+ return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
3184
+ (a.constructor && a.constructor.toString().match(/\Array\(\)/))));
3185
+ };
3186
+
3187
+ /* Invoke the datepicker functionality.
3188
+ @param options string - a command, optionally followed by additional parameters or
3189
+ Object - settings for attaching new datepicker functionality
3190
+ @return jQuery object */
3191
+ $.fn.datepicker = function(options){
3192
+
3193
+ /* Verify an empty collection wasn't passed - Fixes #6976 */
3194
+ if ( !this.length ) {
3195
+ return this;
3196
+ }
3197
+
3198
+ /* Initialise the date picker. */
3199
+ if (!$.datepicker.initialized) {
3200
+ $(document).mousedown($.datepicker._checkExternalClick).
3201
+ find('body').append($.datepicker.dpDiv);
3202
+ $.datepicker.initialized = true;
3203
+ }
3204
+
3205
+ var otherArgs = Array.prototype.slice.call(arguments, 1);
3206
+ if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
3207
+ return $.datepicker['_' + options + 'Datepicker'].
3208
+ apply($.datepicker, [this[0]].concat(otherArgs));
3209
+ if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
3210
+ return $.datepicker['_' + options + 'Datepicker'].
3211
+ apply($.datepicker, [this[0]].concat(otherArgs));
3212
+ return this.each(function() {
3213
+ typeof options == 'string' ?
3214
+ $.datepicker['_' + options + 'Datepicker'].
3215
+ apply($.datepicker, [this].concat(otherArgs)) :
3216
+ $.datepicker._attachDatepicker(this, options);
3217
+ });
3218
+ };
3219
+
3220
+ $.datepicker = new Datepicker(); // singleton instance
3221
+ $.datepicker.initialized = false;
3222
+ $.datepicker.uuid = new Date().getTime();
3223
+ $.datepicker.version = "1.8.13";
3224
+
3225
+ // Workaround for #4055
3226
+ // Add another global to avoid noConflict issues with inline event handlers
3227
+ window['DP_jQuery_' + dpuuid] = $;
3228
+
3229
+ })(jQuery);