timepicker.js 24 KB

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