effective_bootstrap 0.7.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (525) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +644 -0
  4. data/app/assets/images/icons/activity.svg +13 -0
  5. data/app/assets/images/icons/airplay.svg +14 -0
  6. data/app/assets/images/icons/alert-circle.svg +15 -0
  7. data/app/assets/images/icons/alert-octagon.svg +15 -0
  8. data/app/assets/images/icons/alert-triangle.svg +15 -0
  9. data/app/assets/images/icons/align-center.svg +16 -0
  10. data/app/assets/images/icons/align-justify.svg +16 -0
  11. data/app/assets/images/icons/align-left.svg +16 -0
  12. data/app/assets/images/icons/align-right.svg +16 -0
  13. data/app/assets/images/icons/anchor.svg +15 -0
  14. data/app/assets/images/icons/aperture.svg +19 -0
  15. data/app/assets/images/icons/arrow-down-circle.svg +15 -0
  16. data/app/assets/images/icons/arrow-down-left.svg +14 -0
  17. data/app/assets/images/icons/arrow-down-right.svg +14 -0
  18. data/app/assets/images/icons/arrow-down.svg +14 -0
  19. data/app/assets/images/icons/arrow-left-circle.svg +15 -0
  20. data/app/assets/images/icons/arrow-left.svg +14 -0
  21. data/app/assets/images/icons/arrow-right-circle.svg +15 -0
  22. data/app/assets/images/icons/arrow-right.svg +14 -0
  23. data/app/assets/images/icons/arrow-up-circle.svg +15 -0
  24. data/app/assets/images/icons/arrow-up-left.svg +14 -0
  25. data/app/assets/images/icons/arrow-up-right.svg +14 -0
  26. data/app/assets/images/icons/arrow-up.svg +14 -0
  27. data/app/assets/images/icons/at-sign.svg +14 -0
  28. data/app/assets/images/icons/award.svg +14 -0
  29. data/app/assets/images/icons/bar-chart-2.svg +15 -0
  30. data/app/assets/images/icons/bar-chart.svg +15 -0
  31. data/app/assets/images/icons/battery-charging.svg +15 -0
  32. data/app/assets/images/icons/battery.svg +14 -0
  33. data/app/assets/images/icons/bell-off.svg +14 -0
  34. data/app/assets/images/icons/bell.svg +13 -0
  35. data/app/assets/images/icons/bluetooth.svg +13 -0
  36. data/app/assets/images/icons/bold.svg +14 -0
  37. data/app/assets/images/icons/book-open.svg +14 -0
  38. data/app/assets/images/icons/book.svg +14 -0
  39. data/app/assets/images/icons/bookmark.svg +13 -0
  40. data/app/assets/images/icons/box.svg +15 -0
  41. data/app/assets/images/icons/briefcase.svg +14 -0
  42. data/app/assets/images/icons/calendar.svg +16 -0
  43. data/app/assets/images/icons/camera-off.svg +14 -0
  44. data/app/assets/images/icons/camera.svg +14 -0
  45. data/app/assets/images/icons/cast.svg +14 -0
  46. data/app/assets/images/icons/check-circle.svg +14 -0
  47. data/app/assets/images/icons/check-square.svg +14 -0
  48. data/app/assets/images/icons/check.svg +13 -0
  49. data/app/assets/images/icons/chevron-down.svg +13 -0
  50. data/app/assets/images/icons/chevron-left.svg +13 -0
  51. data/app/assets/images/icons/chevron-right.svg +13 -0
  52. data/app/assets/images/icons/chevron-up.svg +13 -0
  53. data/app/assets/images/icons/chevrons-down.svg +14 -0
  54. data/app/assets/images/icons/chevrons-left.svg +14 -0
  55. data/app/assets/images/icons/chevrons-right.svg +14 -0
  56. data/app/assets/images/icons/chevrons-up.svg +14 -0
  57. data/app/assets/images/icons/chrome.svg +17 -0
  58. data/app/assets/images/icons/circle.svg +13 -0
  59. data/app/assets/images/icons/clipboard.svg +14 -0
  60. data/app/assets/images/icons/clock.svg +14 -0
  61. data/app/assets/images/icons/cloud-drizzle.svg +19 -0
  62. data/app/assets/images/icons/cloud-lightning.svg +14 -0
  63. data/app/assets/images/icons/cloud-off.svg +14 -0
  64. data/app/assets/images/icons/cloud-rain.svg +16 -0
  65. data/app/assets/images/icons/cloud-snow.svg +19 -0
  66. data/app/assets/images/icons/cloud.svg +13 -0
  67. data/app/assets/images/icons/code.svg +14 -0
  68. data/app/assets/images/icons/codepen.svg +17 -0
  69. data/app/assets/images/icons/command.svg +13 -0
  70. data/app/assets/images/icons/compass.svg +14 -0
  71. data/app/assets/images/icons/copy.svg +14 -0
  72. data/app/assets/images/icons/corner-down-left.svg +14 -0
  73. data/app/assets/images/icons/corner-down-right.svg +14 -0
  74. data/app/assets/images/icons/corner-left-down.svg +14 -0
  75. data/app/assets/images/icons/corner-left-up.svg +14 -0
  76. data/app/assets/images/icons/corner-right-down.svg +14 -0
  77. data/app/assets/images/icons/corner-right-up.svg +14 -0
  78. data/app/assets/images/icons/corner-up-left.svg +14 -0
  79. data/app/assets/images/icons/corner-up-right.svg +14 -0
  80. data/app/assets/images/icons/cpu.svg +22 -0
  81. data/app/assets/images/icons/credit-card.svg +14 -0
  82. data/app/assets/images/icons/crop.svg +14 -0
  83. data/app/assets/images/icons/crosshair.svg +17 -0
  84. data/app/assets/images/icons/database.svg +15 -0
  85. data/app/assets/images/icons/delete.svg +15 -0
  86. data/app/assets/images/icons/disc.svg +14 -0
  87. data/app/assets/images/icons/dollar-sign.svg +14 -0
  88. data/app/assets/images/icons/download-cloud.svg +15 -0
  89. data/app/assets/images/icons/download.svg +15 -0
  90. data/app/assets/images/icons/droplet.svg +13 -0
  91. data/app/assets/images/icons/edit-2.svg +13 -0
  92. data/app/assets/images/icons/edit-3.svg +14 -0
  93. data/app/assets/images/icons/edit.svg +14 -0
  94. data/app/assets/images/icons/external-link.svg +15 -0
  95. data/app/assets/images/icons/eye-off.svg +14 -0
  96. data/app/assets/images/icons/eye.svg +14 -0
  97. data/app/assets/images/icons/facebook-white.svg +7 -0
  98. data/app/assets/images/icons/facebook.svg +13 -0
  99. data/app/assets/images/icons/fast-forward.svg +14 -0
  100. data/app/assets/images/icons/feather.svg +15 -0
  101. data/app/assets/images/icons/file-minus.svg +15 -0
  102. data/app/assets/images/icons/file-plus.svg +16 -0
  103. data/app/assets/images/icons/file-text.svg +17 -0
  104. data/app/assets/images/icons/file.svg +14 -0
  105. data/app/assets/images/icons/film.svg +20 -0
  106. data/app/assets/images/icons/filter.svg +13 -0
  107. data/app/assets/images/icons/flag.svg +14 -0
  108. data/app/assets/images/icons/folder-minus.svg +14 -0
  109. data/app/assets/images/icons/folder-plus.svg +15 -0
  110. data/app/assets/images/icons/folder.svg +13 -0
  111. data/app/assets/images/icons/git-branch.svg +16 -0
  112. data/app/assets/images/icons/git-commit.svg +15 -0
  113. data/app/assets/images/icons/git-merge.svg +15 -0
  114. data/app/assets/images/icons/git-pull-request.svg +16 -0
  115. data/app/assets/images/icons/github.svg +13 -0
  116. data/app/assets/images/icons/gitlab.svg +13 -0
  117. data/app/assets/images/icons/globe.svg +15 -0
  118. data/app/assets/images/icons/google.svg +2 -0
  119. data/app/assets/images/icons/grid.svg +16 -0
  120. data/app/assets/images/icons/hard-drive.svg +16 -0
  121. data/app/assets/images/icons/hash.svg +16 -0
  122. data/app/assets/images/icons/headphones.svg +14 -0
  123. data/app/assets/images/icons/heart.svg +13 -0
  124. data/app/assets/images/icons/help-circle.svg +15 -0
  125. data/app/assets/images/icons/home.svg +14 -0
  126. data/app/assets/images/icons/image.svg +15 -0
  127. data/app/assets/images/icons/inbox.svg +14 -0
  128. data/app/assets/images/icons/info.svg +15 -0
  129. data/app/assets/images/icons/instagram.svg +15 -0
  130. data/app/assets/images/icons/italic.svg +15 -0
  131. data/app/assets/images/icons/layers.svg +15 -0
  132. data/app/assets/images/icons/layout.svg +15 -0
  133. data/app/assets/images/icons/life-buoy.svg +19 -0
  134. data/app/assets/images/icons/link-2.svg +14 -0
  135. data/app/assets/images/icons/link.svg +14 -0
  136. data/app/assets/images/icons/linkedin.svg +15 -0
  137. data/app/assets/images/icons/list.svg +18 -0
  138. data/app/assets/images/icons/loader.svg +20 -0
  139. data/app/assets/images/icons/lock.svg +14 -0
  140. data/app/assets/images/icons/log-in.svg +15 -0
  141. data/app/assets/images/icons/log-out.svg +15 -0
  142. data/app/assets/images/icons/mail.svg +14 -0
  143. data/app/assets/images/icons/map-pin.svg +14 -0
  144. data/app/assets/images/icons/map.svg +15 -0
  145. data/app/assets/images/icons/maximize-2.svg +16 -0
  146. data/app/assets/images/icons/maximize.svg +13 -0
  147. data/app/assets/images/icons/menu.svg +15 -0
  148. data/app/assets/images/icons/message-circle.svg +13 -0
  149. data/app/assets/images/icons/message-square.svg +13 -0
  150. data/app/assets/images/icons/mic-off.svg +17 -0
  151. data/app/assets/images/icons/mic.svg +16 -0
  152. data/app/assets/images/icons/minimize-2.svg +16 -0
  153. data/app/assets/images/icons/minimize.svg +13 -0
  154. data/app/assets/images/icons/minus-circle.svg +14 -0
  155. data/app/assets/images/icons/minus-square.svg +14 -0
  156. data/app/assets/images/icons/minus.svg +13 -0
  157. data/app/assets/images/icons/monitor.svg +15 -0
  158. data/app/assets/images/icons/moon.svg +13 -0
  159. data/app/assets/images/icons/more-horizontal.svg +15 -0
  160. data/app/assets/images/icons/more-vertical.svg +15 -0
  161. data/app/assets/images/icons/move.svg +18 -0
  162. data/app/assets/images/icons/music.svg +14 -0
  163. data/app/assets/images/icons/navigation-2.svg +13 -0
  164. data/app/assets/images/icons/navigation.svg +13 -0
  165. data/app/assets/images/icons/octagon.svg +13 -0
  166. data/app/assets/images/icons/package.svg +16 -0
  167. data/app/assets/images/icons/paperclip.svg +13 -0
  168. data/app/assets/images/icons/pause-circle.svg +15 -0
  169. data/app/assets/images/icons/pause.svg +14 -0
  170. data/app/assets/images/icons/percent.svg +15 -0
  171. data/app/assets/images/icons/phone-call.svg +13 -0
  172. data/app/assets/images/icons/phone-forwarded.svg +15 -0
  173. data/app/assets/images/icons/phone-incoming.svg +15 -0
  174. data/app/assets/images/icons/phone-missed.svg +15 -0
  175. data/app/assets/images/icons/phone-off.svg +14 -0
  176. data/app/assets/images/icons/phone-outgoing.svg +15 -0
  177. data/app/assets/images/icons/phone.svg +13 -0
  178. data/app/assets/images/icons/pie-chart.svg +14 -0
  179. data/app/assets/images/icons/play-circle.svg +14 -0
  180. data/app/assets/images/icons/play.svg +13 -0
  181. data/app/assets/images/icons/plus-circle.svg +15 -0
  182. data/app/assets/images/icons/plus-square.svg +15 -0
  183. data/app/assets/images/icons/plus.svg +14 -0
  184. data/app/assets/images/icons/pocket.svg +14 -0
  185. data/app/assets/images/icons/power.svg +14 -0
  186. data/app/assets/images/icons/printer.svg +15 -0
  187. data/app/assets/images/icons/radio.svg +14 -0
  188. data/app/assets/images/icons/refresh-ccw.svg +15 -0
  189. data/app/assets/images/icons/refresh-cw.svg +15 -0
  190. data/app/assets/images/icons/repeat.svg +16 -0
  191. data/app/assets/images/icons/rewind.svg +14 -0
  192. data/app/assets/images/icons/rotate-ccw.svg +14 -0
  193. data/app/assets/images/icons/rotate-cw.svg +14 -0
  194. data/app/assets/images/icons/rss.svg +15 -0
  195. data/app/assets/images/icons/save.svg +15 -0
  196. data/app/assets/images/icons/scissors.svg +17 -0
  197. data/app/assets/images/icons/search.svg +14 -0
  198. data/app/assets/images/icons/send.svg +14 -0
  199. data/app/assets/images/icons/server.svg +16 -0
  200. data/app/assets/images/icons/settings.svg +14 -0
  201. data/app/assets/images/icons/share-2.svg +17 -0
  202. data/app/assets/images/icons/share.svg +15 -0
  203. data/app/assets/images/icons/shield-off.svg +15 -0
  204. data/app/assets/images/icons/shield.svg +13 -0
  205. data/app/assets/images/icons/shopping-bag.svg +15 -0
  206. data/app/assets/images/icons/shopping-cart.svg +15 -0
  207. data/app/assets/images/icons/shuffle.svg +17 -0
  208. data/app/assets/images/icons/sidebar.svg +14 -0
  209. data/app/assets/images/icons/skip-back.svg +14 -0
  210. data/app/assets/images/icons/skip-forward.svg +14 -0
  211. data/app/assets/images/icons/slack.svg +17 -0
  212. data/app/assets/images/icons/slash.svg +14 -0
  213. data/app/assets/images/icons/sliders.svg +21 -0
  214. data/app/assets/images/icons/smartphone.svg +14 -0
  215. data/app/assets/images/icons/speaker.svg +15 -0
  216. data/app/assets/images/icons/spinner.svg +1 -0
  217. data/app/assets/images/icons/square.svg +13 -0
  218. data/app/assets/images/icons/star.svg +13 -0
  219. data/app/assets/images/icons/stop-circle.svg +14 -0
  220. data/app/assets/images/icons/sun.svg +21 -0
  221. data/app/assets/images/icons/sunrise.svg +20 -0
  222. data/app/assets/images/icons/sunset.svg +20 -0
  223. data/app/assets/images/icons/tablet.svg +22 -0
  224. data/app/assets/images/icons/tag.svg +14 -0
  225. data/app/assets/images/icons/target.svg +15 -0
  226. data/app/assets/images/icons/terminal.svg +14 -0
  227. data/app/assets/images/icons/thermometer.svg +13 -0
  228. data/app/assets/images/icons/thumbs-down.svg +13 -0
  229. data/app/assets/images/icons/thumbs-up.svg +13 -0
  230. data/app/assets/images/icons/toggle-left.svg +14 -0
  231. data/app/assets/images/icons/toggle-right.svg +14 -0
  232. data/app/assets/images/icons/trash-2.svg +16 -0
  233. data/app/assets/images/icons/trash.svg +14 -0
  234. data/app/assets/images/icons/trending-down.svg +14 -0
  235. data/app/assets/images/icons/trending-up.svg +14 -0
  236. data/app/assets/images/icons/triangle.svg +13 -0
  237. data/app/assets/images/icons/truck.svg +16 -0
  238. data/app/assets/images/icons/tv.svg +14 -0
  239. data/app/assets/images/icons/twitter.svg +13 -0
  240. data/app/assets/images/icons/type.svg +15 -0
  241. data/app/assets/images/icons/umbrella.svg +13 -0
  242. data/app/assets/images/icons/underline.svg +14 -0
  243. data/app/assets/images/icons/unlock.svg +14 -0
  244. data/app/assets/images/icons/upload-cloud.svg +16 -0
  245. data/app/assets/images/icons/upload.svg +15 -0
  246. data/app/assets/images/icons/user-check.svg +15 -0
  247. data/app/assets/images/icons/user-minus.svg +15 -0
  248. data/app/assets/images/icons/user-plus.svg +16 -0
  249. data/app/assets/images/icons/user-x.svg +16 -0
  250. data/app/assets/images/icons/user.svg +14 -0
  251. data/app/assets/images/icons/users.svg +16 -0
  252. data/app/assets/images/icons/video-off.svg +14 -0
  253. data/app/assets/images/icons/video.svg +14 -0
  254. data/app/assets/images/icons/voicemail.svg +15 -0
  255. data/app/assets/images/icons/volume-1.svg +14 -0
  256. data/app/assets/images/icons/volume-2.svg +14 -0
  257. data/app/assets/images/icons/volume-x.svg +15 -0
  258. data/app/assets/images/icons/volume.svg +13 -0
  259. data/app/assets/images/icons/watch.svg +15 -0
  260. data/app/assets/images/icons/wifi-off.svg +19 -0
  261. data/app/assets/images/icons/wifi.svg +16 -0
  262. data/app/assets/images/icons/wind.svg +13 -0
  263. data/app/assets/images/icons/x-circle.svg +15 -0
  264. data/app/assets/images/icons/x-square.svg +15 -0
  265. data/app/assets/images/icons/x.svg +14 -0
  266. data/app/assets/images/icons/zap-off.svg +16 -0
  267. data/app/assets/images/icons/zap.svg +13 -0
  268. data/app/assets/images/icons/zoom-in.svg +16 -0
  269. data/app/assets/images/icons/zoom-out.svg +15 -0
  270. data/app/assets/javascripts/effective_bootstrap.js +25 -0
  271. data/app/assets/javascripts/effective_bootstrap/base.js.coffee +22 -0
  272. data/app/assets/javascripts/effective_bootstrap/confirm.js.coffee.erb +23 -0
  273. data/app/assets/javascripts/effective_bootstrap/form.js.coffee +182 -0
  274. data/app/assets/javascripts/effective_bootstrap/logic.js.coffee +64 -0
  275. data/app/assets/javascripts/effective_bootstrap/other.js.coffee +4 -0
  276. data/app/assets/javascripts/effective_bootstrap/tabs.js +14 -0
  277. data/app/assets/javascripts/effective_checks/initialize.js.coffee +7 -0
  278. data/app/assets/javascripts/effective_checks/input.js +1 -0
  279. data/app/assets/javascripts/effective_ck_editor/initialize.js.coffee +72 -0
  280. data/app/assets/javascripts/effective_ck_editor/input.js +1 -0
  281. data/app/assets/javascripts/effective_clear/initialize.js.coffee +3 -0
  282. data/app/assets/javascripts/effective_clear/input.js +1 -0
  283. data/app/assets/javascripts/effective_date/initialize.js.coffee +7 -0
  284. data/app/assets/javascripts/effective_date/input.js +5 -0
  285. data/app/assets/javascripts/effective_datetime/bootstrap-datetimepicker.js +2636 -0
  286. data/app/assets/javascripts/effective_datetime/initialize.js.coffee +7 -0
  287. data/app/assets/javascripts/effective_datetime/input.js +5 -0
  288. data/app/assets/javascripts/effective_datetime/overrides.js.coffee +45 -0
  289. data/app/assets/javascripts/effective_datetime/turbolinks.js.coffee +5 -0
  290. data/app/assets/javascripts/effective_editor/image-drop-and-paste.js +3 -0
  291. data/app/assets/javascripts/effective_editor/image-resize.js +2 -0
  292. data/app/assets/javascripts/effective_editor/initialize.js.coffee +138 -0
  293. data/app/assets/javascripts/effective_editor/input.js +4 -0
  294. data/app/assets/javascripts/effective_editor/quill.js +11496 -0
  295. data/app/assets/javascripts/effective_file/initialize.js.coffee +19 -0
  296. data/app/assets/javascripts/effective_file/input.js +1 -0
  297. data/app/assets/javascripts/effective_integer/initialize.js.coffee +6 -0
  298. data/app/assets/javascripts/effective_integer/input.js +1 -0
  299. data/app/assets/javascripts/effective_number_text/initialize.js.coffee +6 -0
  300. data/app/assets/javascripts/effective_number_text/input.js +1 -0
  301. data/app/assets/javascripts/effective_percent/initialize.js.coffee +39 -0
  302. data/app/assets/javascripts/effective_percent/input.js +1 -0
  303. data/app/assets/javascripts/effective_phone/initialize.js.coffee +4 -0
  304. data/app/assets/javascripts/effective_phone/input.js +2 -0
  305. data/app/assets/javascripts/effective_phone/jquery.maskedInput.js +182 -0
  306. data/app/assets/javascripts/effective_price/initialize.js.coffee +43 -0
  307. data/app/assets/javascripts/effective_price/input.js +1 -0
  308. data/app/assets/javascripts/effective_radio/initialize.js.coffee +36 -0
  309. data/app/assets/javascripts/effective_radio/input.js +1 -0
  310. data/app/assets/javascripts/effective_select/initialize.js.coffee +56 -0
  311. data/app/assets/javascripts/effective_select/input.js +3 -0
  312. data/app/assets/javascripts/effective_select/overrides.js.coffee +60 -0
  313. data/app/assets/javascripts/effective_select/select2.js +5747 -0
  314. data/app/assets/javascripts/effective_select_or_text/initialize.js +30 -0
  315. data/app/assets/javascripts/effective_select_or_text/input.js +1 -0
  316. data/app/assets/javascripts/effective_time/initialize.js.coffee +7 -0
  317. data/app/assets/javascripts/effective_time/input.js +5 -0
  318. data/app/assets/javascripts/effective_time_zone_select/initialize.js.coffee +13 -0
  319. data/app/assets/javascripts/effective_time_zone_select/input.js +1 -0
  320. data/app/assets/javascripts/moment/locale/af.js +72 -0
  321. data/app/assets/javascripts/moment/locale/ar-dz.js +58 -0
  322. data/app/assets/javascripts/moment/locale/ar-kw.js +58 -0
  323. data/app/assets/javascripts/moment/locale/ar-ly.js +121 -0
  324. data/app/assets/javascripts/moment/locale/ar-ma.js +58 -0
  325. data/app/assets/javascripts/moment/locale/ar-sa.js +103 -0
  326. data/app/assets/javascripts/moment/locale/ar-tn.js +58 -0
  327. data/app/assets/javascripts/moment/locale/ar.js +134 -0
  328. data/app/assets/javascripts/moment/locale/az.js +104 -0
  329. data/app/assets/javascripts/moment/locale/be.js +131 -0
  330. data/app/assets/javascripts/moment/locale/bg.js +89 -0
  331. data/app/assets/javascripts/moment/locale/bm.js +57 -0
  332. data/app/assets/javascripts/moment/locale/bn.js +118 -0
  333. data/app/assets/javascripts/moment/locale/bo.js +118 -0
  334. data/app/assets/javascripts/moment/locale/br.js +107 -0
  335. data/app/assets/javascripts/moment/locale/bs.js +150 -0
  336. data/app/assets/javascripts/moment/locale/ca.js +87 -0
  337. data/app/assets/javascripts/moment/locale/cs.js +171 -0
  338. data/app/assets/javascripts/moment/locale/cv.js +62 -0
  339. data/app/assets/javascripts/moment/locale/cy.js +79 -0
  340. data/app/assets/javascripts/moment/locale/da.js +59 -0
  341. data/app/assets/javascripts/moment/locale/de-at.js +75 -0
  342. data/app/assets/javascripts/moment/locale/de-ch.js +75 -0
  343. data/app/assets/javascripts/moment/locale/de.js +75 -0
  344. data/app/assets/javascripts/moment/locale/dv.js +98 -0
  345. data/app/assets/javascripts/moment/locale/el.js +99 -0
  346. data/app/assets/javascripts/moment/locale/en-SG.js +66 -0
  347. data/app/assets/javascripts/moment/locale/en-au.js +66 -0
  348. data/app/assets/javascripts/moment/locale/en-ca.js +62 -0
  349. data/app/assets/javascripts/moment/locale/en-gb.js +66 -0
  350. data/app/assets/javascripts/moment/locale/en-ie.js +66 -0
  351. data/app/assets/javascripts/moment/locale/en-il.js +61 -0
  352. data/app/assets/javascripts/moment/locale/en-nz.js +66 -0
  353. data/app/assets/javascripts/moment/locale/eo.js +70 -0
  354. data/app/assets/javascripts/moment/locale/es-do.js +91 -0
  355. data/app/assets/javascripts/moment/locale/es-us.js +91 -0
  356. data/app/assets/javascripts/moment/locale/es.js +91 -0
  357. data/app/assets/javascripts/moment/locale/et.js +79 -0
  358. data/app/assets/javascripts/moment/locale/eu.js +65 -0
  359. data/app/assets/javascripts/moment/locale/fa.js +105 -0
  360. data/app/assets/javascripts/moment/locale/fi.js +108 -0
  361. data/app/assets/javascripts/moment/locale/fo.js +59 -0
  362. data/app/assets/javascripts/moment/locale/fr-ca.js +73 -0
  363. data/app/assets/javascripts/moment/locale/fr-ch.js +77 -0
  364. data/app/assets/javascripts/moment/locale/fr.js +82 -0
  365. data/app/assets/javascripts/moment/locale/fy.js +74 -0
  366. data/app/assets/javascripts/moment/locale/ga.js +76 -0
  367. data/app/assets/javascripts/moment/locale/gd.js +75 -0
  368. data/app/assets/javascripts/moment/locale/gl.js +76 -0
  369. data/app/assets/javascripts/moment/locale/gom-latn.js +122 -0
  370. data/app/assets/javascripts/moment/locale/gu.js +123 -0
  371. data/app/assets/javascripts/moment/locale/he.js +96 -0
  372. data/app/assets/javascripts/moment/locale/hi.js +123 -0
  373. data/app/assets/javascripts/moment/locale/hr.js +153 -0
  374. data/app/assets/javascripts/moment/locale/hu.js +109 -0
  375. data/app/assets/javascripts/moment/locale/hy-am.js +94 -0
  376. data/app/assets/javascripts/moment/locale/id.js +81 -0
  377. data/app/assets/javascripts/moment/locale/is.js +131 -0
  378. data/app/assets/javascripts/moment/locale/it-ch.js +68 -0
  379. data/app/assets/javascripts/moment/locale/it.js +68 -0
  380. data/app/assets/javascripts/moment/locale/ja.js +91 -0
  381. data/app/assets/javascripts/moment/locale/jv.js +81 -0
  382. data/app/assets/javascripts/moment/locale/ka.js +88 -0
  383. data/app/assets/javascripts/moment/locale/kk.js +86 -0
  384. data/app/assets/javascripts/moment/locale/km.js +109 -0
  385. data/app/assets/javascripts/moment/locale/kn.js +125 -0
  386. data/app/assets/javascripts/moment/locale/ko.js +80 -0
  387. data/app/assets/javascripts/moment/locale/ku.js +118 -0
  388. data/app/assets/javascripts/moment/locale/ky.js +86 -0
  389. data/app/assets/javascripts/moment/locale/lb.js +135 -0
  390. data/app/assets/javascripts/moment/locale/lo.js +69 -0
  391. data/app/assets/javascripts/moment/locale/lt.js +117 -0
  392. data/app/assets/javascripts/moment/locale/lv.js +96 -0
  393. data/app/assets/javascripts/moment/locale/me.js +111 -0
  394. data/app/assets/javascripts/moment/locale/mi.js +63 -0
  395. data/app/assets/javascripts/moment/locale/mk.js +89 -0
  396. data/app/assets/javascripts/moment/locale/ml.js +80 -0
  397. data/app/assets/javascripts/moment/locale/mn.js +103 -0
  398. data/app/assets/javascripts/moment/locale/mr.js +159 -0
  399. data/app/assets/javascripts/moment/locale/ms-my.js +81 -0
  400. data/app/assets/javascripts/moment/locale/ms.js +81 -0
  401. data/app/assets/javascripts/moment/locale/mt.js +59 -0
  402. data/app/assets/javascripts/moment/locale/my.js +92 -0
  403. data/app/assets/javascripts/moment/locale/nb.js +61 -0
  404. data/app/assets/javascripts/moment/locale/ne.js +122 -0
  405. data/app/assets/javascripts/moment/locale/nl-be.js +86 -0
  406. data/app/assets/javascripts/moment/locale/nl.js +86 -0
  407. data/app/assets/javascripts/moment/locale/nn.js +59 -0
  408. data/app/assets/javascripts/moment/locale/pa-in.js +123 -0
  409. data/app/assets/javascripts/moment/locale/pl.js +125 -0
  410. data/app/assets/javascripts/moment/locale/pt-br.js +60 -0
  411. data/app/assets/javascripts/moment/locale/pt.js +64 -0
  412. data/app/assets/javascripts/moment/locale/ro.js +74 -0
  413. data/app/assets/javascripts/moment/locale/ru.js +181 -0
  414. data/app/assets/javascripts/moment/locale/sd.js +97 -0
  415. data/app/assets/javascripts/moment/locale/se.js +59 -0
  416. data/app/assets/javascripts/moment/locale/si.js +70 -0
  417. data/app/assets/javascripts/moment/locale/sk.js +155 -0
  418. data/app/assets/javascripts/moment/locale/sl.js +172 -0
  419. data/app/assets/javascripts/moment/locale/sq.js +67 -0
  420. data/app/assets/javascripts/moment/locale/sr-cyrl.js +110 -0
  421. data/app/assets/javascripts/moment/locale/sr.js +110 -0
  422. data/app/assets/javascripts/moment/locale/ss.js +87 -0
  423. data/app/assets/javascripts/moment/locale/sv.js +68 -0
  424. data/app/assets/javascripts/moment/locale/sw.js +58 -0
  425. data/app/assets/javascripts/moment/locale/ta.js +128 -0
  426. data/app/assets/javascripts/moment/locale/te.js +88 -0
  427. data/app/assets/javascripts/moment/locale/tet.js +66 -0
  428. data/app/assets/javascripts/moment/locale/tg.js +115 -0
  429. data/app/assets/javascripts/moment/locale/th.js +66 -0
  430. data/app/assets/javascripts/moment/locale/tl-ph.js +61 -0
  431. data/app/assets/javascripts/moment/locale/tlh.js +121 -0
  432. data/app/assets/javascripts/moment/locale/tr.js +93 -0
  433. data/app/assets/javascripts/moment/locale/tzl.js +90 -0
  434. data/app/assets/javascripts/moment/locale/tzm-latn.js +57 -0
  435. data/app/assets/javascripts/moment/locale/tzm.js +57 -0
  436. data/app/assets/javascripts/moment/locale/ug-cn.js +118 -0
  437. data/app/assets/javascripts/moment/locale/uk.js +153 -0
  438. data/app/assets/javascripts/moment/locale/ur.js +97 -0
  439. data/app/assets/javascripts/moment/locale/uz-latn.js +57 -0
  440. data/app/assets/javascripts/moment/locale/uz.js +57 -0
  441. data/app/assets/javascripts/moment/locale/vi.js +78 -0
  442. data/app/assets/javascripts/moment/locale/x-pseudo.js +67 -0
  443. data/app/assets/javascripts/moment/locale/yo.js +59 -0
  444. data/app/assets/javascripts/moment/locale/zh-cn.js +109 -0
  445. data/app/assets/javascripts/moment/locale/zh-hk.js +102 -0
  446. data/app/assets/javascripts/moment/locale/zh-tw.js +102 -0
  447. data/app/assets/javascripts/moment/moment.js +4603 -0
  448. data/app/assets/stylesheets/effective_bootstrap.scss +12 -0
  449. data/app/assets/stylesheets/effective_bootstrap/base.scss +4 -0
  450. data/app/assets/stylesheets/effective_bootstrap/forms.scss +65 -0
  451. data/app/assets/stylesheets/effective_bootstrap/icons.scss +67 -0
  452. data/app/assets/stylesheets/effective_bootstrap/overrides.scss +14 -0
  453. data/app/assets/stylesheets/effective_checks/input.scss +8 -0
  454. data/app/assets/stylesheets/effective_date/input.scss +1 -0
  455. data/app/assets/stylesheets/effective_datetime/bootstrap-datetimepicker.scss +374 -0
  456. data/app/assets/stylesheets/effective_datetime/input.scss +2 -0
  457. data/app/assets/stylesheets/effective_datetime/overrides.scss +31 -0
  458. data/app/assets/stylesheets/effective_editor/input.scss +2 -0
  459. data/app/assets/stylesheets/effective_editor/overrides.scss +25 -0
  460. data/app/assets/stylesheets/effective_editor/quill.scss +948 -0
  461. data/app/assets/stylesheets/effective_file/input.scss +46 -0
  462. data/app/assets/stylesheets/effective_radio/input.scss +29 -0
  463. data/app/assets/stylesheets/effective_select/bootstrap-theme.css +564 -0
  464. data/app/assets/stylesheets/effective_select/input.scss +3 -0
  465. data/app/assets/stylesheets/effective_select/overrides.scss +115 -0
  466. data/app/assets/stylesheets/effective_select/select2.css +484 -0
  467. data/app/assets/stylesheets/effective_select_or_text/input.scss +6 -0
  468. data/app/assets/stylesheets/effective_time/input.scss +1 -0
  469. data/app/helpers/effective_bootstrap_helper.rb +371 -0
  470. data/app/helpers/effective_editor_helper.rb +29 -0
  471. data/app/helpers/effective_form_builder_helper.rb +74 -0
  472. data/app/helpers/effective_icons_helper.rb +51 -0
  473. data/app/models/effective/access_denied.rb +17 -0
  474. data/app/models/effective/form_builder.rb +199 -0
  475. data/app/models/effective/form_input.rb +434 -0
  476. data/app/models/effective/form_inputs/check_box.rb +70 -0
  477. data/app/models/effective/form_inputs/checks.rb +99 -0
  478. data/app/models/effective/form_inputs/ck_editor.rb +48 -0
  479. data/app/models/effective/form_inputs/clear.rb +22 -0
  480. data/app/models/effective/form_inputs/collection_input.rb +168 -0
  481. data/app/models/effective/form_inputs/date_field.rb +34 -0
  482. data/app/models/effective/form_inputs/datetime_field.rb +83 -0
  483. data/app/models/effective/form_inputs/delete.rb +26 -0
  484. data/app/models/effective/form_inputs/editor.rb +88 -0
  485. data/app/models/effective/form_inputs/email_cc_field.rb +19 -0
  486. data/app/models/effective/form_inputs/email_field.rb +20 -0
  487. data/app/models/effective/form_inputs/error_field.rb +47 -0
  488. data/app/models/effective/form_inputs/file_field.rb +135 -0
  489. data/app/models/effective/form_inputs/float_field.rb +20 -0
  490. data/app/models/effective/form_inputs/form_group.rb +15 -0
  491. data/app/models/effective/form_inputs/integer_field.rb +18 -0
  492. data/app/models/effective/form_inputs/number_field.rb +10 -0
  493. data/app/models/effective/form_inputs/number_text_field.rb +15 -0
  494. data/app/models/effective/form_inputs/password_field.rb +24 -0
  495. data/app/models/effective/form_inputs/percent_field.rb +38 -0
  496. data/app/models/effective/form_inputs/phone_field.rb +39 -0
  497. data/app/models/effective/form_inputs/price_field.rb +32 -0
  498. data/app/models/effective/form_inputs/radios.rb +175 -0
  499. data/app/models/effective/form_inputs/remote_link_to.rb +30 -0
  500. data/app/models/effective/form_inputs/reset.rb +22 -0
  501. data/app/models/effective/form_inputs/save.rb +22 -0
  502. data/app/models/effective/form_inputs/search_field.rb +15 -0
  503. data/app/models/effective/form_inputs/select.rb +176 -0
  504. data/app/models/effective/form_inputs/select_or_text.rb +70 -0
  505. data/app/models/effective/form_inputs/static_field.rb +41 -0
  506. data/app/models/effective/form_inputs/submit.rb +109 -0
  507. data/app/models/effective/form_inputs/text_area.rb +11 -0
  508. data/app/models/effective/form_inputs/text_field.rb +6 -0
  509. data/app/models/effective/form_inputs/time_field.rb +34 -0
  510. data/app/models/effective/form_inputs/time_zone_select.rb +15 -0
  511. data/app/models/effective/form_inputs/url_field.rb +20 -0
  512. data/app/models/effective/form_logic.rb +45 -0
  513. data/app/models/effective/form_logics/hide_if.rb +39 -0
  514. data/app/models/effective/form_logics/show_if.rb +39 -0
  515. data/app/models/effective/form_logics/show_if_any.rb +42 -0
  516. data/app/views/effective/style_guide/__fields.html.haml +43 -0
  517. data/app/views/effective/style_guide/__inline_fields.html.haml +4 -0
  518. data/app/views/effective/style_guide/_effective_form_with.html.haml +26 -0
  519. data/app/views/effective/style_guide/_feather_icons.html.haml +9 -0
  520. data/config/effective_bootstrap.rb +27 -0
  521. data/lib/effective_bootstrap.rb +33 -0
  522. data/lib/effective_bootstrap/engine.rb +15 -0
  523. data/lib/effective_bootstrap/version.rb +3 -0
  524. data/lib/generators/effective_bootstrap/install_generator.rb +14 -0
  525. metadata +650 -0
@@ -0,0 +1,64 @@
1
+ (this.EffectiveBootstrap || {}).effective_hide_if = ($element, options) ->
2
+ $affects = $element.closest('form').find("input[name='#{options.name}'],select[name='#{options.name}']")
3
+
4
+ $affects.on 'change', (event) ->
5
+ $target = $(event.target)
6
+ matches = ($target.val() == options.value)
7
+
8
+ if $target.is("[type='checkbox']")
9
+ matches = matches || ($target.is(':checked') && "#{options.value}" == 'true')
10
+ matches = matches || (!$target.is(':checked') && ("#{options.value}" == 'false' || "#{options.value}" == ''))
11
+
12
+ if matches
13
+ $element.hide()
14
+ $element.find('input,textarea,select').prop('disabled', true)
15
+ else
16
+ $element.fadeIn()
17
+ $element.find('input,textarea,select').removeAttr('disabled')
18
+
19
+ # Maybe disable it now
20
+ if options.needDisable
21
+ $element.find('input,textarea,select').prop('disabled', true)
22
+
23
+
24
+ (this.EffectiveBootstrap || {}).effective_show_if = ($element, options) ->
25
+ $affects = $element.closest('form').find("input[name='#{options.name}'],select[name='#{options.name}']")
26
+
27
+ $affects.on 'change', (event) ->
28
+ $target = $(event.target)
29
+ matches = ($target.val() == options.value)
30
+
31
+ if $target.is("[type='checkbox']")
32
+ matches = matches || ($target.is(':checked') && "#{options.value}" == 'true')
33
+ matches = matches || (!$target.is(':checked') && ("#{options.value}" == 'false' || "#{options.value}" == ''))
34
+
35
+ if matches
36
+ $element.fadeIn()
37
+ $element.find('input,textarea,select').removeAttr('disabled')
38
+ else
39
+ $element.hide()
40
+ $element.find('input,textarea,select').prop('disabled', true)
41
+
42
+ # Maybe disable it now
43
+ if options.needDisable
44
+ $element.find('input,textarea,select').prop('disabled', true)
45
+
46
+ (this.EffectiveBootstrap || {}).effective_show_if_any = ($element, options) ->
47
+ $affects = $element.closest('form').find("input[name='#{options.name}'],select[name='#{options.name}']")
48
+ values = JSON.parse(options.value)
49
+
50
+ $affects.on 'change', (event) ->
51
+ selected = $(event.target).val()
52
+ found = values.find((value) => (value == selected || "#{value}" == "#{selected}"))
53
+
54
+ if found
55
+ $element.fadeIn()
56
+ $element.find('input,textarea,select').removeAttr('disabled')
57
+ else
58
+ $element.hide()
59
+ $element.find('input,textarea,select').prop('disabled', true)
60
+
61
+ # Maybe disable it now
62
+ if options.needDisable
63
+ $element.find('input,textarea,select').prop('disabled', true)
64
+
@@ -0,0 +1,4 @@
1
+ # Fade out cocoon remove.
2
+ $(document).on 'cocoon:before-remove', (event, $obj) ->
3
+ $(event.target).data('remove-timeout', 1000)
4
+ $obj.fadeOut('slow')
@@ -0,0 +1,14 @@
1
+ $(document).ready(function() {
2
+ var $tab_with_error = $(".form-control.is-invalid").first().closest('.tab-pane');
3
+
4
+ if ($tab_with_error.length > 0) {
5
+ $(".nav.nav-tabs").find("a[href^='#" + $tab_with_error.attr('id') + "']").tab('show');
6
+ } else if (document.location.hash.length > 0) {
7
+ var $tab_from_url = $(".nav.nav-tabs").find("a[href^='" + document.location.hash + "']");
8
+
9
+ if ($tab_from_url.length > 0) {
10
+ document.location.hash = ""; // This prevents scrolling to the wrong place in the page
11
+ $tab_from_url.tab("show");
12
+ }
13
+ }
14
+ });
@@ -0,0 +1,7 @@
1
+ $(document).on 'click', '[data-effective-checks-all]', (event) ->
2
+ $(event.currentTarget).closest('.effective-checks').find('input:checkbox:enabled:not([readonly])').prop('checked', true)
3
+ false
4
+
5
+ $(document).on 'click', '[data-effective-checks-none]', (event) ->
6
+ $(event.currentTarget).closest('.effective-checks').find('input:checkbox:enabled:not([readonly])').prop('checked', false)
7
+ false
@@ -0,0 +1 @@
1
+ //= require ./initialize
@@ -0,0 +1,72 @@
1
+ # http://eonasdan.github.io/bootstrap-datetimepicker/Options/
2
+ (this.EffectiveBootstrap || {}).effective_ck_editor = ($element, options) ->
3
+ setupCkeditor($element)
4
+ initCkeditor($element, $element.data('input-js-options'))
5
+
6
+ # This is a one-time initialization that is done to check that all the scripts are properly set up
7
+ setupCkeditor = ($inputs) ->
8
+ return unless $inputs.length > 0
9
+
10
+ input_js_options = $inputs.first().data('input-js-options') || {}
11
+
12
+ ckeditor_present = ((try CKEDITOR.version) || '').length > 0
13
+ $head = $('head')
14
+
15
+ unless ckeditor_present
16
+ $head.append("<link href='#{input_js_options['effective_ckeditor_css_path']}' type='text/css', media='screen' rel='stylesheet' />")
17
+ jQuery.ajax({url: input_js_options['effective_ckeditor_js_path'], dataType: 'script', cache: true, async: false})
18
+
19
+ initCkeditor = ($element, input_options) ->
20
+ options =
21
+ toolbar: (input_options['toolbar'] || 'full')
22
+ effectiveRegionType: 'full'
23
+ customConfig: ''
24
+ enterMode: CKEDITOR.ENTER_P
25
+ shiftEnterMode: CKEDITOR.ENTER_BR
26
+ startupOutlineBlocks: true
27
+ startupShowBorders: true
28
+ disableNativeTableHandles: true
29
+ disableNativeSpellChecker: false
30
+ extraPlugins: 'effective_regions,effective_assets'
31
+ removePlugins: 'elementspath'
32
+ format_tags: 'p;h1;h2;h3;h4;h5;h6;pre;div'
33
+ templates: 'effective_regions'
34
+ templates_files: []
35
+ templates_replaceContent: false
36
+ filebrowserWindowHeight: 600
37
+ filebrowserWindowWidth: 800
38
+ filebrowserBrowseUrl: window.CKEDITOR_FILE_BROWSE_URL
39
+ filebrowserImageBrowseUrl: window.CKEDITOR_FILE_BROWSE_URL + '?only=images'
40
+ toolbar_full: [
41
+ { name: 'html', items: ['Sourcedialog', '-', 'ShowBlocks'] },
42
+ { name: 'editing', items: ['Undo', 'Redo'] },
43
+ { name: 'clipboard', items: ['Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord'] },
44
+ { name: 'justify', items: ['JustifyLeft', 'JustifyCenter', 'JustifyRight']},
45
+ { name: 'basicstyles', items: ['Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat'] },
46
+ { name: 'lists', items: ['NumberedList', 'BulletedList', '-', 'Outdent', 'Indent'] },
47
+ '/'
48
+ { name: 'definedstyles', items: ['Styles', 'Format'] },
49
+ { name: 'links', items: ['Link', 'Unlink', '-', 'Anchor'] },
50
+ { name: 'insert', items: ['Image', 'oembed'] },
51
+ { name: 'lists', items: ['NumberedList', 'BulletedList', '-', 'Outdent', 'Indent'] },
52
+ { name: 'insert2', items: ['Table', 'EffectiveReferences', 'Blockquote', 'HorizontalRule', 'PageBreak'] },
53
+ { name: 'colors', items: ['TextColor', 'BGColor'] },
54
+ { name: 'snippets', items: ['Templates'] }
55
+ ],
56
+ toolbar_simple: [
57
+ { name: 'definedstyles', items: ['Format'] },
58
+ { name: 'html', items: ['ShowBlocks'] },
59
+ { name: 'justify', items: ['JustifyLeft', 'JustifyCenter', 'JustifyRight']}
60
+ { name: 'basicstyles', items: ['Bold', 'Italic', 'Underline'] },
61
+ { name: 'insert', items: ['Link', 'Table'] },
62
+ { name: 'lists', items: ['NumberedList', 'BulletedList', '-', 'Outdent', 'Indent'] },
63
+ ]
64
+
65
+ options[k] = v for k, v of ($element.data('input-js-options') || {})
66
+
67
+ ckeditor = CKEDITOR.replace($element.attr('id'), options)
68
+
69
+ ckeditor.on 'insertElement', (event) ->
70
+ element = $(event.data.$)
71
+ if element.is('table')
72
+ element.removeAttr('style').addClass('table')
@@ -0,0 +1 @@
1
+ //= require ./initialize
@@ -0,0 +1,3 @@
1
+ $(document).on 'click', 'button[type=clear]', (event) ->
2
+ event.preventDefault()
3
+ $(event.currentTarget).closest('form').trigger('clear')
@@ -0,0 +1 @@
1
+ //= require ./initialize
@@ -0,0 +1,7 @@
1
+ # http://eonasdan.github.io/bootstrap-datetimepicker/Options/
2
+ (this.EffectiveBootstrap || {}).effective_date = ($element, options) ->
3
+ $element.datetimepicker(options)
4
+
5
+ name = $element.attr('name') || ''
6
+ if name.indexOf('end_') != -1 || name.indexOf('_end') != -1
7
+ $element.trigger('dp.end_date_initialized')
@@ -0,0 +1,5 @@
1
+ //= require ../moment/moment
2
+ //= require ../effective_datetime/bootstrap-datetimepicker
3
+ //= require ../effective_datetime/overrides
4
+ //= require ../effective_datetime/turbolinks
5
+ //= require ./initialize
@@ -0,0 +1,2636 @@
1
+ /*! version : 4.17.47
2
+ =========================================================
3
+ bootstrap-datetimejs
4
+ https://github.com/Eonasdan/bootstrap-datetimepicker
5
+ Copyright (c) 2015 Jonathan Peterson
6
+ =========================================================
7
+ */
8
+ /*
9
+ The MIT License (MIT)
10
+
11
+ Copyright (c) 2015 Jonathan Peterson
12
+
13
+ Permission is hereby granted, free of charge, to any person obtaining a copy
14
+ of this software and associated documentation files (the "Software"), to deal
15
+ in the Software without restriction, including without limitation the rights
16
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
+ copies of the Software, and to permit persons to whom the Software is
18
+ furnished to do so, subject to the following conditions:
19
+
20
+ The above copyright notice and this permission notice shall be included in
21
+ all copies or substantial portions of the Software.
22
+
23
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29
+ THE SOFTWARE.
30
+ */
31
+ /*global define:false */
32
+ /*global exports:false */
33
+ /*global require:false */
34
+ /*global jQuery:false */
35
+ /*global moment:false */
36
+ (function (factory) {
37
+ 'use strict';
38
+ if (typeof define === 'function' && define.amd) {
39
+ // AMD is used - Register as an anonymous module.
40
+ define(['jquery', 'moment'], factory);
41
+ } else if (typeof exports === 'object') {
42
+ module.exports = factory(require('jquery'), require('moment'));
43
+ } else {
44
+ // Neither AMD nor CommonJS used. Use global variables.
45
+ if (typeof jQuery === 'undefined') {
46
+ throw 'bootstrap-datetimepicker requires jQuery to be loaded first';
47
+ }
48
+ if (typeof moment === 'undefined') {
49
+ throw 'bootstrap-datetimepicker requires Moment.js to be loaded first';
50
+ }
51
+ factory(jQuery, moment);
52
+ }
53
+ }(function ($, moment) {
54
+ 'use strict';
55
+ if (!moment) {
56
+ throw new Error('bootstrap-datetimepicker requires Moment.js to be loaded first');
57
+ }
58
+
59
+ var dateTimePicker = function (element, options) {
60
+ var picker = {},
61
+ date,
62
+ viewDate,
63
+ unset = true,
64
+ input,
65
+ component = false,
66
+ widget = false,
67
+ use24Hours,
68
+ minViewModeNumber = 0,
69
+ actualFormat,
70
+ parseFormats,
71
+ currentViewMode,
72
+ datePickerModes = [
73
+ {
74
+ clsName: 'days',
75
+ navFnc: 'M',
76
+ navStep: 1
77
+ },
78
+ {
79
+ clsName: 'months',
80
+ navFnc: 'y',
81
+ navStep: 1
82
+ },
83
+ {
84
+ clsName: 'years',
85
+ navFnc: 'y',
86
+ navStep: 10
87
+ },
88
+ {
89
+ clsName: 'decades',
90
+ navFnc: 'y',
91
+ navStep: 100
92
+ }
93
+ ],
94
+ viewModes = ['days', 'months', 'years', 'decades'],
95
+ verticalModes = ['top', 'bottom', 'auto'],
96
+ horizontalModes = ['left', 'right', 'auto'],
97
+ toolbarPlacements = ['default', 'top', 'bottom'],
98
+ keyMap = {
99
+ 'up': 38,
100
+ 38: 'up',
101
+ 'down': 40,
102
+ 40: 'down',
103
+ 'left': 37,
104
+ 37: 'left',
105
+ 'right': 39,
106
+ 39: 'right',
107
+ 'tab': 9,
108
+ 9: 'tab',
109
+ 'escape': 27,
110
+ 27: 'escape',
111
+ 'enter': 13,
112
+ 13: 'enter',
113
+ 'pageUp': 33,
114
+ 33: 'pageUp',
115
+ 'pageDown': 34,
116
+ 34: 'pageDown',
117
+ 'shift': 16,
118
+ 16: 'shift',
119
+ 'control': 17,
120
+ 17: 'control',
121
+ 'space': 32,
122
+ 32: 'space',
123
+ 't': 84,
124
+ 84: 't',
125
+ 'delete': 46,
126
+ 46: 'delete'
127
+ },
128
+ keyState = {},
129
+
130
+ /********************************************************************************
131
+ *
132
+ * Private functions
133
+ *
134
+ ********************************************************************************/
135
+
136
+ hasTimeZone = function () {
137
+ return moment.tz !== undefined && options.timeZone !== undefined && options.timeZone !== null && options.timeZone !== '';
138
+ },
139
+
140
+ getMoment = function (d) {
141
+ var returnMoment;
142
+
143
+ if (d === undefined || d === null) {
144
+ returnMoment = moment(); //TODO should this use format? and locale?
145
+ } else if (moment.isDate(d) || moment.isMoment(d)) {
146
+ // If the date that is passed in is already a Date() or moment() object,
147
+ // pass it directly to moment.
148
+ returnMoment = moment(d);
149
+ } else if (hasTimeZone()) { // There is a string to parse and a default time zone
150
+ // parse with the tz function which takes a default time zone if it is not in the format string
151
+ returnMoment = moment.tz(d, parseFormats, options.useStrict, options.timeZone);
152
+ } else {
153
+ returnMoment = moment(d, parseFormats, options.useStrict);
154
+ }
155
+
156
+ if (hasTimeZone()) {
157
+ returnMoment.tz(options.timeZone);
158
+ }
159
+
160
+ return returnMoment;
161
+ },
162
+
163
+ isEnabled = function (granularity) {
164
+ if (typeof granularity !== 'string' || granularity.length > 1) {
165
+ throw new TypeError('isEnabled expects a single character string parameter');
166
+ }
167
+ switch (granularity) {
168
+ case 'y':
169
+ return actualFormat.indexOf('Y') !== -1;
170
+ case 'M':
171
+ return actualFormat.indexOf('M') !== -1;
172
+ case 'd':
173
+ return actualFormat.toLowerCase().indexOf('d') !== -1;
174
+ case 'h':
175
+ case 'H':
176
+ return actualFormat.toLowerCase().indexOf('h') !== -1;
177
+ case 'm':
178
+ return actualFormat.indexOf('m') !== -1;
179
+ case 's':
180
+ return actualFormat.indexOf('s') !== -1;
181
+ default:
182
+ return false;
183
+ }
184
+ },
185
+
186
+ hasTime = function () {
187
+ return (isEnabled('h') || isEnabled('m') || isEnabled('s'));
188
+ },
189
+
190
+ hasDate = function () {
191
+ return (isEnabled('y') || isEnabled('M') || isEnabled('d'));
192
+ },
193
+
194
+ getDatePickerTemplate = function () {
195
+ var headTemplate = $('<thead>')
196
+ .append($('<tr>')
197
+ .append($('<th>').addClass('prev').attr('data-action', 'previous')
198
+ .append($('<span>').addClass(options.icons.previous))
199
+ )
200
+ .append($('<th>').addClass('picker-switch').attr('data-action', 'pickerSwitch').attr('colspan', (options.calendarWeeks ? '6' : '5')))
201
+ .append($('<th>').addClass('next').attr('data-action', 'next')
202
+ .append($('<span>').addClass(options.icons.next))
203
+ )
204
+ ),
205
+ contTemplate = $('<tbody>')
206
+ .append($('<tr>')
207
+ .append($('<td>').attr('colspan', (options.calendarWeeks ? '8' : '7')))
208
+ );
209
+
210
+ return [
211
+ $('<div>').addClass('datepicker-days')
212
+ .append($('<table>').addClass('table-condensed')
213
+ .append(headTemplate)
214
+ .append($('<tbody>'))
215
+ ),
216
+ $('<div>').addClass('datepicker-months')
217
+ .append($('<table>').addClass('table-condensed')
218
+ .append(headTemplate.clone())
219
+ .append(contTemplate.clone())
220
+ ),
221
+ $('<div>').addClass('datepicker-years')
222
+ .append($('<table>').addClass('table-condensed')
223
+ .append(headTemplate.clone())
224
+ .append(contTemplate.clone())
225
+ ),
226
+ $('<div>').addClass('datepicker-decades')
227
+ .append($('<table>').addClass('table-condensed')
228
+ .append(headTemplate.clone())
229
+ .append(contTemplate.clone())
230
+ )
231
+ ];
232
+ },
233
+
234
+ getTimePickerMainTemplate = function () {
235
+ var topRow = $('<tr>'),
236
+ middleRow = $('<tr>'),
237
+ bottomRow = $('<tr>');
238
+
239
+ if (isEnabled('h')) {
240
+ topRow.append($('<td>')
241
+ .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.incrementHour }).addClass('btn').attr('data-action', 'incrementHours').append($('<span>').addClass(options.icons.up))));
242
+ middleRow.append($('<td>')
243
+ .append($('<span>').addClass('timepicker-hour').attr({ 'data-time-component': 'hours', 'title': options.tooltips.pickHour }).attr('data-action', 'showHours')));
244
+ bottomRow.append($('<td>')
245
+ .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.decrementHour }).addClass('btn').attr('data-action', 'decrementHours').append($('<span>').addClass(options.icons.down))));
246
+ }
247
+ if (isEnabled('m')) {
248
+ if (isEnabled('h')) {
249
+ topRow.append($('<td>').addClass('separator'));
250
+ middleRow.append($('<td>').addClass('separator').html(':'));
251
+ bottomRow.append($('<td>').addClass('separator'));
252
+ }
253
+ topRow.append($('<td>')
254
+ .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.incrementMinute }).addClass('btn').attr('data-action', 'incrementMinutes')
255
+ .append($('<span>').addClass(options.icons.up))));
256
+ middleRow.append($('<td>')
257
+ .append($('<span>').addClass('timepicker-minute').attr({ 'data-time-component': 'minutes', 'title': options.tooltips.pickMinute }).attr('data-action', 'showMinutes')));
258
+ bottomRow.append($('<td>')
259
+ .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.decrementMinute }).addClass('btn').attr('data-action', 'decrementMinutes')
260
+ .append($('<span>').addClass(options.icons.down))));
261
+ }
262
+ if (isEnabled('s')) {
263
+ if (isEnabled('m')) {
264
+ topRow.append($('<td>').addClass('separator'));
265
+ middleRow.append($('<td>').addClass('separator').html(':'));
266
+ bottomRow.append($('<td>').addClass('separator'));
267
+ }
268
+ topRow.append($('<td>')
269
+ .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.incrementSecond }).addClass('btn').attr('data-action', 'incrementSeconds')
270
+ .append($('<span>').addClass(options.icons.up))));
271
+ middleRow.append($('<td>')
272
+ .append($('<span>').addClass('timepicker-second').attr({ 'data-time-component': 'seconds', 'title': options.tooltips.pickSecond }).attr('data-action', 'showSeconds')));
273
+ bottomRow.append($('<td>')
274
+ .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.decrementSecond }).addClass('btn').attr('data-action', 'decrementSeconds')
275
+ .append($('<span>').addClass(options.icons.down))));
276
+ }
277
+
278
+ if (!use24Hours) {
279
+ topRow.append($('<td>').addClass('separator'));
280
+ middleRow.append($('<td>')
281
+ .append($('<button>').addClass('btn btn-primary').attr({ 'data-action': 'togglePeriod', tabindex: '-1', 'title': options.tooltips.togglePeriod })));
282
+ bottomRow.append($('<td>').addClass('separator'));
283
+ }
284
+
285
+ return $('<div>').addClass('timepicker-picker')
286
+ .append($('<table>').addClass('table-condensed')
287
+ .append([topRow, middleRow, bottomRow]));
288
+ },
289
+
290
+ getTimePickerTemplate = function () {
291
+ var hoursView = $('<div>').addClass('timepicker-hours')
292
+ .append($('<table>').addClass('table-condensed')),
293
+ minutesView = $('<div>').addClass('timepicker-minutes')
294
+ .append($('<table>').addClass('table-condensed')),
295
+ secondsView = $('<div>').addClass('timepicker-seconds')
296
+ .append($('<table>').addClass('table-condensed')),
297
+ ret = [getTimePickerMainTemplate()];
298
+
299
+ if (isEnabled('h')) {
300
+ ret.push(hoursView);
301
+ }
302
+ if (isEnabled('m')) {
303
+ ret.push(minutesView);
304
+ }
305
+ if (isEnabled('s')) {
306
+ ret.push(secondsView);
307
+ }
308
+
309
+ return ret;
310
+ },
311
+
312
+ getToolbar = function () {
313
+ var row = [];
314
+ if (options.showTodayButton) {
315
+ row.push($('<td>').append($('<a>').attr({ 'data-action': 'today', 'title': options.tooltips.today }).append($('<span>').addClass(options.icons.today))));
316
+ }
317
+ if (!options.sideBySide && hasDate() && hasTime()) {
318
+ row.push($('<td>').append($('<a>').attr({ 'data-action': 'togglePicker', 'title': options.tooltips.selectTime }).append($('<span>').addClass(options.icons.time))));
319
+ }
320
+ if (options.showClear) {
321
+ row.push($('<td>').append($('<a>').attr({ 'data-action': 'clear', 'title': options.tooltips.clear }).append($('<span>').addClass(options.icons.clear))));
322
+ }
323
+ if (options.showClose) {
324
+ row.push($('<td>').append($('<a>').attr({ 'data-action': 'close', 'title': options.tooltips.close }).append($('<span>').addClass(options.icons.close))));
325
+ }
326
+ return $('<table>').addClass('table-condensed').append($('<tbody>').append($('<tr>').append(row)));
327
+ },
328
+
329
+ getTemplate = function () {
330
+ var template = $('<div>').addClass('bootstrap-datetimepicker-widget dropdown-menu'),
331
+ dateView = $('<div>').addClass('datepicker').append(getDatePickerTemplate()),
332
+ timeView = $('<div>').addClass('timepicker').append(getTimePickerTemplate()),
333
+ content = $('<ul>').addClass('list-unstyled'),
334
+ toolbar = $('<li>').addClass('picker-switch' + (options.collapse ? ' accordion-toggle' : '')).append(getToolbar());
335
+
336
+ if (options.inline) {
337
+ template.removeClass('dropdown-menu');
338
+ }
339
+
340
+ if (use24Hours) {
341
+ template.addClass('usetwentyfour');
342
+ }
343
+
344
+ if (isEnabled('s') && !use24Hours) {
345
+ template.addClass('wider');
346
+ }
347
+
348
+ if (options.sideBySide && hasDate() && hasTime()) {
349
+ template.addClass('timepicker-sbs');
350
+ if (options.toolbarPlacement === 'top') {
351
+ template.append(toolbar);
352
+ }
353
+ template.append(
354
+ $('<div>').addClass('row')
355
+ .append(dateView.addClass('col-md-6'))
356
+ .append(timeView.addClass('col-md-6'))
357
+ );
358
+ if (options.toolbarPlacement === 'bottom') {
359
+ template.append(toolbar);
360
+ }
361
+ return template;
362
+ }
363
+
364
+ if (options.toolbarPlacement === 'top') {
365
+ content.append(toolbar);
366
+ }
367
+ if (hasDate()) {
368
+ content.append($('<li>').addClass((options.collapse && hasTime() ? 'collapse show' : '')).append(dateView));
369
+ }
370
+ if (options.toolbarPlacement === 'default') {
371
+ content.append(toolbar);
372
+ }
373
+ if (hasTime()) {
374
+ content.append($('<li>').addClass((options.collapse && hasDate() ? 'collapse' : '')).append(timeView));
375
+ }
376
+ if (options.toolbarPlacement === 'bottom') {
377
+ content.append(toolbar);
378
+ }
379
+ return template.append(content);
380
+ },
381
+
382
+ dataToOptions = function () {
383
+ var eData,
384
+ dataOptions = {};
385
+
386
+ if (element.is('input') || options.inline) {
387
+ eData = element.data();
388
+ } else {
389
+ eData = element.find('input').data();
390
+ }
391
+
392
+ if (eData.dateOptions && eData.dateOptions instanceof Object) {
393
+ dataOptions = $.extend(true, dataOptions, eData.dateOptions);
394
+ }
395
+
396
+ $.each(options, function (key) {
397
+ var attributeName = 'date' + key.charAt(0).toUpperCase() + key.slice(1);
398
+ if (eData[attributeName] !== undefined) {
399
+ dataOptions[key] = eData[attributeName];
400
+ }
401
+ });
402
+ return dataOptions;
403
+ },
404
+
405
+ place = function () {
406
+ var position = (component || element).position(),
407
+ offset = (component || element).offset(),
408
+ vertical = options.widgetPositioning.vertical,
409
+ horizontal = options.widgetPositioning.horizontal,
410
+ parent;
411
+
412
+ if (options.widgetParent) {
413
+ parent = options.widgetParent.append(widget);
414
+ } else if (element.is('input')) {
415
+ parent = element.after(widget).parent();
416
+ } else if (options.inline) {
417
+ parent = element.append(widget);
418
+ return;
419
+ } else {
420
+ parent = element;
421
+ element.children().first().after(widget);
422
+ }
423
+
424
+ // Top and bottom logic
425
+ if (vertical === 'auto') {
426
+ if (offset.top + widget.height() * 1.5 >= $(window).height() + $(window).scrollTop() &&
427
+ widget.height() + element.outerHeight() < offset.top) {
428
+ vertical = 'top';
429
+ } else {
430
+ vertical = 'bottom';
431
+ }
432
+ }
433
+
434
+ // Left and right logic
435
+ if (horizontal === 'auto') {
436
+ if (parent.width() < offset.left + widget.outerWidth() / 2 &&
437
+ offset.left + widget.outerWidth() > $(window).width()) {
438
+ horizontal = 'right';
439
+ } else {
440
+ horizontal = 'left';
441
+ }
442
+ }
443
+
444
+ if (vertical === 'top') {
445
+ widget.addClass('top').removeClass('bottom');
446
+ } else {
447
+ widget.addClass('bottom').removeClass('top');
448
+ }
449
+
450
+ if (horizontal === 'right') {
451
+ widget.addClass('pull-right');
452
+ } else {
453
+ widget.removeClass('pull-right');
454
+ }
455
+
456
+ // find the first parent element that has a non-static css positioning
457
+ if (parent.css('position') === 'static') {
458
+ parent = parent.parents().filter(function () {
459
+ return $(this).css('position') !== 'static';
460
+ }).first();
461
+ }
462
+
463
+ if (parent.length === 0) {
464
+ throw new Error('datetimepicker component should be placed within a non-static positioned container');
465
+ }
466
+
467
+ widget.css({
468
+ top: vertical === 'top' ? 'auto' : position.top + element.outerHeight(),
469
+ bottom: vertical === 'top' ? parent.outerHeight() - (parent === element ? 0 : position.top) : 'auto',
470
+ left: horizontal === 'left' ? (parent === element ? 0 : position.left) : 'auto',
471
+ right: horizontal === 'left' ? 'auto' : parent.outerWidth() - element.outerWidth() - (parent === element ? 0 : position.left)
472
+ });
473
+ },
474
+
475
+ notifyEvent = function (e) {
476
+ if (e.type === 'dp.change' && ((e.date && e.date.isSame(e.oldDate)) || (!e.date && !e.oldDate))) {
477
+ return;
478
+ }
479
+ element.trigger(e);
480
+ },
481
+
482
+ viewUpdate = function (e) {
483
+ if (e === 'y') {
484
+ e = 'YYYY';
485
+ }
486
+ notifyEvent({
487
+ type: 'dp.update',
488
+ change: e,
489
+ viewDate: viewDate.clone()
490
+ });
491
+ },
492
+
493
+ showMode = function (dir) {
494
+ if (!widget) {
495
+ return;
496
+ }
497
+ if (dir) {
498
+ currentViewMode = Math.max(minViewModeNumber, Math.min(3, currentViewMode + dir));
499
+ }
500
+ widget.find('.datepicker > div').hide().filter('.datepicker-' + datePickerModes[currentViewMode].clsName).show();
501
+ },
502
+
503
+ fillDow = function () {
504
+ var row = $('<tr>'),
505
+ currentDate = viewDate.clone().startOf('w').startOf('d');
506
+
507
+ if (options.calendarWeeks === true) {
508
+ row.append($('<th>').addClass('cw').text('#'));
509
+ }
510
+
511
+ while (currentDate.isBefore(viewDate.clone().endOf('w'))) {
512
+ row.append($('<th>').addClass('dow').text(currentDate.format('dd')));
513
+ currentDate.add(1, 'd');
514
+ }
515
+ widget.find('.datepicker-days thead').append(row);
516
+ },
517
+
518
+ isInDisabledDates = function (testDate) {
519
+ return options.disabledDates[testDate.format('YYYY-MM-DD')] === true;
520
+ },
521
+
522
+ isInEnabledDates = function (testDate) {
523
+ return options.enabledDates[testDate.format('YYYY-MM-DD')] === true;
524
+ },
525
+
526
+ isInDisabledHours = function (testDate) {
527
+ return options.disabledHours[testDate.format('H')] === true;
528
+ },
529
+
530
+ isInEnabledHours = function (testDate) {
531
+ return options.enabledHours[testDate.format('H')] === true;
532
+ },
533
+
534
+ isValid = function (targetMoment, granularity) {
535
+ if (!targetMoment.isValid()) {
536
+ return false;
537
+ }
538
+ if (options.disabledDates && granularity === 'd' && isInDisabledDates(targetMoment)) {
539
+ return false;
540
+ }
541
+ if (options.enabledDates && granularity === 'd' && !isInEnabledDates(targetMoment)) {
542
+ return false;
543
+ }
544
+ if (options.minDate && targetMoment.isBefore(options.minDate, granularity)) {
545
+ return false;
546
+ }
547
+ if (options.maxDate && targetMoment.isAfter(options.maxDate, granularity)) {
548
+ return false;
549
+ }
550
+ if (options.daysOfWeekDisabled && granularity === 'd' && options.daysOfWeekDisabled.indexOf(targetMoment.day()) !== -1) {
551
+ return false;
552
+ }
553
+ if (options.disabledHours && (granularity === 'h' || granularity === 'm' || granularity === 's') && isInDisabledHours(targetMoment)) {
554
+ return false;
555
+ }
556
+ if (options.enabledHours && (granularity === 'h' || granularity === 'm' || granularity === 's') && !isInEnabledHours(targetMoment)) {
557
+ return false;
558
+ }
559
+ if (options.disabledTimeIntervals && (granularity === 'h' || granularity === 'm' || granularity === 's')) {
560
+ var found = false;
561
+ $.each(options.disabledTimeIntervals, function () {
562
+ if (targetMoment.isBetween(this[0], this[1])) {
563
+ found = true;
564
+ return false;
565
+ }
566
+ });
567
+ if (found) {
568
+ return false;
569
+ }
570
+ }
571
+ return true;
572
+ },
573
+
574
+ fillMonths = function () {
575
+ var spans = [],
576
+ monthsShort = viewDate.clone().startOf('y').startOf('d');
577
+ while (monthsShort.isSame(viewDate, 'y')) {
578
+ spans.push($('<span>').attr('data-action', 'selectMonth').addClass('month').text(monthsShort.format('MMM')));
579
+ monthsShort.add(1, 'M');
580
+ }
581
+ widget.find('.datepicker-months td').empty().append(spans);
582
+ },
583
+
584
+ updateMonths = function () {
585
+ var monthsView = widget.find('.datepicker-months'),
586
+ monthsViewHeader = monthsView.find('th'),
587
+ months = monthsView.find('tbody').find('span');
588
+
589
+ monthsViewHeader.eq(0).find('span').attr('title', options.tooltips.prevYear);
590
+ monthsViewHeader.eq(1).attr('title', options.tooltips.selectYear);
591
+ monthsViewHeader.eq(2).find('span').attr('title', options.tooltips.nextYear);
592
+
593
+ monthsView.find('.disabled').removeClass('disabled');
594
+
595
+ if (!isValid(viewDate.clone().subtract(1, 'y'), 'y')) {
596
+ monthsViewHeader.eq(0).addClass('disabled');
597
+ }
598
+
599
+ monthsViewHeader.eq(1).text(viewDate.year());
600
+
601
+ if (!isValid(viewDate.clone().add(1, 'y'), 'y')) {
602
+ monthsViewHeader.eq(2).addClass('disabled');
603
+ }
604
+
605
+ months.removeClass('active');
606
+ if (date.isSame(viewDate, 'y') && !unset) {
607
+ months.eq(date.month()).addClass('active');
608
+ }
609
+
610
+ months.each(function (index) {
611
+ if (!isValid(viewDate.clone().month(index), 'M')) {
612
+ $(this).addClass('disabled');
613
+ }
614
+ });
615
+ },
616
+
617
+ updateYears = function () {
618
+ var yearsView = widget.find('.datepicker-years'),
619
+ yearsViewHeader = yearsView.find('th'),
620
+ startYear = viewDate.clone().subtract(5, 'y'),
621
+ endYear = viewDate.clone().add(6, 'y'),
622
+ html = '';
623
+
624
+ yearsViewHeader.eq(0).find('span').attr('title', options.tooltips.prevDecade);
625
+ yearsViewHeader.eq(1).attr('title', options.tooltips.selectDecade);
626
+ yearsViewHeader.eq(2).find('span').attr('title', options.tooltips.nextDecade);
627
+
628
+ yearsView.find('.disabled').removeClass('disabled');
629
+
630
+ if (options.minDate && options.minDate.isAfter(startYear, 'y')) {
631
+ yearsViewHeader.eq(0).addClass('disabled');
632
+ }
633
+
634
+ yearsViewHeader.eq(1).text(startYear.year() + '-' + endYear.year());
635
+
636
+ if (options.maxDate && options.maxDate.isBefore(endYear, 'y')) {
637
+ yearsViewHeader.eq(2).addClass('disabled');
638
+ }
639
+
640
+ while (!startYear.isAfter(endYear, 'y')) {
641
+ html += '<span data-action="selectYear" class="year' + (startYear.isSame(date, 'y') && !unset ? ' active' : '') + (!isValid(startYear, 'y') ? ' disabled' : '') + '">' + startYear.year() + '</span>';
642
+ startYear.add(1, 'y');
643
+ }
644
+
645
+ yearsView.find('td').html(html);
646
+ },
647
+
648
+ updateDecades = function () {
649
+ var decadesView = widget.find('.datepicker-decades'),
650
+ decadesViewHeader = decadesView.find('th'),
651
+ startDecade = moment({ y: viewDate.year() - (viewDate.year() % 100) - 1 }),
652
+ endDecade = startDecade.clone().add(100, 'y'),
653
+ startedAt = startDecade.clone(),
654
+ minDateDecade = false,
655
+ maxDateDecade = false,
656
+ endDecadeYear,
657
+ html = '';
658
+
659
+ decadesViewHeader.eq(0).find('span').attr('title', options.tooltips.prevCentury);
660
+ decadesViewHeader.eq(2).find('span').attr('title', options.tooltips.nextCentury);
661
+
662
+ decadesView.find('.disabled').removeClass('disabled');
663
+
664
+ if (startDecade.isSame(moment({ y: 1900 })) || (options.minDate && options.minDate.isAfter(startDecade, 'y'))) {
665
+ decadesViewHeader.eq(0).addClass('disabled');
666
+ }
667
+
668
+ decadesViewHeader.eq(1).text(startDecade.year() + '-' + endDecade.year());
669
+
670
+ if (startDecade.isSame(moment({ y: 2000 })) || (options.maxDate && options.maxDate.isBefore(endDecade, 'y'))) {
671
+ decadesViewHeader.eq(2).addClass('disabled');
672
+ }
673
+
674
+ while (!startDecade.isAfter(endDecade, 'y')) {
675
+ endDecadeYear = startDecade.year() + 12;
676
+ minDateDecade = options.minDate && options.minDate.isAfter(startDecade, 'y') && options.minDate.year() <= endDecadeYear;
677
+ maxDateDecade = options.maxDate && options.maxDate.isAfter(startDecade, 'y') && options.maxDate.year() <= endDecadeYear;
678
+ html += '<span data-action="selectDecade" class="decade' + (date.isAfter(startDecade) && date.year() <= endDecadeYear ? ' active' : '') +
679
+ (!isValid(startDecade, 'y') && !minDateDecade && !maxDateDecade ? ' disabled' : '') + '" data-selection="' + (startDecade.year() + 6) + '">' + (startDecade.year() + 1) + ' - ' + (startDecade.year() + 12) + '</span>';
680
+ startDecade.add(12, 'y');
681
+ }
682
+ html += '<span></span><span></span><span></span>'; //push the dangling block over, at least this way it's even
683
+
684
+ decadesView.find('td').html(html);
685
+ decadesViewHeader.eq(1).text((startedAt.year() + 1) + '-' + (startDecade.year()));
686
+ },
687
+
688
+ fillDate = function () {
689
+ var daysView = widget.find('.datepicker-days'),
690
+ daysViewHeader = daysView.find('th'),
691
+ currentDate,
692
+ html = [],
693
+ row,
694
+ clsNames = [],
695
+ i;
696
+
697
+ if (!hasDate()) {
698
+ return;
699
+ }
700
+
701
+ daysViewHeader.eq(0).find('span').attr('title', options.tooltips.prevMonth);
702
+ daysViewHeader.eq(1).attr('title', options.tooltips.selectMonth);
703
+ daysViewHeader.eq(2).find('span').attr('title', options.tooltips.nextMonth);
704
+
705
+ daysView.find('.disabled').removeClass('disabled');
706
+ daysViewHeader.eq(1).text(viewDate.format(options.dayViewHeaderFormat));
707
+
708
+ if (!isValid(viewDate.clone().subtract(1, 'M'), 'M')) {
709
+ daysViewHeader.eq(0).addClass('disabled');
710
+ }
711
+ if (!isValid(viewDate.clone().add(1, 'M'), 'M')) {
712
+ daysViewHeader.eq(2).addClass('disabled');
713
+ }
714
+
715
+ currentDate = viewDate.clone().startOf('M').startOf('w').startOf('d');
716
+
717
+ for (i = 0; i < 42; i++) { //always display 42 days (should show 6 weeks)
718
+ if (currentDate.weekday() === 0) {
719
+ row = $('<tr>');
720
+ if (options.calendarWeeks) {
721
+ row.append('<td class="cw">' + currentDate.week() + '</td>');
722
+ }
723
+ html.push(row);
724
+ }
725
+ clsNames = ['day'];
726
+ if (currentDate.isBefore(viewDate, 'M')) {
727
+ clsNames.push('old');
728
+ }
729
+ if (currentDate.isAfter(viewDate, 'M')) {
730
+ clsNames.push('new');
731
+ }
732
+ if (currentDate.isSame(date, 'd') && !unset) {
733
+ clsNames.push('active');
734
+ }
735
+ if (!isValid(currentDate, 'd')) {
736
+ clsNames.push('disabled');
737
+ }
738
+ if (currentDate.isSame(getMoment(), 'd')) {
739
+ clsNames.push('today');
740
+ }
741
+ if (currentDate.day() === 0 || currentDate.day() === 6) {
742
+ clsNames.push('weekend');
743
+ }
744
+ notifyEvent({
745
+ type: 'dp.classify',
746
+ date: currentDate,
747
+ classNames: clsNames
748
+ });
749
+ row.append('<td data-action="selectDay" data-day="' + currentDate.format('L') + '" class="' + clsNames.join(' ') + '">' + currentDate.date() + '</td>');
750
+ currentDate.add(1, 'd');
751
+ }
752
+
753
+ daysView.find('tbody').empty().append(html);
754
+
755
+ updateMonths();
756
+
757
+ updateYears();
758
+
759
+ updateDecades();
760
+ },
761
+
762
+ fillHours = function () {
763
+ var table = widget.find('.timepicker-hours table'),
764
+ currentHour = viewDate.clone().startOf('d'),
765
+ html = [],
766
+ row = $('<tr>');
767
+
768
+ if (viewDate.hour() > 11 && !use24Hours) {
769
+ currentHour.hour(12);
770
+ }
771
+ while (currentHour.isSame(viewDate, 'd') && (use24Hours || (viewDate.hour() < 12 && currentHour.hour() < 12) || viewDate.hour() > 11)) {
772
+ if (currentHour.hour() % 4 === 0) {
773
+ row = $('<tr>');
774
+ html.push(row);
775
+ }
776
+ row.append('<td data-action="selectHour" class="hour' + (!isValid(currentHour, 'h') ? ' disabled' : '') + '">' + currentHour.format(use24Hours ? 'HH' : 'hh') + '</td>');
777
+ currentHour.add(1, 'h');
778
+ }
779
+ table.empty().append(html);
780
+ },
781
+
782
+ fillMinutes = function () {
783
+ var table = widget.find('.timepicker-minutes table'),
784
+ currentMinute = viewDate.clone().startOf('h'),
785
+ html = [],
786
+ row = $('<tr>'),
787
+ step = options.stepping === 1 ? 5 : options.stepping;
788
+
789
+ while (viewDate.isSame(currentMinute, 'h')) {
790
+ if (currentMinute.minute() % (step * 4) === 0) {
791
+ row = $('<tr>');
792
+ html.push(row);
793
+ }
794
+ row.append('<td data-action="selectMinute" class="minute' + (!isValid(currentMinute, 'm') ? ' disabled' : '') + '">' + currentMinute.format('mm') + '</td>');
795
+ currentMinute.add(step, 'm');
796
+ }
797
+ table.empty().append(html);
798
+ },
799
+
800
+ fillSeconds = function () {
801
+ var table = widget.find('.timepicker-seconds table'),
802
+ currentSecond = viewDate.clone().startOf('m'),
803
+ html = [],
804
+ row = $('<tr>');
805
+
806
+ while (viewDate.isSame(currentSecond, 'm')) {
807
+ if (currentSecond.second() % 20 === 0) {
808
+ row = $('<tr>');
809
+ html.push(row);
810
+ }
811
+ row.append('<td data-action="selectSecond" class="second' + (!isValid(currentSecond, 's') ? ' disabled' : '') + '">' + currentSecond.format('ss') + '</td>');
812
+ currentSecond.add(5, 's');
813
+ }
814
+
815
+ table.empty().append(html);
816
+ },
817
+
818
+ fillTime = function () {
819
+ var toggle, newDate, timeComponents = widget.find('.timepicker span[data-time-component]');
820
+
821
+ if (!use24Hours) {
822
+ toggle = widget.find('.timepicker [data-action=togglePeriod]');
823
+ newDate = date.clone().add((date.hours() >= 12) ? -12 : 12, 'h');
824
+
825
+ toggle.text(date.format('A'));
826
+
827
+ if (isValid(newDate, 'h')) {
828
+ toggle.removeClass('disabled');
829
+ } else {
830
+ toggle.addClass('disabled');
831
+ }
832
+ }
833
+ timeComponents.filter('[data-time-component=hours]').text(date.format(use24Hours ? 'HH' : 'hh'));
834
+ timeComponents.filter('[data-time-component=minutes]').text(date.format('mm'));
835
+ timeComponents.filter('[data-time-component=seconds]').text(date.format('ss'));
836
+
837
+ fillHours();
838
+ fillMinutes();
839
+ fillSeconds();
840
+ },
841
+
842
+ update = function () {
843
+ if (!widget) {
844
+ return;
845
+ }
846
+ fillDate();
847
+ fillTime();
848
+ },
849
+
850
+ setValue = function (targetMoment) {
851
+ var oldDate = unset ? null : date;
852
+
853
+ // case of calling setValue(null or false)
854
+ if (!targetMoment) {
855
+ unset = true;
856
+ input.val('');
857
+ element.data('date', '');
858
+ notifyEvent({
859
+ type: 'dp.change',
860
+ date: false,
861
+ oldDate: oldDate
862
+ });
863
+ update();
864
+ return;
865
+ }
866
+
867
+ targetMoment = targetMoment.clone().locale(options.locale);
868
+
869
+ if (hasTimeZone()) {
870
+ targetMoment.tz(options.timeZone);
871
+ }
872
+
873
+ if (options.stepping !== 1) {
874
+ targetMoment.minutes((Math.round(targetMoment.minutes() / options.stepping) * options.stepping)).seconds(0);
875
+
876
+ while (options.minDate && targetMoment.isBefore(options.minDate)) {
877
+ targetMoment.add(options.stepping, 'minutes');
878
+ }
879
+ }
880
+
881
+ if (isValid(targetMoment)) {
882
+ date = targetMoment;
883
+ viewDate = date.clone();
884
+ input.val(date.format(actualFormat));
885
+ element.data('date', date.format(actualFormat));
886
+ unset = false;
887
+ update();
888
+ notifyEvent({
889
+ type: 'dp.change',
890
+ date: date.clone(),
891
+ oldDate: oldDate
892
+ });
893
+ } else {
894
+ if (!options.keepInvalid) {
895
+ input.val(unset ? '' : date.format(actualFormat));
896
+ } else {
897
+ notifyEvent({
898
+ type: 'dp.change',
899
+ date: targetMoment,
900
+ oldDate: oldDate
901
+ });
902
+ }
903
+ notifyEvent({
904
+ type: 'dp.error',
905
+ date: targetMoment,
906
+ oldDate: oldDate
907
+ });
908
+ }
909
+ },
910
+
911
+ /**
912
+ * Hides the widget. Possibly will emit dp.hide
913
+ */
914
+ hide = function () {
915
+ var transitioning = false;
916
+ if (!widget) {
917
+ return picker;
918
+ }
919
+ // Ignore event if in the middle of a picker transition
920
+ widget.find('.collapse').each(function () {
921
+ var collapseData = $(this).data('collapse');
922
+ if (collapseData && collapseData.transitioning) {
923
+ transitioning = true;
924
+ return false;
925
+ }
926
+ return true;
927
+ });
928
+ if (transitioning) {
929
+ return picker;
930
+ }
931
+ if (component && component.hasClass('btn')) {
932
+ component.toggleClass('active');
933
+ }
934
+ widget.hide();
935
+
936
+ $(window).off('resize', place);
937
+ widget.off('click', '[data-action]');
938
+ widget.off('mousedown', false);
939
+
940
+ widget.remove();
941
+ widget = false;
942
+
943
+ notifyEvent({
944
+ type: 'dp.hide',
945
+ date: date.clone()
946
+ });
947
+
948
+ input.blur();
949
+
950
+ viewDate = date.clone();
951
+
952
+ return picker;
953
+ },
954
+
955
+ clear = function () {
956
+ setValue(null);
957
+ },
958
+
959
+ parseInputDate = function (inputDate) {
960
+ if (options.parseInputDate === undefined) {
961
+ if (!moment.isMoment(inputDate) || inputDate instanceof Date) {
962
+ inputDate = getMoment(inputDate);
963
+ }
964
+ } else {
965
+ inputDate = options.parseInputDate(inputDate);
966
+ }
967
+ //inputDate.locale(options.locale);
968
+ return inputDate;
969
+ },
970
+
971
+ /********************************************************************************
972
+ *
973
+ * Widget UI interaction functions
974
+ *
975
+ ********************************************************************************/
976
+ actions = {
977
+ next: function () {
978
+ var navFnc = datePickerModes[currentViewMode].navFnc;
979
+ viewDate.add(datePickerModes[currentViewMode].navStep, navFnc);
980
+ fillDate();
981
+ viewUpdate(navFnc);
982
+ },
983
+
984
+ previous: function () {
985
+ var navFnc = datePickerModes[currentViewMode].navFnc;
986
+ viewDate.subtract(datePickerModes[currentViewMode].navStep, navFnc);
987
+ fillDate();
988
+ viewUpdate(navFnc);
989
+ },
990
+
991
+ pickerSwitch: function () {
992
+ showMode(1);
993
+ },
994
+
995
+ selectMonth: function (e) {
996
+ var month = $(e.target).closest('tbody').find('span').index($(e.target));
997
+ viewDate.month(month);
998
+ if (currentViewMode === minViewModeNumber) {
999
+ setValue(date.clone().year(viewDate.year()).month(viewDate.month()));
1000
+ if (!options.inline) {
1001
+ hide();
1002
+ }
1003
+ } else {
1004
+ showMode(-1);
1005
+ fillDate();
1006
+ }
1007
+ viewUpdate('M');
1008
+ },
1009
+
1010
+ selectYear: function (e) {
1011
+ var year = parseInt($(e.target).text(), 10) || 0;
1012
+ viewDate.year(year);
1013
+ if (currentViewMode === minViewModeNumber) {
1014
+ setValue(date.clone().year(viewDate.year()));
1015
+ if (!options.inline) {
1016
+ hide();
1017
+ }
1018
+ } else {
1019
+ showMode(-1);
1020
+ fillDate();
1021
+ }
1022
+ viewUpdate('YYYY');
1023
+ },
1024
+
1025
+ selectDecade: function (e) {
1026
+ var year = parseInt($(e.target).data('selection'), 10) || 0;
1027
+ viewDate.year(year);
1028
+ if (currentViewMode === minViewModeNumber) {
1029
+ setValue(date.clone().year(viewDate.year()));
1030
+ if (!options.inline) {
1031
+ hide();
1032
+ }
1033
+ } else {
1034
+ showMode(-1);
1035
+ fillDate();
1036
+ }
1037
+ viewUpdate('YYYY');
1038
+ },
1039
+
1040
+ selectDay: function (e) {
1041
+ var day = viewDate.clone();
1042
+ if ($(e.target).is('.old')) {
1043
+ day.subtract(1, 'M');
1044
+ }
1045
+ if ($(e.target).is('.new')) {
1046
+ day.add(1, 'M');
1047
+ }
1048
+ setValue(day.date(parseInt($(e.target).text(), 10)));
1049
+ if (!hasTime() && !options.keepOpen && !options.inline) {
1050
+ hide();
1051
+ }
1052
+ },
1053
+
1054
+ incrementHours: function () {
1055
+ var newDate = date.clone().add(1, 'h');
1056
+ if (isValid(newDate, 'h')) {
1057
+ setValue(newDate);
1058
+ }
1059
+ },
1060
+
1061
+ incrementMinutes: function () {
1062
+ var newDate = date.clone().add(options.stepping, 'm');
1063
+ if (isValid(newDate, 'm')) {
1064
+ setValue(newDate);
1065
+ }
1066
+ },
1067
+
1068
+ incrementSeconds: function () {
1069
+ var newDate = date.clone().add(1, 's');
1070
+ if (isValid(newDate, 's')) {
1071
+ setValue(newDate);
1072
+ }
1073
+ },
1074
+
1075
+ decrementHours: function () {
1076
+ var newDate = date.clone().subtract(1, 'h');
1077
+ if (isValid(newDate, 'h')) {
1078
+ setValue(newDate);
1079
+ }
1080
+ },
1081
+
1082
+ decrementMinutes: function () {
1083
+ var newDate = date.clone().subtract(options.stepping, 'm');
1084
+ if (isValid(newDate, 'm')) {
1085
+ setValue(newDate);
1086
+ }
1087
+ },
1088
+
1089
+ decrementSeconds: function () {
1090
+ var newDate = date.clone().subtract(1, 's');
1091
+ if (isValid(newDate, 's')) {
1092
+ setValue(newDate);
1093
+ }
1094
+ },
1095
+
1096
+ togglePeriod: function () {
1097
+ setValue(date.clone().add((date.hours() >= 12) ? -12 : 12, 'h'));
1098
+ },
1099
+
1100
+ togglePicker: function (e) {
1101
+ var $this = $(e.target),
1102
+ $parent = $this.closest('ul'),
1103
+ expanded = $parent.find('.show'),
1104
+ closed = $parent.find('.collapse:not(.show)'),
1105
+ collapseData;
1106
+
1107
+ if (expanded && expanded.length) {
1108
+ collapseData = expanded.data('collapse');
1109
+ if (collapseData && collapseData.transitioning) {
1110
+ return;
1111
+ }
1112
+ if (expanded.collapse) { // if collapse plugin is available through bootstrap.js then use it
1113
+ expanded.collapse('hide');
1114
+ closed.collapse('show');
1115
+ } else { // otherwise just toggle in class on the two views
1116
+ expanded.removeClass('show');
1117
+ closed.addClass('show');
1118
+ }
1119
+ if ($this.is('span')) {
1120
+ $this.toggleClass(options.icons.time + ' ' + options.icons.date);
1121
+ } else {
1122
+ $this.find('span').toggleClass(options.icons.time + ' ' + options.icons.date);
1123
+ }
1124
+
1125
+ // NOTE: uncomment if toggled state will be restored in show()
1126
+ //if (component) {
1127
+ // component.find('span').toggleClass(options.icons.time + ' ' + options.icons.date);
1128
+ //}
1129
+ }
1130
+ },
1131
+
1132
+ showPicker: function () {
1133
+ widget.find('.timepicker > div:not(.timepicker-picker)').hide();
1134
+ widget.find('.timepicker .timepicker-picker').show();
1135
+ },
1136
+
1137
+ showHours: function () {
1138
+ widget.find('.timepicker .timepicker-picker').hide();
1139
+ widget.find('.timepicker .timepicker-hours').show();
1140
+ },
1141
+
1142
+ showMinutes: function () {
1143
+ widget.find('.timepicker .timepicker-picker').hide();
1144
+ widget.find('.timepicker .timepicker-minutes').show();
1145
+ },
1146
+
1147
+ showSeconds: function () {
1148
+ widget.find('.timepicker .timepicker-picker').hide();
1149
+ widget.find('.timepicker .timepicker-seconds').show();
1150
+ },
1151
+
1152
+ selectHour: function (e) {
1153
+ var hour = parseInt($(e.target).text(), 10);
1154
+
1155
+ if (!use24Hours) {
1156
+ if (date.hours() >= 12) {
1157
+ if (hour !== 12) {
1158
+ hour += 12;
1159
+ }
1160
+ } else {
1161
+ if (hour === 12) {
1162
+ hour = 0;
1163
+ }
1164
+ }
1165
+ }
1166
+ setValue(date.clone().hours(hour));
1167
+ actions.showPicker.call(picker);
1168
+ },
1169
+
1170
+ selectMinute: function (e) {
1171
+ setValue(date.clone().minutes(parseInt($(e.target).text(), 10)));
1172
+ actions.showPicker.call(picker);
1173
+ },
1174
+
1175
+ selectSecond: function (e) {
1176
+ setValue(date.clone().seconds(parseInt($(e.target).text(), 10)));
1177
+ actions.showPicker.call(picker);
1178
+ },
1179
+
1180
+ clear: clear,
1181
+
1182
+ today: function () {
1183
+ var todaysDate = getMoment();
1184
+ if (isValid(todaysDate, 'd')) {
1185
+ setValue(todaysDate);
1186
+ }
1187
+ },
1188
+
1189
+ close: hide
1190
+ },
1191
+
1192
+ doAction = function (e) {
1193
+ if ($(e.currentTarget).is('.disabled')) {
1194
+ return false;
1195
+ }
1196
+ actions[$(e.currentTarget).data('action')].apply(picker, arguments);
1197
+ return false;
1198
+ },
1199
+
1200
+ /**
1201
+ * Shows the widget. Possibly will emit dp.show and dp.change
1202
+ */
1203
+ show = function () {
1204
+ var currentMoment,
1205
+ useCurrentGranularity = {
1206
+ 'year': function (m) {
1207
+ return m.month(0).date(1).hours(0).seconds(0).minutes(0);
1208
+ },
1209
+ 'month': function (m) {
1210
+ return m.date(1).hours(0).seconds(0).minutes(0);
1211
+ },
1212
+ 'day': function (m) {
1213
+ return m.hours(0).seconds(0).minutes(0);
1214
+ },
1215
+ 'hour': function (m) {
1216
+ return m.seconds(0).minutes(0);
1217
+ },
1218
+ 'minute': function (m) {
1219
+ return m.seconds(0);
1220
+ }
1221
+ };
1222
+
1223
+ if (input.prop('disabled') || (!options.ignoreReadonly && input.prop('readonly')) || widget) {
1224
+ return picker;
1225
+ }
1226
+ if (input.val() !== undefined && input.val().trim().length !== 0) {
1227
+ setValue(parseInputDate(input.val().trim()));
1228
+ } else if (unset && options.useCurrent && (options.inline || (input.is('input') && input.val().trim().length === 0))) {
1229
+ currentMoment = getMoment();
1230
+ if (typeof options.useCurrent === 'string') {
1231
+ currentMoment = useCurrentGranularity[options.useCurrent](currentMoment);
1232
+ }
1233
+ setValue(currentMoment);
1234
+ }
1235
+ widget = getTemplate();
1236
+
1237
+ fillDow();
1238
+ fillMonths();
1239
+
1240
+ widget.find('.timepicker-hours').hide();
1241
+ widget.find('.timepicker-minutes').hide();
1242
+ widget.find('.timepicker-seconds').hide();
1243
+
1244
+ update();
1245
+ showMode();
1246
+
1247
+ $(window).on('resize', place);
1248
+ widget.on('click', '[data-action]', doAction); // this handles clicks on the widget
1249
+ widget.on('mousedown', false);
1250
+
1251
+ if (component && component.hasClass('btn')) {
1252
+ component.toggleClass('active');
1253
+ }
1254
+ place();
1255
+ widget.show();
1256
+ if (options.focusOnShow && !input.is(':focus')) {
1257
+ input.focus();
1258
+ }
1259
+
1260
+ notifyEvent({
1261
+ type: 'dp.show'
1262
+ });
1263
+ return picker;
1264
+ },
1265
+
1266
+ /**
1267
+ * Shows or hides the widget
1268
+ */
1269
+ toggle = function () {
1270
+ return (widget ? hide() : show());
1271
+ },
1272
+
1273
+ keydown = function (e) {
1274
+ var handler = null,
1275
+ index,
1276
+ index2,
1277
+ pressedKeys = [],
1278
+ pressedModifiers = {},
1279
+ currentKey = e.which,
1280
+ keyBindKeys,
1281
+ allModifiersPressed,
1282
+ pressed = 'p';
1283
+
1284
+ keyState[currentKey] = pressed;
1285
+
1286
+ for (index in keyState) {
1287
+ if (keyState.hasOwnProperty(index) && keyState[index] === pressed) {
1288
+ pressedKeys.push(index);
1289
+ if (parseInt(index, 10) !== currentKey) {
1290
+ pressedModifiers[index] = true;
1291
+ }
1292
+ }
1293
+ }
1294
+
1295
+ for (index in options.keyBinds) {
1296
+ if (options.keyBinds.hasOwnProperty(index) && typeof (options.keyBinds[index]) === 'function') {
1297
+ keyBindKeys = index.split(' ');
1298
+ if (keyBindKeys.length === pressedKeys.length && keyMap[currentKey] === keyBindKeys[keyBindKeys.length - 1]) {
1299
+ allModifiersPressed = true;
1300
+ for (index2 = keyBindKeys.length - 2; index2 >= 0; index2--) {
1301
+ if (!(keyMap[keyBindKeys[index2]] in pressedModifiers)) {
1302
+ allModifiersPressed = false;
1303
+ break;
1304
+ }
1305
+ }
1306
+ if (allModifiersPressed) {
1307
+ handler = options.keyBinds[index];
1308
+ break;
1309
+ }
1310
+ }
1311
+ }
1312
+ }
1313
+
1314
+ if (handler) {
1315
+ handler.call(picker, widget);
1316
+ e.stopPropagation();
1317
+ e.preventDefault();
1318
+ }
1319
+ },
1320
+
1321
+ keyup = function (e) {
1322
+ keyState[e.which] = 'r';
1323
+ e.stopPropagation();
1324
+ e.preventDefault();
1325
+ },
1326
+
1327
+ change = function (e) {
1328
+ var val = $(e.target).val().trim(),
1329
+ parsedDate = val ? parseInputDate(val) : null;
1330
+ setValue(parsedDate);
1331
+ e.stopImmediatePropagation();
1332
+ return false;
1333
+ },
1334
+
1335
+ attachDatePickerElementEvents = function () {
1336
+ input.on({
1337
+ 'change': change,
1338
+ 'blur': options.debug ? '' : hide,
1339
+ 'keydown': keydown,
1340
+ 'keyup': keyup,
1341
+ 'focus': options.allowInputToggle ? show : ''
1342
+ });
1343
+
1344
+ if (element.is('input')) {
1345
+ input.on({
1346
+ 'focus': show
1347
+ });
1348
+ } else if (component) {
1349
+ component.on('click', toggle);
1350
+ component.on('mousedown', false);
1351
+ }
1352
+ },
1353
+
1354
+ detachDatePickerElementEvents = function () {
1355
+ input.off({
1356
+ 'change': change,
1357
+ 'blur': blur,
1358
+ 'keydown': keydown,
1359
+ 'keyup': keyup,
1360
+ 'focus': options.allowInputToggle ? hide : ''
1361
+ });
1362
+
1363
+ if (element.is('input')) {
1364
+ input.off({
1365
+ 'focus': show
1366
+ });
1367
+ } else if (component) {
1368
+ component.off('click', toggle);
1369
+ component.off('mousedown', false);
1370
+ }
1371
+ },
1372
+
1373
+ indexGivenDates = function (givenDatesArray) {
1374
+ // Store given enabledDates and disabledDates as keys.
1375
+ // This way we can check their existence in O(1) time instead of looping through whole array.
1376
+ // (for example: options.enabledDates['2014-02-27'] === true)
1377
+ var givenDatesIndexed = {};
1378
+ $.each(givenDatesArray, function () {
1379
+ var dDate = parseInputDate(this);
1380
+ if (dDate.isValid()) {
1381
+ givenDatesIndexed[dDate.format('YYYY-MM-DD')] = true;
1382
+ }
1383
+ });
1384
+ return (Object.keys(givenDatesIndexed).length) ? givenDatesIndexed : false;
1385
+ },
1386
+
1387
+ indexGivenHours = function (givenHoursArray) {
1388
+ // Store given enabledHours and disabledHours as keys.
1389
+ // This way we can check their existence in O(1) time instead of looping through whole array.
1390
+ // (for example: options.enabledHours['2014-02-27'] === true)
1391
+ var givenHoursIndexed = {};
1392
+ $.each(givenHoursArray, function () {
1393
+ givenHoursIndexed[this] = true;
1394
+ });
1395
+ return (Object.keys(givenHoursIndexed).length) ? givenHoursIndexed : false;
1396
+ },
1397
+
1398
+ initFormatting = function () {
1399
+ var format = options.format || 'L LT';
1400
+
1401
+ actualFormat = format.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput) {
1402
+ var newinput = date.localeData().longDateFormat(formatInput) || formatInput;
1403
+ return newinput.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput2) { //temp fix for #740
1404
+ return date.localeData().longDateFormat(formatInput2) || formatInput2;
1405
+ });
1406
+ });
1407
+
1408
+
1409
+ parseFormats = options.extraFormats ? options.extraFormats.slice() : [];
1410
+ if (parseFormats.indexOf(format) < 0 && parseFormats.indexOf(actualFormat) < 0) {
1411
+ parseFormats.push(actualFormat);
1412
+ }
1413
+
1414
+ use24Hours = (actualFormat.toLowerCase().indexOf('a') < 1 && actualFormat.replace(/\[.*?\]/g, '').indexOf('h') < 1);
1415
+
1416
+ if (isEnabled('y')) {
1417
+ minViewModeNumber = 2;
1418
+ }
1419
+ if (isEnabled('M')) {
1420
+ minViewModeNumber = 1;
1421
+ }
1422
+ if (isEnabled('d')) {
1423
+ minViewModeNumber = 0;
1424
+ }
1425
+
1426
+ currentViewMode = Math.max(minViewModeNumber, currentViewMode);
1427
+
1428
+ if (!unset) {
1429
+ setValue(date);
1430
+ }
1431
+ };
1432
+
1433
+ /********************************************************************************
1434
+ *
1435
+ * Public API functions
1436
+ * =====================
1437
+ *
1438
+ * Important: Do not expose direct references to private objects or the options
1439
+ * object to the outer world. Always return a clone when returning values or make
1440
+ * a clone when setting a private variable.
1441
+ *
1442
+ ********************************************************************************/
1443
+ picker.destroy = function () {
1444
+ ///<summary>Destroys the widget and removes all attached event listeners</summary>
1445
+ hide();
1446
+ detachDatePickerElementEvents();
1447
+ element.removeData('DateTimePicker');
1448
+ element.removeData('date');
1449
+ };
1450
+
1451
+ picker.toggle = toggle;
1452
+
1453
+ picker.show = show;
1454
+
1455
+ picker.hide = hide;
1456
+
1457
+ picker.disable = function () {
1458
+ ///<summary>Disables the input element, the component is attached to, by adding a disabled="true" attribute to it.
1459
+ ///If the widget was visible before that call it is hidden. Possibly emits dp.hide</summary>
1460
+ hide();
1461
+ if (component && component.hasClass('btn')) {
1462
+ component.addClass('disabled');
1463
+ }
1464
+ input.prop('disabled', true);
1465
+ return picker;
1466
+ };
1467
+
1468
+ picker.enable = function () {
1469
+ ///<summary>Enables the input element, the component is attached to, by removing disabled attribute from it.</summary>
1470
+ if (component && component.hasClass('btn')) {
1471
+ component.removeClass('disabled');
1472
+ }
1473
+ input.prop('disabled', false);
1474
+ return picker;
1475
+ };
1476
+
1477
+ picker.ignoreReadonly = function (ignoreReadonly) {
1478
+ if (arguments.length === 0) {
1479
+ return options.ignoreReadonly;
1480
+ }
1481
+ if (typeof ignoreReadonly !== 'boolean') {
1482
+ throw new TypeError('ignoreReadonly () expects a boolean parameter');
1483
+ }
1484
+ options.ignoreReadonly = ignoreReadonly;
1485
+ return picker;
1486
+ };
1487
+
1488
+ picker.options = function (newOptions) {
1489
+ if (arguments.length === 0) {
1490
+ return $.extend(true, {}, options);
1491
+ }
1492
+
1493
+ if (!(newOptions instanceof Object)) {
1494
+ throw new TypeError('options() options parameter should be an object');
1495
+ }
1496
+ $.extend(true, options, newOptions);
1497
+ $.each(options, function (key, value) {
1498
+ if (picker[key] !== undefined) {
1499
+ picker[key](value);
1500
+ } else {
1501
+ throw new TypeError('option ' + key + ' is not recognized!');
1502
+ }
1503
+ });
1504
+ return picker;
1505
+ };
1506
+
1507
+ picker.date = function (newDate) {
1508
+ ///<signature helpKeyword="$.fn.datetimepicker.date">
1509
+ ///<summary>Returns the component's model current date, a moment object or null if not set.</summary>
1510
+ ///<returns type="Moment">date.clone()</returns>
1511
+ ///</signature>
1512
+ ///<signature>
1513
+ ///<summary>Sets the components model current moment to it. Passing a null value unsets the components model current moment. Parsing of the newDate parameter is made using moment library with the options.format and options.useStrict components configuration.</summary>
1514
+ ///<param name="newDate" locid="$.fn.datetimepicker.date_p:newDate">Takes string, Date, moment, null parameter.</param>
1515
+ ///</signature>
1516
+ if (arguments.length === 0) {
1517
+ if (unset) {
1518
+ return null;
1519
+ }
1520
+ return date.clone();
1521
+ }
1522
+
1523
+ if (newDate !== null && typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) {
1524
+ throw new TypeError('date() parameter must be one of [null, string, moment or Date]');
1525
+ }
1526
+
1527
+ setValue(newDate === null ? null : parseInputDate(newDate));
1528
+ return picker;
1529
+ };
1530
+
1531
+ picker.format = function (newFormat) {
1532
+ ///<summary>test su</summary>
1533
+ ///<param name="newFormat">info about para</param>
1534
+ ///<returns type="string|boolean">returns foo</returns>
1535
+ if (arguments.length === 0) {
1536
+ return options.format;
1537
+ }
1538
+
1539
+ if ((typeof newFormat !== 'string') && ((typeof newFormat !== 'boolean') || (newFormat !== false))) {
1540
+ throw new TypeError('format() expects a string or boolean:false parameter ' + newFormat);
1541
+ }
1542
+
1543
+ options.format = newFormat;
1544
+ if (actualFormat) {
1545
+ initFormatting(); // reinit formatting
1546
+ }
1547
+ return picker;
1548
+ };
1549
+
1550
+ picker.timeZone = function (newZone) {
1551
+ if (arguments.length === 0) {
1552
+ return options.timeZone;
1553
+ }
1554
+
1555
+ if (typeof newZone !== 'string') {
1556
+ throw new TypeError('newZone() expects a string parameter');
1557
+ }
1558
+
1559
+ options.timeZone = newZone;
1560
+
1561
+ return picker;
1562
+ };
1563
+
1564
+ picker.dayViewHeaderFormat = function (newFormat) {
1565
+ if (arguments.length === 0) {
1566
+ return options.dayViewHeaderFormat;
1567
+ }
1568
+
1569
+ if (typeof newFormat !== 'string') {
1570
+ throw new TypeError('dayViewHeaderFormat() expects a string parameter');
1571
+ }
1572
+
1573
+ options.dayViewHeaderFormat = newFormat;
1574
+ return picker;
1575
+ };
1576
+
1577
+ picker.extraFormats = function (formats) {
1578
+ if (arguments.length === 0) {
1579
+ return options.extraFormats;
1580
+ }
1581
+
1582
+ if (formats !== false && !(formats instanceof Array)) {
1583
+ throw new TypeError('extraFormats() expects an array or false parameter');
1584
+ }
1585
+
1586
+ options.extraFormats = formats;
1587
+ if (parseFormats) {
1588
+ initFormatting(); // reinit formatting
1589
+ }
1590
+ return picker;
1591
+ };
1592
+
1593
+ picker.disabledDates = function (dates) {
1594
+ ///<signature helpKeyword="$.fn.datetimepicker.disabledDates">
1595
+ ///<summary>Returns an array with the currently set disabled dates on the component.</summary>
1596
+ ///<returns type="array">options.disabledDates</returns>
1597
+ ///</signature>
1598
+ ///<signature>
1599
+ ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of
1600
+ ///options.enabledDates if such exist.</summary>
1601
+ ///<param name="dates" locid="$.fn.datetimepicker.disabledDates_p:dates">Takes an [ string or Date or moment ] of values and allows the user to select only from those days.</param>
1602
+ ///</signature>
1603
+ if (arguments.length === 0) {
1604
+ return (options.disabledDates ? $.extend({}, options.disabledDates) : options.disabledDates);
1605
+ }
1606
+
1607
+ if (!dates) {
1608
+ options.disabledDates = false;
1609
+ update();
1610
+ return picker;
1611
+ }
1612
+ if (!(dates instanceof Array)) {
1613
+ throw new TypeError('disabledDates() expects an array parameter');
1614
+ }
1615
+ options.disabledDates = indexGivenDates(dates);
1616
+ options.enabledDates = false;
1617
+ update();
1618
+ return picker;
1619
+ };
1620
+
1621
+ picker.enabledDates = function (dates) {
1622
+ ///<signature helpKeyword="$.fn.datetimepicker.enabledDates">
1623
+ ///<summary>Returns an array with the currently set enabled dates on the component.</summary>
1624
+ ///<returns type="array">options.enabledDates</returns>
1625
+ ///</signature>
1626
+ ///<signature>
1627
+ ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of options.disabledDates if such exist.</summary>
1628
+ ///<param name="dates" locid="$.fn.datetimepicker.enabledDates_p:dates">Takes an [ string or Date or moment ] of values and allows the user to select only from those days.</param>
1629
+ ///</signature>
1630
+ if (arguments.length === 0) {
1631
+ return (options.enabledDates ? $.extend({}, options.enabledDates) : options.enabledDates);
1632
+ }
1633
+
1634
+ if (!dates) {
1635
+ options.enabledDates = false;
1636
+ update();
1637
+ return picker;
1638
+ }
1639
+ if (!(dates instanceof Array)) {
1640
+ throw new TypeError('enabledDates() expects an array parameter');
1641
+ }
1642
+ options.enabledDates = indexGivenDates(dates);
1643
+ options.disabledDates = false;
1644
+ update();
1645
+ return picker;
1646
+ };
1647
+
1648
+ picker.daysOfWeekDisabled = function (daysOfWeekDisabled) {
1649
+ if (arguments.length === 0) {
1650
+ return options.daysOfWeekDisabled.splice(0);
1651
+ }
1652
+
1653
+ if ((typeof daysOfWeekDisabled === 'boolean') && !daysOfWeekDisabled) {
1654
+ options.daysOfWeekDisabled = false;
1655
+ update();
1656
+ return picker;
1657
+ }
1658
+
1659
+ if (!(daysOfWeekDisabled instanceof Array)) {
1660
+ throw new TypeError('daysOfWeekDisabled() expects an array parameter');
1661
+ }
1662
+ options.daysOfWeekDisabled = daysOfWeekDisabled.reduce(function (previousValue, currentValue) {
1663
+ currentValue = parseInt(currentValue, 10);
1664
+ if (currentValue > 6 || currentValue < 0 || isNaN(currentValue)) {
1665
+ return previousValue;
1666
+ }
1667
+ if (previousValue.indexOf(currentValue) === -1) {
1668
+ previousValue.push(currentValue);
1669
+ }
1670
+ return previousValue;
1671
+ }, []).sort();
1672
+ if (options.useCurrent && !options.keepInvalid) {
1673
+ var tries = 0;
1674
+ while (!isValid(date, 'd')) {
1675
+ date.add(1, 'd');
1676
+ if (tries === 31) {
1677
+ throw 'Tried 31 times to find a valid date';
1678
+ }
1679
+ tries++;
1680
+ }
1681
+ setValue(date);
1682
+ }
1683
+ update();
1684
+ return picker;
1685
+ };
1686
+
1687
+ picker.maxDate = function (maxDate) {
1688
+ if (arguments.length === 0) {
1689
+ return options.maxDate ? options.maxDate.clone() : options.maxDate;
1690
+ }
1691
+
1692
+ if ((typeof maxDate === 'boolean') && maxDate === false) {
1693
+ options.maxDate = false;
1694
+ update();
1695
+ return picker;
1696
+ }
1697
+
1698
+ if (typeof maxDate === 'string') {
1699
+ if (maxDate === 'now' || maxDate === 'moment') {
1700
+ maxDate = getMoment();
1701
+ }
1702
+ }
1703
+
1704
+ var parsedDate = parseInputDate(maxDate);
1705
+
1706
+ if (!parsedDate.isValid()) {
1707
+ throw new TypeError('maxDate() Could not parse date parameter: ' + maxDate);
1708
+ }
1709
+ if (options.minDate && parsedDate.isBefore(options.minDate)) {
1710
+ throw new TypeError('maxDate() date parameter is before options.minDate: ' + parsedDate.format(actualFormat));
1711
+ }
1712
+ options.maxDate = parsedDate;
1713
+ if (options.useCurrent && !options.keepInvalid && date.isAfter(maxDate)) {
1714
+ setValue(options.maxDate);
1715
+ }
1716
+ if (viewDate.isAfter(parsedDate)) {
1717
+ viewDate = parsedDate.clone().subtract(options.stepping, 'm');
1718
+ }
1719
+ update();
1720
+ return picker;
1721
+ };
1722
+
1723
+ picker.minDate = function (minDate) {
1724
+ if (arguments.length === 0) {
1725
+ return options.minDate ? options.minDate.clone() : options.minDate;
1726
+ }
1727
+
1728
+ if ((typeof minDate === 'boolean') && minDate === false) {
1729
+ options.minDate = false;
1730
+ update();
1731
+ return picker;
1732
+ }
1733
+
1734
+ if (typeof minDate === 'string') {
1735
+ if (minDate === 'now' || minDate === 'moment') {
1736
+ minDate = getMoment();
1737
+ }
1738
+ }
1739
+
1740
+ var parsedDate = parseInputDate(minDate);
1741
+
1742
+ if (!parsedDate.isValid()) {
1743
+ throw new TypeError('minDate() Could not parse date parameter: ' + minDate);
1744
+ }
1745
+ if (options.maxDate && parsedDate.isAfter(options.maxDate)) {
1746
+ throw new TypeError('minDate() date parameter is after options.maxDate: ' + parsedDate.format(actualFormat));
1747
+ }
1748
+ options.minDate = parsedDate;
1749
+ if (options.useCurrent && !options.keepInvalid && date.isBefore(minDate)) {
1750
+ setValue(options.minDate);
1751
+ }
1752
+ if (viewDate.isBefore(parsedDate)) {
1753
+ viewDate = parsedDate.clone().add(options.stepping, 'm');
1754
+ }
1755
+ update();
1756
+ return picker;
1757
+ };
1758
+
1759
+ picker.defaultDate = function (defaultDate) {
1760
+ ///<signature helpKeyword="$.fn.datetimepicker.defaultDate">
1761
+ ///<summary>Returns a moment with the options.defaultDate option configuration or false if not set</summary>
1762
+ ///<returns type="Moment">date.clone()</returns>
1763
+ ///</signature>
1764
+ ///<signature>
1765
+ ///<summary>Will set the picker's inital date. If a boolean:false value is passed the options.defaultDate parameter is cleared.</summary>
1766
+ ///<param name="defaultDate" locid="$.fn.datetimepicker.defaultDate_p:defaultDate">Takes a string, Date, moment, boolean:false</param>
1767
+ ///</signature>
1768
+ if (arguments.length === 0) {
1769
+ return options.defaultDate ? options.defaultDate.clone() : options.defaultDate;
1770
+ }
1771
+ if (!defaultDate) {
1772
+ options.defaultDate = false;
1773
+ return picker;
1774
+ }
1775
+
1776
+ if (typeof defaultDate === 'string') {
1777
+ if (defaultDate === 'now' || defaultDate === 'moment') {
1778
+ defaultDate = getMoment();
1779
+ } else {
1780
+ defaultDate = getMoment(defaultDate);
1781
+ }
1782
+ }
1783
+
1784
+ var parsedDate = parseInputDate(defaultDate);
1785
+ if (!parsedDate.isValid()) {
1786
+ throw new TypeError('defaultDate() Could not parse date parameter: ' + defaultDate);
1787
+ }
1788
+ if (!isValid(parsedDate)) {
1789
+ throw new TypeError('defaultDate() date passed is invalid according to component setup validations');
1790
+ }
1791
+
1792
+ options.defaultDate = parsedDate;
1793
+
1794
+ if ((options.defaultDate && options.inline) || input.val().trim() === '') {
1795
+ setValue(options.defaultDate);
1796
+ }
1797
+ return picker;
1798
+ };
1799
+
1800
+ picker.locale = function (locale) {
1801
+ if (arguments.length === 0) {
1802
+ return options.locale;
1803
+ }
1804
+
1805
+ if (!moment.localeData(locale)) {
1806
+ throw new TypeError('locale() locale ' + locale + ' is not loaded from moment locales!');
1807
+ }
1808
+
1809
+ options.locale = locale;
1810
+ date.locale(options.locale);
1811
+ viewDate.locale(options.locale);
1812
+
1813
+ if (actualFormat) {
1814
+ initFormatting(); // reinit formatting
1815
+ }
1816
+ if (widget) {
1817
+ hide();
1818
+ show();
1819
+ }
1820
+ return picker;
1821
+ };
1822
+
1823
+ picker.stepping = function (stepping) {
1824
+ if (arguments.length === 0) {
1825
+ return options.stepping;
1826
+ }
1827
+
1828
+ stepping = parseInt(stepping, 10);
1829
+ if (isNaN(stepping) || stepping < 1) {
1830
+ stepping = 1;
1831
+ }
1832
+ options.stepping = stepping;
1833
+ return picker;
1834
+ };
1835
+
1836
+ picker.useCurrent = function (useCurrent) {
1837
+ var useCurrentOptions = ['year', 'month', 'day', 'hour', 'minute'];
1838
+ if (arguments.length === 0) {
1839
+ return options.useCurrent;
1840
+ }
1841
+
1842
+ if ((typeof useCurrent !== 'boolean') && (typeof useCurrent !== 'string')) {
1843
+ throw new TypeError('useCurrent() expects a boolean or string parameter');
1844
+ }
1845
+ if (typeof useCurrent === 'string' && useCurrentOptions.indexOf(useCurrent.toLowerCase()) === -1) {
1846
+ throw new TypeError('useCurrent() expects a string parameter of ' + useCurrentOptions.join(', '));
1847
+ }
1848
+ options.useCurrent = useCurrent;
1849
+ return picker;
1850
+ };
1851
+
1852
+ picker.collapse = function (collapse) {
1853
+ if (arguments.length === 0) {
1854
+ return options.collapse;
1855
+ }
1856
+
1857
+ if (typeof collapse !== 'boolean') {
1858
+ throw new TypeError('collapse() expects a boolean parameter');
1859
+ }
1860
+ if (options.collapse === collapse) {
1861
+ return picker;
1862
+ }
1863
+ options.collapse = collapse;
1864
+ if (widget) {
1865
+ hide();
1866
+ show();
1867
+ }
1868
+ return picker;
1869
+ };
1870
+
1871
+ picker.icons = function (icons) {
1872
+ if (arguments.length === 0) {
1873
+ return $.extend({}, options.icons);
1874
+ }
1875
+
1876
+ if (!(icons instanceof Object)) {
1877
+ throw new TypeError('icons() expects parameter to be an Object');
1878
+ }
1879
+ $.extend(options.icons, icons);
1880
+ if (widget) {
1881
+ hide();
1882
+ show();
1883
+ }
1884
+ return picker;
1885
+ };
1886
+
1887
+ picker.tooltips = function (tooltips) {
1888
+ if (arguments.length === 0) {
1889
+ return $.extend({}, options.tooltips);
1890
+ }
1891
+
1892
+ if (!(tooltips instanceof Object)) {
1893
+ throw new TypeError('tooltips() expects parameter to be an Object');
1894
+ }
1895
+ $.extend(options.tooltips, tooltips);
1896
+ if (widget) {
1897
+ hide();
1898
+ show();
1899
+ }
1900
+ return picker;
1901
+ };
1902
+
1903
+ picker.useStrict = function (useStrict) {
1904
+ if (arguments.length === 0) {
1905
+ return options.useStrict;
1906
+ }
1907
+
1908
+ if (typeof useStrict !== 'boolean') {
1909
+ throw new TypeError('useStrict() expects a boolean parameter');
1910
+ }
1911
+ options.useStrict = useStrict;
1912
+ return picker;
1913
+ };
1914
+
1915
+ picker.sideBySide = function (sideBySide) {
1916
+ if (arguments.length === 0) {
1917
+ return options.sideBySide;
1918
+ }
1919
+
1920
+ if (typeof sideBySide !== 'boolean') {
1921
+ throw new TypeError('sideBySide() expects a boolean parameter');
1922
+ }
1923
+ options.sideBySide = sideBySide;
1924
+ if (widget) {
1925
+ hide();
1926
+ show();
1927
+ }
1928
+ return picker;
1929
+ };
1930
+
1931
+ picker.viewMode = function (viewMode) {
1932
+ if (arguments.length === 0) {
1933
+ return options.viewMode;
1934
+ }
1935
+
1936
+ if (typeof viewMode !== 'string') {
1937
+ throw new TypeError('viewMode() expects a string parameter');
1938
+ }
1939
+
1940
+ if (viewModes.indexOf(viewMode) === -1) {
1941
+ throw new TypeError('viewMode() parameter must be one of (' + viewModes.join(', ') + ') value');
1942
+ }
1943
+
1944
+ options.viewMode = viewMode;
1945
+ currentViewMode = Math.max(viewModes.indexOf(viewMode), minViewModeNumber);
1946
+
1947
+ showMode();
1948
+ return picker;
1949
+ };
1950
+
1951
+ picker.toolbarPlacement = function (toolbarPlacement) {
1952
+ if (arguments.length === 0) {
1953
+ return options.toolbarPlacement;
1954
+ }
1955
+
1956
+ if (typeof toolbarPlacement !== 'string') {
1957
+ throw new TypeError('toolbarPlacement() expects a string parameter');
1958
+ }
1959
+ if (toolbarPlacements.indexOf(toolbarPlacement) === -1) {
1960
+ throw new TypeError('toolbarPlacement() parameter must be one of (' + toolbarPlacements.join(', ') + ') value');
1961
+ }
1962
+ options.toolbarPlacement = toolbarPlacement;
1963
+
1964
+ if (widget) {
1965
+ hide();
1966
+ show();
1967
+ }
1968
+ return picker;
1969
+ };
1970
+
1971
+ picker.widgetPositioning = function (widgetPositioning) {
1972
+ if (arguments.length === 0) {
1973
+ return $.extend({}, options.widgetPositioning);
1974
+ }
1975
+
1976
+ if (({}).toString.call(widgetPositioning) !== '[object Object]') {
1977
+ throw new TypeError('widgetPositioning() expects an object variable');
1978
+ }
1979
+ if (widgetPositioning.horizontal) {
1980
+ if (typeof widgetPositioning.horizontal !== 'string') {
1981
+ throw new TypeError('widgetPositioning() horizontal variable must be a string');
1982
+ }
1983
+ widgetPositioning.horizontal = widgetPositioning.horizontal.toLowerCase();
1984
+ if (horizontalModes.indexOf(widgetPositioning.horizontal) === -1) {
1985
+ throw new TypeError('widgetPositioning() expects horizontal parameter to be one of (' + horizontalModes.join(', ') + ')');
1986
+ }
1987
+ options.widgetPositioning.horizontal = widgetPositioning.horizontal;
1988
+ }
1989
+ if (widgetPositioning.vertical) {
1990
+ if (typeof widgetPositioning.vertical !== 'string') {
1991
+ throw new TypeError('widgetPositioning() vertical variable must be a string');
1992
+ }
1993
+ widgetPositioning.vertical = widgetPositioning.vertical.toLowerCase();
1994
+ if (verticalModes.indexOf(widgetPositioning.vertical) === -1) {
1995
+ throw new TypeError('widgetPositioning() expects vertical parameter to be one of (' + verticalModes.join(', ') + ')');
1996
+ }
1997
+ options.widgetPositioning.vertical = widgetPositioning.vertical;
1998
+ }
1999
+ update();
2000
+ return picker;
2001
+ };
2002
+
2003
+ picker.calendarWeeks = function (calendarWeeks) {
2004
+ if (arguments.length === 0) {
2005
+ return options.calendarWeeks;
2006
+ }
2007
+
2008
+ if (typeof calendarWeeks !== 'boolean') {
2009
+ throw new TypeError('calendarWeeks() expects parameter to be a boolean value');
2010
+ }
2011
+
2012
+ options.calendarWeeks = calendarWeeks;
2013
+ update();
2014
+ return picker;
2015
+ };
2016
+
2017
+ picker.showTodayButton = function (showTodayButton) {
2018
+ if (arguments.length === 0) {
2019
+ return options.showTodayButton;
2020
+ }
2021
+
2022
+ if (typeof showTodayButton !== 'boolean') {
2023
+ throw new TypeError('showTodayButton() expects a boolean parameter');
2024
+ }
2025
+
2026
+ options.showTodayButton = showTodayButton;
2027
+ if (widget) {
2028
+ hide();
2029
+ show();
2030
+ }
2031
+ return picker;
2032
+ };
2033
+
2034
+ picker.showClear = function (showClear) {
2035
+ if (arguments.length === 0) {
2036
+ return options.showClear;
2037
+ }
2038
+
2039
+ if (typeof showClear !== 'boolean') {
2040
+ throw new TypeError('showClear() expects a boolean parameter');
2041
+ }
2042
+
2043
+ options.showClear = showClear;
2044
+ if (widget) {
2045
+ hide();
2046
+ show();
2047
+ }
2048
+ return picker;
2049
+ };
2050
+
2051
+ picker.widgetParent = function (widgetParent) {
2052
+ if (arguments.length === 0) {
2053
+ return options.widgetParent;
2054
+ }
2055
+
2056
+ if (typeof widgetParent === 'string') {
2057
+ widgetParent = $(widgetParent);
2058
+ }
2059
+
2060
+ if (widgetParent !== null && (typeof widgetParent !== 'string' && !(widgetParent instanceof $))) {
2061
+ throw new TypeError('widgetParent() expects a string or a jQuery object parameter');
2062
+ }
2063
+
2064
+ options.widgetParent = widgetParent;
2065
+ if (widget) {
2066
+ hide();
2067
+ show();
2068
+ }
2069
+ return picker;
2070
+ };
2071
+
2072
+ picker.keepOpen = function (keepOpen) {
2073
+ if (arguments.length === 0) {
2074
+ return options.keepOpen;
2075
+ }
2076
+
2077
+ if (typeof keepOpen !== 'boolean') {
2078
+ throw new TypeError('keepOpen() expects a boolean parameter');
2079
+ }
2080
+
2081
+ options.keepOpen = keepOpen;
2082
+ return picker;
2083
+ };
2084
+
2085
+ picker.focusOnShow = function (focusOnShow) {
2086
+ if (arguments.length === 0) {
2087
+ return options.focusOnShow;
2088
+ }
2089
+
2090
+ if (typeof focusOnShow !== 'boolean') {
2091
+ throw new TypeError('focusOnShow() expects a boolean parameter');
2092
+ }
2093
+
2094
+ options.focusOnShow = focusOnShow;
2095
+ return picker;
2096
+ };
2097
+
2098
+ picker.inline = function (inline) {
2099
+ if (arguments.length === 0) {
2100
+ return options.inline;
2101
+ }
2102
+
2103
+ if (typeof inline !== 'boolean') {
2104
+ throw new TypeError('inline() expects a boolean parameter');
2105
+ }
2106
+
2107
+ options.inline = inline;
2108
+ return picker;
2109
+ };
2110
+
2111
+ picker.clear = function () {
2112
+ clear();
2113
+ return picker;
2114
+ };
2115
+
2116
+ picker.keyBinds = function (keyBinds) {
2117
+ if (arguments.length === 0) {
2118
+ return options.keyBinds;
2119
+ }
2120
+
2121
+ options.keyBinds = keyBinds;
2122
+ return picker;
2123
+ };
2124
+
2125
+ picker.getMoment = function (d) {
2126
+ return getMoment(d);
2127
+ };
2128
+
2129
+ picker.debug = function (debug) {
2130
+ if (typeof debug !== 'boolean') {
2131
+ throw new TypeError('debug() expects a boolean parameter');
2132
+ }
2133
+
2134
+ options.debug = debug;
2135
+ return picker;
2136
+ };
2137
+
2138
+ picker.allowInputToggle = function (allowInputToggle) {
2139
+ if (arguments.length === 0) {
2140
+ return options.allowInputToggle;
2141
+ }
2142
+
2143
+ if (typeof allowInputToggle !== 'boolean') {
2144
+ throw new TypeError('allowInputToggle() expects a boolean parameter');
2145
+ }
2146
+
2147
+ options.allowInputToggle = allowInputToggle;
2148
+ return picker;
2149
+ };
2150
+
2151
+ picker.showClose = function (showClose) {
2152
+ if (arguments.length === 0) {
2153
+ return options.showClose;
2154
+ }
2155
+
2156
+ if (typeof showClose !== 'boolean') {
2157
+ throw new TypeError('showClose() expects a boolean parameter');
2158
+ }
2159
+
2160
+ options.showClose = showClose;
2161
+ return picker;
2162
+ };
2163
+
2164
+ picker.keepInvalid = function (keepInvalid) {
2165
+ if (arguments.length === 0) {
2166
+ return options.keepInvalid;
2167
+ }
2168
+
2169
+ if (typeof keepInvalid !== 'boolean') {
2170
+ throw new TypeError('keepInvalid() expects a boolean parameter');
2171
+ }
2172
+ options.keepInvalid = keepInvalid;
2173
+ return picker;
2174
+ };
2175
+
2176
+ picker.datepickerInput = function (datepickerInput) {
2177
+ if (arguments.length === 0) {
2178
+ return options.datepickerInput;
2179
+ }
2180
+
2181
+ if (typeof datepickerInput !== 'string') {
2182
+ throw new TypeError('datepickerInput() expects a string parameter');
2183
+ }
2184
+
2185
+ options.datepickerInput = datepickerInput;
2186
+ return picker;
2187
+ };
2188
+
2189
+ picker.parseInputDate = function (parseInputDate) {
2190
+ if (arguments.length === 0) {
2191
+ return options.parseInputDate;
2192
+ }
2193
+
2194
+ if (typeof parseInputDate !== 'function') {
2195
+ throw new TypeError('parseInputDate() sholud be as function');
2196
+ }
2197
+
2198
+ options.parseInputDate = parseInputDate;
2199
+
2200
+ return picker;
2201
+ };
2202
+
2203
+ picker.disabledTimeIntervals = function (disabledTimeIntervals) {
2204
+ ///<signature helpKeyword="$.fn.datetimepicker.disabledTimeIntervals">
2205
+ ///<summary>Returns an array with the currently set disabled dates on the component.</summary>
2206
+ ///<returns type="array">options.disabledTimeIntervals</returns>
2207
+ ///</signature>
2208
+ ///<signature>
2209
+ ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of
2210
+ ///options.enabledDates if such exist.</summary>
2211
+ ///<param name="dates" locid="$.fn.datetimepicker.disabledTimeIntervals_p:dates">Takes an [ string or Date or moment ] of values and allows the user to select only from those days.</param>
2212
+ ///</signature>
2213
+ if (arguments.length === 0) {
2214
+ return (options.disabledTimeIntervals ? $.extend({}, options.disabledTimeIntervals) : options.disabledTimeIntervals);
2215
+ }
2216
+
2217
+ if (!disabledTimeIntervals) {
2218
+ options.disabledTimeIntervals = false;
2219
+ update();
2220
+ return picker;
2221
+ }
2222
+ if (!(disabledTimeIntervals instanceof Array)) {
2223
+ throw new TypeError('disabledTimeIntervals() expects an array parameter');
2224
+ }
2225
+ options.disabledTimeIntervals = disabledTimeIntervals;
2226
+ update();
2227
+ return picker;
2228
+ };
2229
+
2230
+ picker.disabledHours = function (hours) {
2231
+ ///<signature helpKeyword="$.fn.datetimepicker.disabledHours">
2232
+ ///<summary>Returns an array with the currently set disabled hours on the component.</summary>
2233
+ ///<returns type="array">options.disabledHours</returns>
2234
+ ///</signature>
2235
+ ///<signature>
2236
+ ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of
2237
+ ///options.enabledHours if such exist.</summary>
2238
+ ///<param name="hours" locid="$.fn.datetimepicker.disabledHours_p:hours">Takes an [ int ] of values and disallows the user to select only from those hours.</param>
2239
+ ///</signature>
2240
+ if (arguments.length === 0) {
2241
+ return (options.disabledHours ? $.extend({}, options.disabledHours) : options.disabledHours);
2242
+ }
2243
+
2244
+ if (!hours) {
2245
+ options.disabledHours = false;
2246
+ update();
2247
+ return picker;
2248
+ }
2249
+ if (!(hours instanceof Array)) {
2250
+ throw new TypeError('disabledHours() expects an array parameter');
2251
+ }
2252
+ options.disabledHours = indexGivenHours(hours);
2253
+ options.enabledHours = false;
2254
+ if (options.useCurrent && !options.keepInvalid) {
2255
+ var tries = 0;
2256
+ while (!isValid(date, 'h')) {
2257
+ date.add(1, 'h');
2258
+ if (tries === 24) {
2259
+ throw 'Tried 24 times to find a valid date';
2260
+ }
2261
+ tries++;
2262
+ }
2263
+ setValue(date);
2264
+ }
2265
+ update();
2266
+ return picker;
2267
+ };
2268
+
2269
+ picker.enabledHours = function (hours) {
2270
+ ///<signature helpKeyword="$.fn.datetimepicker.enabledHours">
2271
+ ///<summary>Returns an array with the currently set enabled hours on the component.</summary>
2272
+ ///<returns type="array">options.enabledHours</returns>
2273
+ ///</signature>
2274
+ ///<signature>
2275
+ ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of options.disabledHours if such exist.</summary>
2276
+ ///<param name="hours" locid="$.fn.datetimepicker.enabledHours_p:hours">Takes an [ int ] of values and allows the user to select only from those hours.</param>
2277
+ ///</signature>
2278
+ if (arguments.length === 0) {
2279
+ return (options.enabledHours ? $.extend({}, options.enabledHours) : options.enabledHours);
2280
+ }
2281
+
2282
+ if (!hours) {
2283
+ options.enabledHours = false;
2284
+ update();
2285
+ return picker;
2286
+ }
2287
+ if (!(hours instanceof Array)) {
2288
+ throw new TypeError('enabledHours() expects an array parameter');
2289
+ }
2290
+ options.enabledHours = indexGivenHours(hours);
2291
+ options.disabledHours = false;
2292
+ if (options.useCurrent && !options.keepInvalid) {
2293
+ var tries = 0;
2294
+ while (!isValid(date, 'h')) {
2295
+ date.add(1, 'h');
2296
+ if (tries === 24) {
2297
+ throw 'Tried 24 times to find a valid date';
2298
+ }
2299
+ tries++;
2300
+ }
2301
+ setValue(date);
2302
+ }
2303
+ update();
2304
+ return picker;
2305
+ };
2306
+ /**
2307
+ * Returns the component's model current viewDate, a moment object or null if not set. Passing a null value unsets the components model current moment. Parsing of the newDate parameter is made using moment library with the options.format and options.useStrict components configuration.
2308
+ * @param {Takes string, viewDate, moment, null parameter.} newDate
2309
+ * @returns {viewDate.clone()}
2310
+ */
2311
+ picker.viewDate = function (newDate) {
2312
+ if (arguments.length === 0) {
2313
+ return viewDate.clone();
2314
+ }
2315
+
2316
+ if (!newDate) {
2317
+ viewDate = date.clone();
2318
+ return picker;
2319
+ }
2320
+
2321
+ if (typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) {
2322
+ throw new TypeError('viewDate() parameter must be one of [string, moment or Date]');
2323
+ }
2324
+
2325
+ viewDate = parseInputDate(newDate);
2326
+ viewUpdate();
2327
+ return picker;
2328
+ };
2329
+
2330
+ // initializing element and component attributes
2331
+ if (element.is('input')) {
2332
+ input = element;
2333
+ } else {
2334
+ input = element.find(options.datepickerInput);
2335
+ if (input.length === 0) {
2336
+ input = element.find('input');
2337
+ } else if (!input.is('input')) {
2338
+ throw new Error('CSS class "' + options.datepickerInput + '" cannot be applied to non input element');
2339
+ }
2340
+ }
2341
+
2342
+ if (element.hasClass('input-group')) {
2343
+ // in case there is more then one 'input-group-addon' Issue #48
2344
+ if (element.find('.datepickerbutton').length === 0) {
2345
+ component = element.find('.input-group-addon');
2346
+ } else {
2347
+ component = element.find('.datepickerbutton');
2348
+ }
2349
+ }
2350
+
2351
+ if (!options.inline && !input.is('input')) {
2352
+ throw new Error('Could not initialize DateTimePicker without an input element');
2353
+ }
2354
+
2355
+ // Set defaults for date here now instead of in var declaration
2356
+ date = getMoment();
2357
+ viewDate = date.clone();
2358
+
2359
+ $.extend(true, options, dataToOptions());
2360
+
2361
+ picker.options(options);
2362
+
2363
+ initFormatting();
2364
+
2365
+ attachDatePickerElementEvents();
2366
+
2367
+ if (input.prop('disabled')) {
2368
+ picker.disable();
2369
+ }
2370
+ if (input.is('input') && input.val().trim().length !== 0) {
2371
+ setValue(parseInputDate(input.val().trim()));
2372
+ }
2373
+ else if (options.defaultDate && input.attr('placeholder') === undefined) {
2374
+ setValue(options.defaultDate);
2375
+ }
2376
+ if (options.inline) {
2377
+ show();
2378
+ }
2379
+ return picker;
2380
+ };
2381
+
2382
+ /********************************************************************************
2383
+ *
2384
+ * jQuery plugin constructor and defaults object
2385
+ *
2386
+ ********************************************************************************/
2387
+
2388
+ /**
2389
+ * See (http://jquery.com/).
2390
+ * @name jQuery
2391
+ * @class
2392
+ * See the jQuery Library (http://jquery.com/) for full details. This just
2393
+ * documents the function and classes that are added to jQuery by this plug-in.
2394
+ */
2395
+ /**
2396
+ * See (http://jquery.com/)
2397
+ * @name fn
2398
+ * @class
2399
+ * See the jQuery Library (http://jquery.com/) for full details. This just
2400
+ * documents the function and classes that are added to jQuery by this plug-in.
2401
+ * @memberOf jQuery
2402
+ */
2403
+ /**
2404
+ * Show comments
2405
+ * @class datetimepicker
2406
+ * @memberOf jQuery.fn
2407
+ */
2408
+ $.fn.datetimepicker = function (options) {
2409
+ options = options || {};
2410
+
2411
+ var args = Array.prototype.slice.call(arguments, 1),
2412
+ isInstance = true,
2413
+ thisMethods = ['destroy', 'hide', 'show', 'toggle'],
2414
+ returnValue;
2415
+
2416
+ if (typeof options === 'object') {
2417
+ return this.each(function () {
2418
+ var $this = $(this),
2419
+ _options;
2420
+ if (!$this.data('DateTimePicker')) {
2421
+ // create a private copy of the defaults object
2422
+ _options = $.extend(true, {}, $.fn.datetimepicker.defaults, options);
2423
+ $this.data('DateTimePicker', dateTimePicker($this, _options));
2424
+ }
2425
+ });
2426
+ } else if (typeof options === 'string') {
2427
+ this.each(function () {
2428
+ var $this = $(this),
2429
+ instance = $this.data('DateTimePicker');
2430
+ if (!instance) {
2431
+ throw new Error('bootstrap-datetimepicker("' + options + '") method was called on an element that is not using DateTimePicker');
2432
+ }
2433
+
2434
+ returnValue = instance[options].apply(instance, args);
2435
+ isInstance = returnValue === instance;
2436
+ });
2437
+
2438
+ if (isInstance || $.inArray(options, thisMethods) > -1) {
2439
+ return this;
2440
+ }
2441
+
2442
+ return returnValue;
2443
+ }
2444
+
2445
+ throw new TypeError('Invalid arguments for DateTimePicker: ' + options);
2446
+ };
2447
+
2448
+ $.fn.datetimepicker.defaults = {
2449
+ timeZone: '',
2450
+ format: false,
2451
+ dayViewHeaderFormat: 'MMMM YYYY',
2452
+ extraFormats: false,
2453
+ stepping: 1,
2454
+ minDate: false,
2455
+ maxDate: false,
2456
+ useCurrent: true,
2457
+ collapse: true,
2458
+ locale: moment.locale(),
2459
+ defaultDate: false,
2460
+ disabledDates: false,
2461
+ enabledDates: false,
2462
+ icons: {
2463
+ time: 'glyphicon glyphicon-time',
2464
+ date: 'glyphicon glyphicon-calendar',
2465
+ up: 'glyphicon glyphicon-chevron-up',
2466
+ down: 'glyphicon glyphicon-chevron-down',
2467
+ previous: 'glyphicon glyphicon-chevron-left',
2468
+ next: 'glyphicon glyphicon-chevron-right',
2469
+ today: 'glyphicon glyphicon-screenshot',
2470
+ clear: 'glyphicon glyphicon-trash',
2471
+ close: 'glyphicon glyphicon-remove'
2472
+ },
2473
+ tooltips: {
2474
+ today: 'Go to today',
2475
+ clear: 'Clear selection',
2476
+ close: 'Close the picker',
2477
+ selectMonth: 'Select Month',
2478
+ prevMonth: 'Previous Month',
2479
+ nextMonth: 'Next Month',
2480
+ selectYear: 'Select Year',
2481
+ prevYear: 'Previous Year',
2482
+ nextYear: 'Next Year',
2483
+ selectDecade: 'Select Decade',
2484
+ prevDecade: 'Previous Decade',
2485
+ nextDecade: 'Next Decade',
2486
+ prevCentury: 'Previous Century',
2487
+ nextCentury: 'Next Century',
2488
+ pickHour: 'Pick Hour',
2489
+ incrementHour: 'Increment Hour',
2490
+ decrementHour: 'Decrement Hour',
2491
+ pickMinute: 'Pick Minute',
2492
+ incrementMinute: 'Increment Minute',
2493
+ decrementMinute: 'Decrement Minute',
2494
+ pickSecond: 'Pick Second',
2495
+ incrementSecond: 'Increment Second',
2496
+ decrementSecond: 'Decrement Second',
2497
+ togglePeriod: 'Toggle Period',
2498
+ selectTime: 'Select Time'
2499
+ },
2500
+ useStrict: false,
2501
+ sideBySide: false,
2502
+ daysOfWeekDisabled: false,
2503
+ calendarWeeks: false,
2504
+ viewMode: 'days',
2505
+ toolbarPlacement: 'default',
2506
+ showTodayButton: false,
2507
+ showClear: false,
2508
+ showClose: false,
2509
+ widgetPositioning: {
2510
+ horizontal: 'auto',
2511
+ vertical: 'auto'
2512
+ },
2513
+ widgetParent: null,
2514
+ ignoreReadonly: false,
2515
+ keepOpen: false,
2516
+ focusOnShow: true,
2517
+ inline: false,
2518
+ keepInvalid: false,
2519
+ datepickerInput: '.datepickerinput',
2520
+ keyBinds: {
2521
+ up: function (widget) {
2522
+ if (!widget) {
2523
+ return;
2524
+ }
2525
+ var d = this.date() || this.getMoment();
2526
+ if (widget.find('.datepicker').is(':visible')) {
2527
+ this.date(d.clone().subtract(7, 'd'));
2528
+ } else {
2529
+ this.date(d.clone().add(this.stepping(), 'm'));
2530
+ }
2531
+ },
2532
+ down: function (widget) {
2533
+ if (!widget) {
2534
+ this.show();
2535
+ return;
2536
+ }
2537
+ var d = this.date() || this.getMoment();
2538
+ if (widget.find('.datepicker').is(':visible')) {
2539
+ this.date(d.clone().add(7, 'd'));
2540
+ } else {
2541
+ this.date(d.clone().subtract(this.stepping(), 'm'));
2542
+ }
2543
+ },
2544
+ 'control up': function (widget) {
2545
+ if (!widget) {
2546
+ return;
2547
+ }
2548
+ var d = this.date() || this.getMoment();
2549
+ if (widget.find('.datepicker').is(':visible')) {
2550
+ this.date(d.clone().subtract(1, 'y'));
2551
+ } else {
2552
+ this.date(d.clone().add(1, 'h'));
2553
+ }
2554
+ },
2555
+ 'control down': function (widget) {
2556
+ if (!widget) {
2557
+ return;
2558
+ }
2559
+ var d = this.date() || this.getMoment();
2560
+ if (widget.find('.datepicker').is(':visible')) {
2561
+ this.date(d.clone().add(1, 'y'));
2562
+ } else {
2563
+ this.date(d.clone().subtract(1, 'h'));
2564
+ }
2565
+ },
2566
+ left: function (widget) {
2567
+ if (!widget) {
2568
+ return;
2569
+ }
2570
+ var d = this.date() || this.getMoment();
2571
+ if (widget.find('.datepicker').is(':visible')) {
2572
+ this.date(d.clone().subtract(1, 'd'));
2573
+ }
2574
+ },
2575
+ right: function (widget) {
2576
+ if (!widget) {
2577
+ return;
2578
+ }
2579
+ var d = this.date() || this.getMoment();
2580
+ if (widget.find('.datepicker').is(':visible')) {
2581
+ this.date(d.clone().add(1, 'd'));
2582
+ }
2583
+ },
2584
+ pageUp: function (widget) {
2585
+ if (!widget) {
2586
+ return;
2587
+ }
2588
+ var d = this.date() || this.getMoment();
2589
+ if (widget.find('.datepicker').is(':visible')) {
2590
+ this.date(d.clone().subtract(1, 'M'));
2591
+ }
2592
+ },
2593
+ pageDown: function (widget) {
2594
+ if (!widget) {
2595
+ return;
2596
+ }
2597
+ var d = this.date() || this.getMoment();
2598
+ if (widget.find('.datepicker').is(':visible')) {
2599
+ this.date(d.clone().add(1, 'M'));
2600
+ }
2601
+ },
2602
+ enter: function () {
2603
+ this.hide();
2604
+ },
2605
+ escape: function () {
2606
+ this.hide();
2607
+ },
2608
+ //tab: function (widget) { //this break the flow of the form. disabling for now
2609
+ // var toggle = widget.find('.picker-switch a[data-action="togglePicker"]');
2610
+ // if(toggle.length > 0) toggle.click();
2611
+ //},
2612
+ 'control space': function (widget) {
2613
+ if (!widget) {
2614
+ return;
2615
+ }
2616
+ if (widget.find('.timepicker').is(':visible')) {
2617
+ widget.find('.btn[data-action="togglePeriod"]').click();
2618
+ }
2619
+ },
2620
+ t: function () {
2621
+ this.date(this.getMoment());
2622
+ },
2623
+ 'delete': function () {
2624
+ this.clear();
2625
+ }
2626
+ },
2627
+ debug: false,
2628
+ allowInputToggle: false,
2629
+ disabledTimeIntervals: false,
2630
+ disabledHours: false,
2631
+ enabledHours: false,
2632
+ viewDate: false
2633
+ };
2634
+
2635
+ return $.fn.datetimepicker;
2636
+ }));