bootstrap-timepicker.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903
  1. //TODO: move arrow styles and button click code into configurable items, with defaults matching the existing code
  2. /*!
  3. * Timepicker Component for Twitter Bootstrap
  4. *
  5. * Copyright 2013 Joris de Wit
  6. *
  7. * Contributors https://github.com/jdewit/bootstrap-timepicker/graphs/contributors
  8. *
  9. * For the full copyright and license information, please view the LICENSE
  10. * file that was distributed with this source code.
  11. */
  12. (function($, window, document, undefined) {
  13. 'use strict';
  14. // TIMEPICKER PUBLIC CLASS DEFINITION
  15. var Timepicker = function(element, options) {
  16. this.widget = '';
  17. this.$element = $(element);
  18. this.defaultTime = options.defaultTime;
  19. this.disableFocus = options.disableFocus;
  20. this.isOpen = options.isOpen;
  21. this.minuteStep = options.minuteStep;
  22. this.modalBackdrop = options.modalBackdrop;
  23. this.secondStep = options.secondStep;
  24. this.showInputs = options.showInputs;
  25. this.showMeridian = options.showMeridian;
  26. this.showSeconds = options.showSeconds;
  27. this.template = options.template;
  28. this.appendWidgetTo = options.appendWidgetTo;
  29. this.upArrowStyle = options.upArrowStyle;
  30. this.downArrowStyle = options.downArrowStyle;
  31. this.containerClass = options.containerClass;
  32. this._init();
  33. };
  34. Timepicker.prototype = {
  35. constructor: Timepicker,
  36. _init: function() {
  37. var self = this;
  38. if (this.$element.parent().hasClass('input-append') || this.$element.parent().hasClass('input-prepend')) {
  39. if (this.$element.parent('.input-append, .input-prepend').find('.add-on').length) {
  40. this.$element.parent('.input-append, .input-prepend').find('.add-on').on({
  41. 'click.timepicker': $.proxy(this.showWidget, this)
  42. });
  43. } else {
  44. this.$element.closest(this.containerClass).find('.add-on').on({
  45. 'click.timepicker': $.proxy(this.showWidget, this)
  46. });
  47. }
  48. this.$element.on({
  49. 'focus.timepicker': $.proxy(this.highlightUnit, this),
  50. 'click.timepicker': $.proxy(this.highlightUnit, this),
  51. 'keydown.timepicker': $.proxy(this.elementKeydown, this),
  52. 'blur.timepicker': $.proxy(this.blurElement, this)
  53. });
  54. } else {
  55. if (this.template) {
  56. this.$element.on({
  57. 'focus.timepicker': $.proxy(this.showWidget, this),
  58. 'click.timepicker': $.proxy(this.showWidget, this),
  59. 'blur.timepicker': $.proxy(this.blurElement, this)
  60. });
  61. } else {
  62. this.$element.on({
  63. 'focus.timepicker': $.proxy(this.highlightUnit, this),
  64. 'click.timepicker': $.proxy(this.highlightUnit, this),
  65. 'keydown.timepicker': $.proxy(this.elementKeydown, this),
  66. 'blur.timepicker': $.proxy(this.blurElement, this)
  67. });
  68. }
  69. }
  70. if (this.template !== false) {
  71. this.$widget = $(this.getTemplate()).prependTo(this.$element.parents(this.appendWidgetTo)).on('click', $.proxy(this.widgetClick, this));
  72. } else {
  73. this.$widget = false;
  74. }
  75. if (this.showInputs && this.$widget !== false) {
  76. this.$widget.find('input').each(function() {
  77. $(this).on({
  78. 'click.timepicker': function() { $(this).select(); },
  79. 'keydown.timepicker': $.proxy(self.widgetKeydown, self)
  80. });
  81. });
  82. }
  83. this.setDefaultTime(this.defaultTime);
  84. },
  85. blurElement: function() {
  86. this.highlightedUnit = undefined;
  87. this.updateFromElementVal();
  88. },
  89. decrementHour: function() {
  90. if (this.showMeridian) {
  91. if (this.hour === 1) {
  92. this.hour = 12;
  93. } else if (this.hour === 12) {
  94. this.hour--;
  95. return this.toggleMeridian();
  96. } else if (this.hour === 0) {
  97. this.hour = 11;
  98. return this.toggleMeridian();
  99. } else {
  100. this.hour--;
  101. }
  102. } else {
  103. if (this.hour === 0) {
  104. this.hour = 23;
  105. } else {
  106. this.hour--;
  107. }
  108. }
  109. this.update();
  110. },
  111. decrementMinute: function(step) {
  112. var newVal;
  113. if (step) {
  114. newVal = this.minute - step;
  115. } else {
  116. newVal = this.minute - this.minuteStep;
  117. }
  118. if (newVal < 0) {
  119. this.decrementHour();
  120. this.minute = newVal + 60;
  121. } else {
  122. this.minute = newVal;
  123. }
  124. this.update();
  125. },
  126. decrementSecond: function() {
  127. var newVal = this.second - this.secondStep;
  128. if (newVal < 0) {
  129. this.decrementMinute(true);
  130. this.second = newVal + 60;
  131. } else {
  132. this.second = newVal;
  133. }
  134. this.update();
  135. },
  136. elementKeydown: function(e) {
  137. switch (e.keyCode) {
  138. case 9: //tab
  139. this.updateFromElementVal();
  140. switch (this.highlightedUnit) {
  141. case 'hour':
  142. e.preventDefault();
  143. this.highlightNextUnit();
  144. break;
  145. case 'minute':
  146. if (this.showMeridian || this.showSeconds) {
  147. e.preventDefault();
  148. this.highlightNextUnit();
  149. }
  150. break;
  151. case 'second':
  152. if (this.showMeridian) {
  153. e.preventDefault();
  154. this.highlightNextUnit();
  155. }
  156. break;
  157. }
  158. break;
  159. case 27: // escape
  160. this.updateFromElementVal();
  161. break;
  162. case 37: // left arrow
  163. e.preventDefault();
  164. this.highlightPrevUnit();
  165. this.updateFromElementVal();
  166. break;
  167. case 38: // up arrow
  168. e.preventDefault();
  169. switch (this.highlightedUnit) {
  170. case 'hour':
  171. this.incrementHour();
  172. this.highlightHour();
  173. break;
  174. case 'minute':
  175. this.incrementMinute();
  176. this.highlightMinute();
  177. break;
  178. case 'second':
  179. this.incrementSecond();
  180. this.highlightSecond();
  181. break;
  182. case 'meridian':
  183. this.toggleMeridian();
  184. this.highlightMeridian();
  185. break;
  186. }
  187. break;
  188. case 39: // right arrow
  189. e.preventDefault();
  190. this.updateFromElementVal();
  191. this.highlightNextUnit();
  192. break;
  193. case 40: // down arrow
  194. e.preventDefault();
  195. switch (this.highlightedUnit) {
  196. case 'hour':
  197. this.decrementHour();
  198. this.highlightHour();
  199. break;
  200. case 'minute':
  201. this.decrementMinute();
  202. this.highlightMinute();
  203. break;
  204. case 'second':
  205. this.decrementSecond();
  206. this.highlightSecond();
  207. break;
  208. case 'meridian':
  209. this.toggleMeridian();
  210. this.highlightMeridian();
  211. break;
  212. }
  213. break;
  214. }
  215. },
  216. formatTime: function(hour, minute, second, meridian) {
  217. hour = hour < 10 ? '0' + hour : hour;
  218. minute = minute < 10 ? '0' + minute : minute;
  219. second = second < 10 ? '0' + second : second;
  220. return hour + ':' + minute + (this.showSeconds ? ':' + second : '') + (this.showMeridian ? ' ' + meridian : '');
  221. },
  222. getCursorPosition: function() {
  223. var input = this.$element.get(0);
  224. if ('selectionStart' in input) {// Standard-compliant browsers
  225. return input.selectionStart;
  226. } else if (document.selection) {// IE fix
  227. input.focus();
  228. var sel = document.selection.createRange(),
  229. selLen = document.selection.createRange().text.length;
  230. sel.moveStart('character', - input.value.length);
  231. return sel.text.length - selLen;
  232. }
  233. },
  234. getTemplate: function() {
  235. var template,
  236. hourTemplate,
  237. minuteTemplate,
  238. secondTemplate,
  239. meridianTemplate,
  240. templateContent;
  241. if (this.showInputs) {
  242. hourTemplate = '<input type="text" name="hour" class="bootstrap-timepicker-hour form-control" maxlength="2"/>';
  243. minuteTemplate = '<input type="text" name="minute" class="bootstrap-timepicker-minute form-control" maxlength="2"/>';
  244. secondTemplate = '<input type="text" name="second" class="bootstrap-timepicker-second form-control" maxlength="2"/>';
  245. meridianTemplate = '<input type="text" name="meridian" class="bootstrap-timepicker-meridian form-control" maxlength="2"/>';
  246. } else {
  247. hourTemplate = '<span class="bootstrap-timepicker-hour"></span>';
  248. minuteTemplate = '<span class="bootstrap-timepicker-minute"></span>';
  249. secondTemplate = '<span class="bootstrap-timepicker-second"></span>';
  250. meridianTemplate = '<span class="bootstrap-timepicker-meridian"></span>';
  251. }
  252. templateContent = '<table>'+
  253. '<tr>'+
  254. '<td><a href="#" data-action="incrementHour"><i class="' + this.upArrowStyle + '"></i></a></td>'+
  255. '<td class="separator">&nbsp;</td>'+
  256. '<td><a href="#" data-action="incrementMinute"><i class="' + this.upArrowStyle + '"></i></a></td>'+
  257. (this.showSeconds ?
  258. '<td class="separator">&nbsp;</td>'+
  259. '<td><a href="#" data-action="incrementSecond"><i class="' + this.upArrowStyle + '"></i></a></td>'
  260. : '') +
  261. (this.showMeridian ?
  262. '<td class="separator">&nbsp;</td>'+
  263. '<td class="meridian-column"><a href="#" data-action="toggleMeridian"><i class="' + this.upArrowStyle + '"></i></a></td>'
  264. : '') +
  265. '</tr>'+
  266. '<tr>'+
  267. '<td>'+ hourTemplate +'</td> '+
  268. '<td class="separator">:</td>'+
  269. '<td>'+ minuteTemplate +'</td> '+
  270. (this.showSeconds ?
  271. '<td class="separator">:</td>'+
  272. '<td>'+ secondTemplate +'</td>'
  273. : '') +
  274. (this.showMeridian ?
  275. '<td class="separator">&nbsp;</td>'+
  276. '<td>'+ meridianTemplate +'</td>'
  277. : '') +
  278. '</tr>'+
  279. '<tr>'+
  280. '<td><a href="#" data-action="decrementHour"><i class="' + this.downArrowStyle + '"></i></a></td>'+
  281. '<td class="separator"></td>'+
  282. '<td><a href="#" data-action="decrementMinute"><i class="' + this.downArrowStyle + '"></i></a></td>'+
  283. (this.showSeconds ?
  284. '<td class="separator">&nbsp;</td>'+
  285. '<td><a href="#" data-action="decrementSecond"><i class="' + this.downArrowStyle + '"></i></a></td>'
  286. : '') +
  287. (this.showMeridian ?
  288. '<td class="separator">&nbsp;</td>'+
  289. '<td><a href="#" data-action="toggleMeridian"><i class="' + this.downArrowStyle + '"></i></a></td>'
  290. : '') +
  291. '</tr>'+
  292. '</table>';
  293. switch(this.template) {
  294. case 'modal':
  295. template = '<div class="bootstrap-timepicker-widget modal hide fade in" data-backdrop="'+ (this.modalBackdrop ? 'true' : 'false') +'">'+
  296. '<div class="modal-header">'+
  297. '<a href="#" class="close" data-dismiss="modal">×</a>'+
  298. '<h3>Pick a Time</h3>'+
  299. '</div>'+
  300. '<div class="modal-content">'+
  301. templateContent +
  302. '</div>'+
  303. '<div class="modal-footer">'+
  304. '<a href="#" class="btn btn-primary" data-dismiss="modal">OK</a>'+
  305. '</div>'+
  306. '</div>';
  307. break;
  308. case 'dropdown':
  309. template = '<div class="bootstrap-timepicker-widget dropdown-menu">'+ templateContent +'</div>';
  310. break;
  311. }
  312. return template;
  313. },
  314. getTime: function() {
  315. return this.formatTime(this.hour, this.minute, this.second, this.meridian);
  316. },
  317. hideWidget: function() {
  318. if (this.isOpen === false) {
  319. return;
  320. }
  321. if (this.showInputs) {
  322. this.updateFromWidgetInputs();
  323. }
  324. this.$element.trigger({
  325. 'type': 'hide.timepicker',
  326. 'time': {
  327. 'value': this.getTime(),
  328. 'hours': this.hour,
  329. 'minutes': this.minute,
  330. 'seconds': this.second,
  331. 'meridian': this.meridian
  332. }
  333. });
  334. if (this.template === 'modal' && this.$widget.modal) {
  335. this.$widget.modal('hide');
  336. } else {
  337. this.$widget.removeClass('open');
  338. }
  339. $(document).off('mousedown.timepicker');
  340. this.isOpen = false;
  341. },
  342. highlightUnit: function() {
  343. this.position = this.getCursorPosition();
  344. if (this.position >= 0 && this.position <= 2) {
  345. this.highlightHour();
  346. } else if (this.position >= 3 && this.position <= 5) {
  347. this.highlightMinute();
  348. } else if (this.position >= 6 && this.position <= 8) {
  349. if (this.showSeconds) {
  350. this.highlightSecond();
  351. } else {
  352. this.highlightMeridian();
  353. }
  354. } else if (this.position >= 9 && this.position <= 11) {
  355. this.highlightMeridian();
  356. }
  357. },
  358. highlightNextUnit: function() {
  359. switch (this.highlightedUnit) {
  360. case 'hour':
  361. this.highlightMinute();
  362. break;
  363. case 'minute':
  364. if (this.showSeconds) {
  365. this.highlightSecond();
  366. } else if (this.showMeridian){
  367. this.highlightMeridian();
  368. } else {
  369. this.highlightHour();
  370. }
  371. break;
  372. case 'second':
  373. if (this.showMeridian) {
  374. this.highlightMeridian();
  375. } else {
  376. this.highlightHour();
  377. }
  378. break;
  379. case 'meridian':
  380. this.highlightHour();
  381. break;
  382. }
  383. },
  384. highlightPrevUnit: function() {
  385. switch (this.highlightedUnit) {
  386. case 'hour':
  387. this.highlightMeridian();
  388. break;
  389. case 'minute':
  390. this.highlightHour();
  391. break;
  392. case 'second':
  393. this.highlightMinute();
  394. break;
  395. case 'meridian':
  396. if (this.showSeconds) {
  397. this.highlightSecond();
  398. } else {
  399. this.highlightMinute();
  400. }
  401. break;
  402. }
  403. },
  404. highlightHour: function() {
  405. var $element = this.$element.get(0);
  406. this.highlightedUnit = 'hour';
  407. if ($element.setSelectionRange) {
  408. setTimeout(function() {
  409. $element.setSelectionRange(0,2);
  410. }, 0);
  411. }
  412. },
  413. highlightMinute: function() {
  414. var $element = this.$element.get(0);
  415. this.highlightedUnit = 'minute';
  416. if ($element.setSelectionRange) {
  417. setTimeout(function() {
  418. $element.setSelectionRange(3,5);
  419. }, 0);
  420. }
  421. },
  422. highlightSecond: function() {
  423. var $element = this.$element.get(0);
  424. this.highlightedUnit = 'second';
  425. if ($element.setSelectionRange) {
  426. setTimeout(function() {
  427. $element.setSelectionRange(6,8);
  428. }, 0);
  429. }
  430. },
  431. highlightMeridian: function() {
  432. var $element = this.$element.get(0);
  433. this.highlightedUnit = 'meridian';
  434. if ($element.setSelectionRange) {
  435. if (this.showSeconds) {
  436. setTimeout(function() {
  437. $element.setSelectionRange(9,11);
  438. }, 0);
  439. } else {
  440. setTimeout(function() {
  441. $element.setSelectionRange(6,8);
  442. }, 0);
  443. }
  444. }
  445. },
  446. incrementHour: function() {
  447. if (this.showMeridian) {
  448. if (this.hour === 11) {
  449. this.hour++;
  450. return this.toggleMeridian();
  451. } else if (this.hour === 12) {
  452. this.hour = 0;
  453. }
  454. }
  455. if (this.hour === 23) {
  456. this.hour = 0;
  457. return;
  458. }
  459. this.hour++;
  460. this.update();
  461. },
  462. incrementMinute: function(step) {
  463. var newVal;
  464. if (step) {
  465. newVal = this.minute + step;
  466. } else {
  467. newVal = this.minute + this.minuteStep - (this.minute % this.minuteStep);
  468. }
  469. if (newVal > 59) {
  470. this.incrementHour();
  471. this.minute = newVal - 60;
  472. } else {
  473. this.minute = newVal;
  474. }
  475. this.update();
  476. },
  477. incrementSecond: function() {
  478. var newVal = this.second + this.secondStep - (this.second % this.secondStep);
  479. if (newVal > 59) {
  480. this.incrementMinute(true);
  481. this.second = newVal - 60;
  482. } else {
  483. this.second = newVal;
  484. }
  485. this.update();
  486. },
  487. remove: function() {
  488. $('document').off('.timepicker');
  489. if (this.$widget) {
  490. this.$widget.remove();
  491. }
  492. delete this.$element.data().timepicker;
  493. },
  494. setDefaultTime: function(defaultTime){
  495. if (!this.$element.val()) {
  496. if (defaultTime === 'current') {
  497. var dTime = new Date(),
  498. hours = dTime.getHours(),
  499. minutes = Math.floor(dTime.getMinutes() / this.minuteStep) * this.minuteStep,
  500. seconds = Math.floor(dTime.getSeconds() / this.secondStep) * this.secondStep,
  501. meridian = 'AM';
  502. if (this.showMeridian) {
  503. if (hours === 0) {
  504. hours = 12;
  505. } else if (hours >= 12) {
  506. if (hours > 12) {
  507. hours = hours - 12;
  508. }
  509. meridian = 'PM';
  510. } else {
  511. meridian = 'AM';
  512. }
  513. }
  514. this.hour = hours;
  515. this.minute = minutes;
  516. this.second = seconds;
  517. this.meridian = meridian;
  518. this.update();
  519. } else if (defaultTime === false) {
  520. this.hour = 0;
  521. this.minute = 0;
  522. this.second = 0;
  523. this.meridian = 'AM';
  524. } else {
  525. this.setTime(defaultTime);
  526. }
  527. } else {
  528. this.updateFromElementVal();
  529. }
  530. },
  531. setTime: function(time) {
  532. var arr,
  533. timeArray;
  534. if (this.showMeridian) {
  535. arr = time.split(' ');
  536. timeArray = arr[0].split(':');
  537. this.meridian = arr[1];
  538. } else {
  539. timeArray = time.split(':');
  540. }
  541. this.hour = parseInt(timeArray[0], 10);
  542. this.minute = parseInt(timeArray[1], 10);
  543. this.second = parseInt(timeArray[2], 10);
  544. if (isNaN(this.hour)) {
  545. this.hour = 0;
  546. }
  547. if (isNaN(this.minute)) {
  548. this.minute = 0;
  549. }
  550. if (this.showMeridian) {
  551. if (this.hour > 12) {
  552. this.hour = 12;
  553. } else if (this.hour < 1) {
  554. this.hour = 12;
  555. }
  556. if (this.meridian === 'am' || this.meridian === 'a') {
  557. this.meridian = 'AM';
  558. } else if (this.meridian === 'pm' || this.meridian === 'p') {
  559. this.meridian = 'PM';
  560. }
  561. if (this.meridian !== 'AM' && this.meridian !== 'PM') {
  562. this.meridian = 'AM';
  563. }
  564. } else {
  565. if (this.hour >= 24) {
  566. this.hour = 23;
  567. } else if (this.hour < 0) {
  568. this.hour = 0;
  569. }
  570. }
  571. if (this.minute < 0) {
  572. this.minute = 0;
  573. } else if (this.minute >= 60) {
  574. this.minute = 59;
  575. }
  576. if (this.showSeconds) {
  577. if (isNaN(this.second)) {
  578. this.second = 0;
  579. } else if (this.second < 0) {
  580. this.second = 0;
  581. } else if (this.second >= 60) {
  582. this.second = 59;
  583. }
  584. }
  585. this.update();
  586. },
  587. showWidget: function() {
  588. if (this.isOpen) {
  589. return;
  590. }
  591. if (this.$element.is(':disabled')) {
  592. return;
  593. }
  594. var self = this;
  595. $(document).on('mousedown.timepicker', function (e) {
  596. // Clicked outside the timepicker, hide it
  597. if ($(e.target).closest('.bootstrap-timepicker-widget').length === 0) {
  598. self.hideWidget();
  599. }
  600. });
  601. this.$element.trigger({
  602. 'type': 'show.timepicker',
  603. 'time': {
  604. 'value': this.getTime(),
  605. 'hours': this.hour,
  606. 'minutes': this.minute,
  607. 'seconds': this.second,
  608. 'meridian': this.meridian
  609. }
  610. });
  611. if (this.disableFocus) {
  612. this.$element.blur();
  613. }
  614. this.updateFromElementVal();
  615. if (this.template === 'modal' && this.$widget.modal) {
  616. this.$widget.modal('show').on('hidden', $.proxy(this.hideWidget, this));
  617. } else {
  618. if (this.isOpen === false) {
  619. this.$widget.addClass('open');
  620. }
  621. }
  622. this.isOpen = true;
  623. },
  624. toggleMeridian: function() {
  625. this.meridian = this.meridian === 'AM' ? 'PM' : 'AM';
  626. this.update();
  627. },
  628. update: function() {
  629. this.$element.trigger({
  630. 'type': 'changeTime.timepicker',
  631. 'time': {
  632. 'value': this.getTime(),
  633. 'hours': this.hour,
  634. 'minutes': this.minute,
  635. 'seconds': this.second,
  636. 'meridian': this.meridian
  637. }
  638. });
  639. this.updateElement();
  640. this.updateWidget();
  641. },
  642. updateElement: function() {
  643. this.$element.val(this.getTime()).change();
  644. },
  645. updateFromElementVal: function() {
  646. var val = this.$element.val();
  647. if (val) {
  648. this.setTime(val);
  649. }
  650. },
  651. updateWidget: function() {
  652. if (this.$widget === false) {
  653. return;
  654. }
  655. var hour = this.hour < 10 ? '0' + this.hour : this.hour,
  656. minute = this.minute < 10 ? '0' + this.minute : this.minute,
  657. second = this.second < 10 ? '0' + this.second : this.second;
  658. if (this.showInputs) {
  659. this.$widget.find('input.bootstrap-timepicker-hour').val(hour);
  660. this.$widget.find('input.bootstrap-timepicker-minute').val(minute);
  661. if (this.showSeconds) {
  662. this.$widget.find('input.bootstrap-timepicker-second').val(second);
  663. }
  664. if (this.showMeridian) {
  665. this.$widget.find('input.bootstrap-timepicker-meridian').val(this.meridian);
  666. }
  667. } else {
  668. this.$widget.find('span.bootstrap-timepicker-hour').text(hour);
  669. this.$widget.find('span.bootstrap-timepicker-minute').text(minute);
  670. if (this.showSeconds) {
  671. this.$widget.find('span.bootstrap-timepicker-second').text(second);
  672. }
  673. if (this.showMeridian) {
  674. this.$widget.find('span.bootstrap-timepicker-meridian').text(this.meridian);
  675. }
  676. }
  677. },
  678. updateFromWidgetInputs: function() {
  679. if (this.$widget === false) {
  680. return;
  681. }
  682. var time = $('input.bootstrap-timepicker-hour', this.$widget).val() + ':' +
  683. $('input.bootstrap-timepicker-minute', this.$widget).val() +
  684. (this.showSeconds ? ':' + $('input.bootstrap-timepicker-second', this.$widget).val() : '') +
  685. (this.showMeridian ? ' ' + $('input.bootstrap-timepicker-meridian', this.$widget).val() : '');
  686. this.setTime(time);
  687. },
  688. widgetClick: function(e) {
  689. e.stopPropagation();
  690. e.preventDefault();
  691. var action = $(e.target).closest('a').data('action');
  692. if (action) {
  693. this[action]();
  694. }
  695. },
  696. widgetKeydown: function(e) {
  697. var $input = $(e.target).closest('input'),
  698. name = $input.attr('name');
  699. switch (e.keyCode) {
  700. case 9: //tab
  701. if (this.showMeridian) {
  702. if (name === 'meridian') {
  703. return this.hideWidget();
  704. }
  705. } else {
  706. if (this.showSeconds) {
  707. if (name === 'second') {
  708. return this.hideWidget();
  709. }
  710. } else {
  711. if (name === 'minute') {
  712. return this.hideWidget();
  713. }
  714. }
  715. }
  716. this.updateFromWidgetInputs();
  717. break;
  718. case 27: // escape
  719. this.hideWidget();
  720. break;
  721. case 38: // up arrow
  722. e.preventDefault();
  723. switch (name) {
  724. case 'hour':
  725. this.incrementHour();
  726. break;
  727. case 'minute':
  728. this.incrementMinute();
  729. break;
  730. case 'second':
  731. this.incrementSecond();
  732. break;
  733. case 'meridian':
  734. this.toggleMeridian();
  735. break;
  736. }
  737. break;
  738. case 40: // down arrow
  739. e.preventDefault();
  740. switch (name) {
  741. case 'hour':
  742. this.decrementHour();
  743. break;
  744. case 'minute':
  745. this.decrementMinute();
  746. break;
  747. case 'second':
  748. this.decrementSecond();
  749. break;
  750. case 'meridian':
  751. this.toggleMeridian();
  752. break;
  753. }
  754. break;
  755. }
  756. }
  757. };
  758. //TIMEPICKER PLUGIN DEFINITION
  759. $.fn.timepicker = function(option) {
  760. var args = Array.apply(null, arguments);
  761. args.shift();
  762. return this.each(function() {
  763. var $this = $(this),
  764. data = $this.data('timepicker'),
  765. options = typeof option === 'object' && option;
  766. if (!data) {
  767. $this.data('timepicker', (data = new Timepicker(this, $.extend({}, $.fn.timepicker.defaults, options, $(this).data()))));
  768. }
  769. if (typeof option === 'string') {
  770. data[option].apply(data, args);
  771. }
  772. });
  773. };
  774. $.fn.timepicker.defaults = {
  775. defaultTime: 'current',
  776. disableFocus: false,
  777. isOpen: false,
  778. minuteStep: 15,
  779. modalBackdrop: false,
  780. secondStep: 15,
  781. showSeconds: false,
  782. showInputs: true,
  783. showMeridian: true,
  784. template: 'dropdown',
  785. appendWidgetTo: '.bootstrap-timepicker',
  786. upArrowStyle: 'glyphicon glyphicon-chevron-up',
  787. downArrowStyle: 'glyphicon glyphicon-chevron-down',
  788. containerClass: 'bootstrap-timepicker'
  789. };
  790. $.fn.timepicker.Constructor = Timepicker;
  791. })(jQuery, window, document);