iqvoc 3.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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);