bootstrap-datetimepicker.js 56 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385
  1. /*
  2. //! version : 3.1.3
  3. =========================================================
  4. bootstrap-datetimepicker.js
  5. https://github.com/Eonasdan/bootstrap-datetimepicker
  6. =========================================================
  7. The MIT License (MIT)
  8. Copyright (c) 2014 Jonathan Peterson
  9. Permission is hereby granted, free of charge, to any person obtaining a copy
  10. of this software and associated documentation files (the "Software"), to deal
  11. in the Software without restriction, including without limitation the rights
  12. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. copies of the Software, and to permit persons to whom the Software is
  14. furnished to do so, subject to the following conditions:
  15. The above copyright notice and this permission notice shall be included in
  16. all copies or substantial portions of the Software.
  17. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. THE SOFTWARE.
  24. */
  25. ;(function (root, factory) {
  26. 'use strict';
  27. if (typeof define === 'function' && define.amd) {
  28. // AMD is used - Register as an anonymous module.
  29. define(['jquery', 'moment'], factory);
  30. } else if (typeof exports === 'object') {
  31. factory(require('jquery'), require('moment'));
  32. }
  33. else {
  34. // Neither AMD or CommonJS used. Use global variables.
  35. if (!jQuery) {
  36. throw new Error('bootstrap-datetimepicker requires jQuery to be loaded first');
  37. }
  38. if (!moment) {
  39. throw new Error('bootstrap-datetimepicker requires moment.js to be loaded first');
  40. }
  41. factory(root.jQuery, moment);
  42. }
  43. }(this, function ($, moment) {
  44. 'use strict';
  45. if (typeof moment === 'undefined') {
  46. throw new Error('momentjs is required');
  47. }
  48. var dpgId = 0,
  49. DateTimePicker = function (element, options) {
  50. var defaults = $.fn.datetimepicker.defaults,
  51. icons = {
  52. time: 'glyphicon glyphicon-time',
  53. date: 'glyphicon glyphicon-calendar',
  54. up: 'glyphicon glyphicon-chevron-up',
  55. down: 'glyphicon glyphicon-chevron-down'
  56. },
  57. picker = this,
  58. errored = false,
  59. dDate,
  60. init = function () {
  61. var icon = false, localeData, rInterval;
  62. picker.options = $.extend({}, defaults, options);
  63. picker.options.icons = $.extend({}, icons, picker.options.icons);
  64. picker.element = $(element);
  65. dataToOptions();
  66. if (!(picker.options.pickTime || picker.options.pickDate)) {
  67. throw new Error('Must choose at least one picker');
  68. }
  69. picker.id = dpgId++;
  70. moment.locale(picker.options.language);
  71. picker.date = moment();
  72. picker.unset = false;
  73. picker.isInput = picker.element.is('input');
  74. picker.component = false;
  75. if (picker.element.hasClass('input-group')) {
  76. if (picker.element.find('.datepickerbutton').size() === 0) {//in case there is more then one 'input-group-addon' Issue #48
  77. picker.component = picker.element.find('[class^="input-group-"]');
  78. }
  79. else {
  80. picker.component = picker.element.find('.datepickerbutton');
  81. }
  82. }
  83. picker.format = picker.options.format;
  84. localeData = moment().localeData();
  85. if (!picker.format) {
  86. picker.format = (picker.options.pickDate ? localeData.longDateFormat('L') : '');
  87. if (picker.options.pickDate && picker.options.pickTime) {
  88. picker.format += ' ';
  89. }
  90. picker.format += (picker.options.pickTime ? localeData.longDateFormat('LT') : '');
  91. if (picker.options.useSeconds) {
  92. if (localeData.longDateFormat('LT').indexOf(' A') !== -1) {
  93. picker.format = picker.format.split(' A')[0] + ':ss A';
  94. }
  95. else {
  96. picker.format += ':ss';
  97. }
  98. }
  99. }
  100. picker.use24hours = (picker.format.toLowerCase().indexOf('a') < 0 && picker.format.indexOf('h') < 0);
  101. if (picker.component) {
  102. icon = picker.component.find('span');
  103. }
  104. if (picker.options.pickTime) {
  105. if (icon) {
  106. icon.addClass(picker.options.icons.time);
  107. }
  108. }
  109. if (picker.options.pickDate) {
  110. if (icon) {
  111. icon.removeClass(picker.options.icons.time);
  112. icon.addClass(picker.options.icons.date);
  113. }
  114. }
  115. picker.options.widgetParent =
  116. typeof picker.options.widgetParent === 'string' && picker.options.widgetParent ||
  117. picker.element.parents().filter(function () {
  118. return 'scroll' === $(this).css('overflow-y');
  119. }).get(0) ||
  120. 'body';
  121. picker.widget = $(getTemplate()).appendTo(picker.options.widgetParent);
  122. picker.minViewMode = picker.options.minViewMode || 0;
  123. if (typeof picker.minViewMode === 'string') {
  124. switch (picker.minViewMode) {
  125. case 'months':
  126. picker.minViewMode = 1;
  127. break;
  128. case 'years':
  129. picker.minViewMode = 2;
  130. break;
  131. default:
  132. picker.minViewMode = 0;
  133. break;
  134. }
  135. }
  136. picker.viewMode = picker.options.viewMode || 0;
  137. if (typeof picker.viewMode === 'string') {
  138. switch (picker.viewMode) {
  139. case 'months':
  140. picker.viewMode = 1;
  141. break;
  142. case 'years':
  143. picker.viewMode = 2;
  144. break;
  145. default:
  146. picker.viewMode = 0;
  147. break;
  148. }
  149. }
  150. picker.viewMode = Math.max(picker.viewMode, picker.minViewMode);
  151. picker.options.disabledDates = indexGivenDates(picker.options.disabledDates);
  152. picker.options.enabledDates = indexGivenDates(picker.options.enabledDates);
  153. picker.startViewMode = picker.viewMode;
  154. picker.setMinDate(picker.options.minDate);
  155. picker.setMaxDate(picker.options.maxDate);
  156. fillDow();
  157. fillMonths();
  158. fillHours();
  159. fillMinutes();
  160. fillSeconds();
  161. update();
  162. showMode();
  163. if (!getPickerInput().prop('disabled')) {
  164. attachDatePickerEvents();
  165. }
  166. if (picker.options.defaultDate !== '' && getPickerInput().val() === '') {
  167. picker.setValue(picker.options.defaultDate);
  168. }
  169. if (picker.options.minuteStepping !== 1) {
  170. rInterval = picker.options.minuteStepping;
  171. picker.date.minutes((Math.round(picker.date.minutes() / rInterval) * rInterval) % 60).seconds(0);
  172. }
  173. },
  174. getPickerInput = function () {
  175. var input;
  176. if (picker.isInput) {
  177. return picker.element;
  178. }
  179. input = picker.element.find('.datepickerinput');
  180. if (input.size() === 0) {
  181. input = picker.element.find('input');
  182. }
  183. else if (!input.is('input')) {
  184. throw new Error('CSS class "datepickerinput" cannot be applied to non input element');
  185. }
  186. return input;
  187. },
  188. dataToOptions = function () {
  189. var eData;
  190. if (picker.element.is('input')) {
  191. eData = picker.element.data();
  192. }
  193. else {
  194. eData = picker.element.find('input').data();
  195. }
  196. if (eData.dateFormat !== undefined) {
  197. picker.options.format = eData.dateFormat;
  198. }
  199. if (eData.datePickdate !== undefined) {
  200. picker.options.pickDate = eData.datePickdate;
  201. }
  202. if (eData.datePicktime !== undefined) {
  203. picker.options.pickTime = eData.datePicktime;
  204. }
  205. if (eData.dateUseminutes !== undefined) {
  206. picker.options.useMinutes = eData.dateUseminutes;
  207. }
  208. if (eData.dateUseseconds !== undefined) {
  209. picker.options.useSeconds = eData.dateUseseconds;
  210. }
  211. if (eData.dateUsecurrent !== undefined) {
  212. picker.options.useCurrent = eData.dateUsecurrent;
  213. }
  214. if (eData.calendarWeeks !== undefined) {
  215. picker.options.calendarWeeks = eData.calendarWeeks;
  216. }
  217. if (eData.dateMinutestepping !== undefined) {
  218. picker.options.minuteStepping = eData.dateMinutestepping;
  219. }
  220. if (eData.dateMindate !== undefined) {
  221. picker.options.minDate = eData.dateMindate;
  222. }
  223. if (eData.dateMaxdate !== undefined) {
  224. picker.options.maxDate = eData.dateMaxdate;
  225. }
  226. if (eData.dateShowtoday !== undefined) {
  227. picker.options.showToday = eData.dateShowtoday;
  228. }
  229. if (eData.dateCollapse !== undefined) {
  230. picker.options.collapse = eData.dateCollapse;
  231. }
  232. if (eData.dateLanguage !== undefined) {
  233. picker.options.language = eData.dateLanguage;
  234. }
  235. if (eData.dateDefaultdate !== undefined) {
  236. picker.options.defaultDate = eData.dateDefaultdate;
  237. }
  238. if (eData.dateDisableddates !== undefined) {
  239. picker.options.disabledDates = eData.dateDisableddates;
  240. }
  241. if (eData.dateEnableddates !== undefined) {
  242. picker.options.enabledDates = eData.dateEnableddates;
  243. }
  244. if (eData.dateIcons !== undefined) {
  245. picker.options.icons = eData.dateIcons;
  246. }
  247. if (eData.dateUsestrict !== undefined) {
  248. picker.options.useStrict = eData.dateUsestrict;
  249. }
  250. if (eData.dateDirection !== undefined) {
  251. picker.options.direction = eData.dateDirection;
  252. }
  253. if (eData.dateSidebyside !== undefined) {
  254. picker.options.sideBySide = eData.dateSidebyside;
  255. }
  256. if (eData.dateDaysofweekdisabled !== undefined) {
  257. picker.options.daysOfWeekDisabled = eData.dateDaysofweekdisabled;
  258. }
  259. },
  260. place = function () {
  261. var position = 'absolute',
  262. offset = picker.component ? picker.component.offset() : picker.element.offset(),
  263. $window = $(window),
  264. placePosition;
  265. picker.width = picker.component ? picker.component.outerWidth() : picker.element.outerWidth();
  266. offset.top = offset.top + picker.element.outerHeight();
  267. if (picker.options.direction === 'up') {
  268. placePosition = 'top';
  269. } else if (picker.options.direction === 'bottom') {
  270. placePosition = 'bottom';
  271. } else if (picker.options.direction === 'auto') {
  272. if (offset.top + picker.widget.height() > $window.height() + $window.scrollTop() && picker.widget.height() + picker.element.outerHeight() < offset.top) {
  273. placePosition = 'top';
  274. } else {
  275. placePosition = 'bottom';
  276. }
  277. }
  278. if (placePosition === 'top') {
  279. //ACE
  280. offset.bottom = Math.max($window.height() , document.documentElement.scrollHeight || document.body.scrollHeight) - offset.top + picker.element.outerHeight() + 3;
  281. picker.widget.addClass('top').removeClass('bottom');
  282. } else {
  283. offset.top += 1;
  284. picker.widget.addClass('bottom').removeClass('top');
  285. }
  286. if (picker.options.width !== undefined) {
  287. picker.widget.width(picker.options.width);
  288. }
  289. if (picker.options.orientation === 'left') {
  290. picker.widget.addClass('left-oriented');
  291. offset.left = offset.left - picker.widget.width() + 20;
  292. }
  293. if (isInFixed()) {
  294. position = 'fixed';
  295. offset.top -= $window.scrollTop();
  296. offset.left -= $window.scrollLeft();
  297. }
  298. if ($window.width() < offset.left + picker.widget.outerWidth()) {
  299. offset.right = $window.width() - offset.left - picker.width;
  300. offset.left = 'auto';
  301. picker.widget.addClass('pull-right');
  302. } else {
  303. offset.right = 'auto';
  304. picker.widget.removeClass('pull-right');
  305. }
  306. if (placePosition === 'top') {
  307. picker.widget.css({
  308. position: position,
  309. bottom: offset.bottom,
  310. top: 'auto',
  311. left: offset.left,
  312. right: offset.right
  313. });
  314. } else {
  315. picker.widget.css({
  316. position: position,
  317. top: offset.top,
  318. bottom: 'auto',
  319. left: offset.left,
  320. right: offset.right
  321. });
  322. }
  323. },
  324. notifyChange = function (oldDate, eventType) {
  325. if (moment(picker.date).isSame(moment(oldDate)) && !errored) {
  326. return;
  327. }
  328. errored = false;
  329. picker.element.trigger({
  330. type: 'dp.change',
  331. date: moment(picker.date),
  332. oldDate: moment(oldDate)
  333. });
  334. if (eventType !== 'change') {
  335. picker.element.change();
  336. }
  337. },
  338. notifyError = function (date) {
  339. errored = true;
  340. picker.element.trigger({
  341. type: 'dp.error',
  342. date: moment(date, picker.format, picker.options.useStrict)
  343. });
  344. },
  345. update = function (newDate) {
  346. moment.locale(picker.options.language);
  347. var dateStr = newDate;
  348. if (!dateStr) {
  349. dateStr = getPickerInput().val();
  350. if (dateStr) {
  351. picker.date = moment(dateStr, picker.format, picker.options.useStrict);
  352. }
  353. if (!picker.date) {
  354. picker.date = moment();
  355. }
  356. }
  357. picker.viewDate = moment(picker.date).startOf('month');
  358. fillDate();
  359. fillTime();
  360. },
  361. fillDow = function () {
  362. moment.locale(picker.options.language);
  363. var html = $('<tr>'), weekdaysMin = moment.weekdaysMin(), i;
  364. if (picker.options.calendarWeeks === true) {
  365. html.append('<th class="cw">#</th>');
  366. }
  367. if (moment().localeData()._week.dow === 0) { // starts on Sunday
  368. for (i = 0; i < 7; i++) {
  369. html.append('<th class="dow">' + weekdaysMin[i] + '</th>');
  370. }
  371. } else {
  372. for (i = 1; i < 8; i++) {
  373. if (i === 7) {
  374. html.append('<th class="dow">' + weekdaysMin[0] + '</th>');
  375. } else {
  376. html.append('<th class="dow">' + weekdaysMin[i] + '</th>');
  377. }
  378. }
  379. }
  380. picker.widget.find('.datepicker-days thead').append(html);
  381. },
  382. fillMonths = function () {
  383. moment.locale(picker.options.language);
  384. var html = '', i, monthsShort = moment.monthsShort();
  385. for (i = 0; i < 12; i++) {
  386. html += '<span class="month">' + monthsShort[i] + '</span>';
  387. }
  388. picker.widget.find('.datepicker-months td').append(html);
  389. },
  390. fillDate = function () {
  391. if (!picker.options.pickDate) {
  392. return;
  393. }
  394. moment.locale(picker.options.language);
  395. var year = picker.viewDate.year(),
  396. month = picker.viewDate.month(),
  397. startYear = picker.options.minDate.year(),
  398. startMonth = picker.options.minDate.month(),
  399. endYear = picker.options.maxDate.year(),
  400. endMonth = picker.options.maxDate.month(),
  401. currentDate,
  402. prevMonth, nextMonth, html = [], row, clsName, i, days, yearCont, currentYear, months = moment.months();
  403. picker.widget.find('.datepicker-days').find('.disabled').removeClass('disabled');
  404. picker.widget.find('.datepicker-months').find('.disabled').removeClass('disabled');
  405. picker.widget.find('.datepicker-years').find('.disabled').removeClass('disabled');
  406. picker.widget.find('.datepicker-days th:eq(1)').text(
  407. months[month] + ' ' + year);
  408. prevMonth = moment(picker.viewDate, picker.format, picker.options.useStrict).subtract(1, 'months');
  409. days = prevMonth.daysInMonth();
  410. prevMonth.date(days).startOf('week');
  411. if ((year === startYear && month <= startMonth) || year < startYear) {
  412. picker.widget.find('.datepicker-days th:eq(0)').addClass('disabled');
  413. }
  414. if ((year === endYear && month >= endMonth) || year > endYear) {
  415. picker.widget.find('.datepicker-days th:eq(2)').addClass('disabled');
  416. }
  417. nextMonth = moment(prevMonth).add(42, 'd');
  418. while (prevMonth.isBefore(nextMonth)) {
  419. if (prevMonth.weekday() === moment().startOf('week').weekday()) {
  420. row = $('<tr>');
  421. html.push(row);
  422. if (picker.options.calendarWeeks === true) {
  423. row.append('<td class="cw">' + prevMonth.week() + '</td>');
  424. }
  425. }
  426. clsName = '';
  427. if (prevMonth.year() < year || (prevMonth.year() === year && prevMonth.month() < month)) {
  428. clsName += ' old';
  429. } else if (prevMonth.year() > year || (prevMonth.year() === year && prevMonth.month() > month)) {
  430. clsName += ' new';
  431. }
  432. if (prevMonth.isSame(moment({y: picker.date.year(), M: picker.date.month(), d: picker.date.date()}))) {
  433. clsName += ' active';
  434. }
  435. if (isInDisableDates(prevMonth, 'day') || !isInEnableDates(prevMonth)) {
  436. clsName += ' disabled';
  437. }
  438. if (picker.options.showToday === true) {
  439. if (prevMonth.isSame(moment(), 'day')) {
  440. clsName += ' today';
  441. }
  442. }
  443. if (picker.options.daysOfWeekDisabled) {
  444. for (i = 0; i < picker.options.daysOfWeekDisabled.length; i++) {
  445. if (prevMonth.day() === picker.options.daysOfWeekDisabled[i]) {
  446. clsName += ' disabled';
  447. break;
  448. }
  449. }
  450. }
  451. row.append('<td class="day' + clsName + '">' + prevMonth.date() + '</td>');
  452. currentDate = prevMonth.date();
  453. prevMonth.add(1, 'd');
  454. if (currentDate === prevMonth.date()) {
  455. prevMonth.add(1, 'd');
  456. }
  457. }
  458. picker.widget.find('.datepicker-days tbody').empty().append(html);
  459. currentYear = picker.date.year();
  460. months = picker.widget.find('.datepicker-months').find('th:eq(1)').text(year).end().find('span').removeClass('active');
  461. if (currentYear === year) {
  462. months.eq(picker.date.month()).addClass('active');
  463. }
  464. if (year - 1 < startYear) {
  465. picker.widget.find('.datepicker-months th:eq(0)').addClass('disabled');
  466. }
  467. if (year + 1 > endYear) {
  468. picker.widget.find('.datepicker-months th:eq(2)').addClass('disabled');
  469. }
  470. for (i = 0; i < 12; i++) {
  471. if ((year === startYear && startMonth > i) || (year < startYear)) {
  472. $(months[i]).addClass('disabled');
  473. } else if ((year === endYear && endMonth < i) || (year > endYear)) {
  474. $(months[i]).addClass('disabled');
  475. }
  476. }
  477. html = '';
  478. year = parseInt(year / 10, 10) * 10;
  479. yearCont = picker.widget.find('.datepicker-years').find(
  480. 'th:eq(1)').text(year + '-' + (year + 9)).parents('table').find('td');
  481. picker.widget.find('.datepicker-years').find('th').removeClass('disabled');
  482. if (startYear > year) {
  483. picker.widget.find('.datepicker-years').find('th:eq(0)').addClass('disabled');
  484. }
  485. if (endYear < year + 9) {
  486. picker.widget.find('.datepicker-years').find('th:eq(2)').addClass('disabled');
  487. }
  488. year -= 1;
  489. for (i = -1; i < 11; i++) {
  490. html += '<span class="year' + (i === -1 || i === 10 ? ' old' : '') + (currentYear === year ? ' active' : '') + ((year < startYear || year > endYear) ? ' disabled' : '') + '">' + year + '</span>';
  491. year += 1;
  492. }
  493. yearCont.html(html);
  494. },
  495. fillHours = function () {
  496. moment.locale(picker.options.language);
  497. var table = picker.widget.find('.timepicker .timepicker-hours table'), html = '', current, i, j;
  498. table.parent().hide();
  499. if (picker.use24hours) {
  500. current = 0;
  501. for (i = 0; i < 6; i += 1) {
  502. html += '<tr>';
  503. for (j = 0; j < 4; j += 1) {
  504. html += '<td class="hour">' + padLeft(current.toString()) + '</td>';
  505. current++;
  506. }
  507. html += '</tr>';
  508. }
  509. }
  510. else {
  511. current = 1;
  512. for (i = 0; i < 3; i += 1) {
  513. html += '<tr>';
  514. for (j = 0; j < 4; j += 1) {
  515. html += '<td class="hour">' + padLeft(current.toString()) + '</td>';
  516. current++;
  517. }
  518. html += '</tr>';
  519. }
  520. }
  521. table.html(html);
  522. },
  523. fillMinutes = function () {
  524. var table = picker.widget.find('.timepicker .timepicker-minutes table'), html = '', current = 0, i, j, step = picker.options.minuteStepping;
  525. table.parent().hide();
  526. if (step === 1) {
  527. step = 5;
  528. }
  529. for (i = 0; i < Math.ceil(60 / step / 4) ; i++) {
  530. html += '<tr>';
  531. for (j = 0; j < 4; j += 1) {
  532. if (current < 60) {
  533. html += '<td class="minute">' + padLeft(current.toString()) + '</td>';
  534. current += step;
  535. } else {
  536. html += '<td></td>';
  537. }
  538. }
  539. html += '</tr>';
  540. }
  541. table.html(html);
  542. },
  543. fillSeconds = function () {
  544. var table = picker.widget.find('.timepicker .timepicker-seconds table'), html = '', current = 0, i, j;
  545. table.parent().hide();
  546. for (i = 0; i < 3; i++) {
  547. html += '<tr>';
  548. for (j = 0; j < 4; j += 1) {
  549. html += '<td class="second">' + padLeft(current.toString()) + '</td>';
  550. current += 5;
  551. }
  552. html += '</tr>';
  553. }
  554. table.html(html);
  555. },
  556. fillTime = function () {
  557. if (!picker.date) {
  558. return;
  559. }
  560. var timeComponents = picker.widget.find('.timepicker span[data-time-component]'),
  561. hour = picker.date.hours(),
  562. period = picker.date.format('A');
  563. if (!picker.use24hours) {
  564. if (hour === 0) {
  565. hour = 12;
  566. } else if (hour !== 12) {
  567. hour = hour % 12;
  568. }
  569. picker.widget.find('.timepicker [data-action=togglePeriod]').text(period);
  570. }
  571. timeComponents.filter('[data-time-component=hours]').text(padLeft(hour));
  572. timeComponents.filter('[data-time-component=minutes]').text(padLeft(picker.date.minutes()));
  573. timeComponents.filter('[data-time-component=seconds]').text(padLeft(picker.date.second()));
  574. },
  575. click = function (e) {
  576. e.stopPropagation();
  577. e.preventDefault();
  578. picker.unset = false;
  579. var target = $(e.target).closest('span, td, th'), month, year, step, day, oldDate = moment(picker.date);
  580. if (target.length === 1) {
  581. if (!target.is('.disabled')) {
  582. switch (target[0].nodeName.toLowerCase()) {
  583. case 'th':
  584. switch (target[0].className) {
  585. case 'picker-switch':
  586. showMode(1);
  587. break;
  588. case 'prev':
  589. case 'next':
  590. step = dpGlobal.modes[picker.viewMode].navStep;
  591. if (target[0].className === 'prev') {
  592. step = step * -1;
  593. }
  594. picker.viewDate.add(step, dpGlobal.modes[picker.viewMode].navFnc);
  595. fillDate();
  596. break;
  597. }
  598. break;
  599. case 'span':
  600. if (target.is('.month')) {
  601. month = target.parent().find('span').index(target);
  602. picker.viewDate.month(month);
  603. } else {
  604. year = parseInt(target.text(), 10) || 0;
  605. picker.viewDate.year(year);
  606. }
  607. if (picker.viewMode === picker.minViewMode) {
  608. picker.date = moment({
  609. y: picker.viewDate.year(),
  610. M: picker.viewDate.month(),
  611. d: picker.viewDate.date(),
  612. h: picker.date.hours(),
  613. m: picker.date.minutes(),
  614. s: picker.date.seconds()
  615. });
  616. set();
  617. notifyChange(oldDate, e.type);
  618. }
  619. showMode(-1);
  620. fillDate();
  621. break;
  622. case 'td':
  623. if (target.is('.day')) {
  624. day = parseInt(target.text(), 10) || 1;
  625. month = picker.viewDate.month();
  626. year = picker.viewDate.year();
  627. if (target.is('.old')) {
  628. if (month === 0) {
  629. month = 11;
  630. year -= 1;
  631. } else {
  632. month -= 1;
  633. }
  634. } else if (target.is('.new')) {
  635. if (month === 11) {
  636. month = 0;
  637. year += 1;
  638. } else {
  639. month += 1;
  640. }
  641. }
  642. picker.date = moment({
  643. y: year,
  644. M: month,
  645. d: day,
  646. h: picker.date.hours(),
  647. m: picker.date.minutes(),
  648. s: picker.date.seconds()
  649. }
  650. );
  651. picker.viewDate = moment({
  652. y: year, M: month, d: Math.min(28, day)
  653. });
  654. fillDate();
  655. set();
  656. notifyChange(oldDate, e.type);
  657. }
  658. break;
  659. }
  660. }
  661. }
  662. },
  663. actions = {
  664. incrementHours: function () {
  665. checkDate('add', 'hours', 1);
  666. },
  667. incrementMinutes: function () {
  668. checkDate('add', 'minutes', picker.options.minuteStepping);
  669. },
  670. incrementSeconds: function () {
  671. checkDate('add', 'seconds', 1);
  672. },
  673. decrementHours: function () {
  674. checkDate('subtract', 'hours', 1);
  675. },
  676. decrementMinutes: function () {
  677. checkDate('subtract', 'minutes', picker.options.minuteStepping);
  678. },
  679. decrementSeconds: function () {
  680. checkDate('subtract', 'seconds', 1);
  681. },
  682. togglePeriod: function () {
  683. var hour = picker.date.hours();
  684. if (hour >= 12) {
  685. hour -= 12;
  686. } else {
  687. hour += 12;
  688. }
  689. picker.date.hours(hour);
  690. },
  691. showPicker: function () {
  692. picker.widget.find('.timepicker > div:not(.timepicker-picker)').hide();
  693. picker.widget.find('.timepicker .timepicker-picker').show();
  694. },
  695. showHours: function () {
  696. picker.widget.find('.timepicker .timepicker-picker').hide();
  697. picker.widget.find('.timepicker .timepicker-hours').show();
  698. },
  699. showMinutes: function () {
  700. picker.widget.find('.timepicker .timepicker-picker').hide();
  701. picker.widget.find('.timepicker .timepicker-minutes').show();
  702. },
  703. showSeconds: function () {
  704. picker.widget.find('.timepicker .timepicker-picker').hide();
  705. picker.widget.find('.timepicker .timepicker-seconds').show();
  706. },
  707. selectHour: function (e) {
  708. var hour = parseInt($(e.target).text(), 10);
  709. if (!picker.use24hours) {
  710. if (picker.date.hours() >= 12) {
  711. if (hour !== 12) {
  712. hour += 12;
  713. }
  714. } else {
  715. if (hour === 12) {
  716. hour = 0;
  717. }
  718. }
  719. }
  720. picker.date.hours(hour);
  721. actions.showPicker.call(picker);
  722. },
  723. selectMinute: function (e) {
  724. picker.date.minutes(parseInt($(e.target).text(), 10));
  725. actions.showPicker.call(picker);
  726. },
  727. selectSecond: function (e) {
  728. picker.date.seconds(parseInt($(e.target).text(), 10));
  729. actions.showPicker.call(picker);
  730. }
  731. },
  732. doAction = function (e) {
  733. var oldDate = moment(picker.date),
  734. action = $(e.currentTarget).data('action'),
  735. rv = actions[action].apply(picker, arguments);
  736. stopEvent(e);
  737. if (!picker.date) {
  738. picker.date = moment({y: 1970});
  739. }
  740. set();
  741. fillTime();
  742. notifyChange(oldDate, e.type);
  743. return rv;
  744. },
  745. stopEvent = function (e) {
  746. e.stopPropagation();
  747. e.preventDefault();
  748. },
  749. keydown = function (e) {
  750. if (e.keyCode === 27) { // allow escape to hide picker
  751. picker.hide();
  752. }
  753. },
  754. change = function (e) {
  755. moment.locale(picker.options.language);
  756. var input = $(e.target), oldDate = moment(picker.date), newDate = moment(input.val(), picker.format, picker.options.useStrict);
  757. if (newDate.isValid() && !isInDisableDates(newDate) && isInEnableDates(newDate)) {
  758. update();
  759. picker.setValue(newDate);
  760. notifyChange(oldDate, e.type);
  761. set();
  762. }
  763. else {
  764. picker.viewDate = oldDate;
  765. picker.unset = true;
  766. notifyChange(oldDate, e.type);
  767. notifyError(newDate);
  768. }
  769. },
  770. showMode = function (dir) {
  771. if (dir) {
  772. picker.viewMode = Math.max(picker.minViewMode, Math.min(2, picker.viewMode + dir));
  773. }
  774. picker.widget.find('.datepicker > div').hide().filter('.datepicker-' + dpGlobal.modes[picker.viewMode].clsName).show();
  775. },
  776. attachDatePickerEvents = function () {
  777. var $this, $parent, expanded, closed, collapseData;
  778. picker.widget.on('click', '.datepicker *', $.proxy(click, this)); // this handles date picker clicks
  779. picker.widget.on('click', '[data-action]', $.proxy(doAction, this)); // this handles time picker clicks
  780. picker.widget.on('mousedown', $.proxy(stopEvent, this));
  781. picker.element.on('keydown', $.proxy(keydown, this));
  782. if (picker.options.pickDate && picker.options.pickTime) {
  783. picker.widget.on('click.togglePicker', '.accordion-toggle', function (e) {
  784. e.stopPropagation();
  785. $this = $(this);
  786. $parent = $this.closest('ul');
  787. expanded = $parent.find('.in');
  788. closed = $parent.find('.collapse:not(.in)');
  789. if (expanded && expanded.length) {
  790. collapseData = expanded.data('collapse');
  791. if (collapseData && collapseData.transitioning) {
  792. return;
  793. }
  794. expanded.collapse('hide');
  795. closed.collapse('show');
  796. $this.find('span').toggleClass(picker.options.icons.time + ' ' + picker.options.icons.date);
  797. if (picker.component) {
  798. picker.component.find('span').toggleClass(picker.options.icons.time + ' ' + picker.options.icons.date);
  799. }
  800. }
  801. });
  802. }
  803. if (picker.isInput) {
  804. picker.element.on({
  805. 'click': $.proxy(picker.show, this),
  806. 'focus': $.proxy(picker.show, this),
  807. 'change': $.proxy(change, this),
  808. 'blur': $.proxy(picker.hide, this)
  809. });
  810. } else {
  811. picker.element.on({
  812. 'change': $.proxy(change, this)
  813. }, 'input');
  814. if (picker.component) {
  815. picker.component.on('click', $.proxy(picker.show, this));
  816. picker.component.on('mousedown', $.proxy(stopEvent, this));
  817. } else {
  818. picker.element.on('click', $.proxy(picker.show, this));
  819. }
  820. }
  821. },
  822. attachDatePickerGlobalEvents = function () {
  823. $(window).on(
  824. 'resize.datetimepicker' + picker.id, $.proxy(place, this));
  825. if (!picker.isInput) {
  826. $(document).on(
  827. 'mousedown.datetimepicker' + picker.id, $.proxy(picker.hide, this));
  828. }
  829. },
  830. detachDatePickerEvents = function () {
  831. picker.widget.off('click', '.datepicker *', picker.click);
  832. picker.widget.off('click', '[data-action]');
  833. picker.widget.off('mousedown', picker.stopEvent);
  834. if (picker.options.pickDate && picker.options.pickTime) {
  835. picker.widget.off('click.togglePicker');
  836. }
  837. if (picker.isInput) {
  838. picker.element.off({
  839. 'focus': picker.show,
  840. 'change': change,
  841. 'click': picker.show,
  842. 'blur' : picker.hide
  843. });
  844. } else {
  845. picker.element.off({
  846. 'change': change
  847. }, 'input');
  848. if (picker.component) {
  849. picker.component.off('click', picker.show);
  850. picker.component.off('mousedown', picker.stopEvent);
  851. } else {
  852. picker.element.off('click', picker.show);
  853. }
  854. }
  855. },
  856. detachDatePickerGlobalEvents = function () {
  857. $(window).off('resize.datetimepicker' + picker.id);
  858. if (!picker.isInput) {
  859. $(document).off('mousedown.datetimepicker' + picker.id);
  860. }
  861. },
  862. isInFixed = function () {
  863. if (picker.element) {
  864. var parents = picker.element.parents(), inFixed = false, i;
  865. for (i = 0; i < parents.length; i++) {
  866. if ($(parents[i]).css('position') === 'fixed') {
  867. inFixed = true;
  868. break;
  869. }
  870. }
  871. return inFixed;
  872. } else {
  873. return false;
  874. }
  875. },
  876. set = function () {
  877. moment.locale(picker.options.language);
  878. var formatted = '';
  879. if (!picker.unset) {
  880. formatted = moment(picker.date).format(picker.format);
  881. }
  882. getPickerInput().val(formatted);
  883. picker.element.data('date', formatted);
  884. if (!picker.options.pickTime) {
  885. picker.hide();
  886. }
  887. },
  888. checkDate = function (direction, unit, amount) {
  889. moment.locale(picker.options.language);
  890. var newDate;
  891. if (direction === 'add') {
  892. newDate = moment(picker.date);
  893. if (newDate.hours() === 23) {
  894. newDate.add(amount, unit);
  895. }
  896. newDate.add(amount, unit);
  897. }
  898. else {
  899. newDate = moment(picker.date).subtract(amount, unit);
  900. }
  901. if (isInDisableDates(moment(newDate.subtract(amount, unit))) || isInDisableDates(newDate)) {
  902. notifyError(newDate.format(picker.format));
  903. return;
  904. }
  905. if (direction === 'add') {
  906. picker.date.add(amount, unit);
  907. }
  908. else {
  909. picker.date.subtract(amount, unit);
  910. }
  911. picker.unset = false;
  912. },
  913. isInDisableDates = function (date, timeUnit) {
  914. moment.locale(picker.options.language);
  915. var maxDate = moment(picker.options.maxDate, picker.format, picker.options.useStrict),
  916. minDate = moment(picker.options.minDate, picker.format, picker.options.useStrict);
  917. if (timeUnit) {
  918. maxDate = maxDate.endOf(timeUnit);
  919. minDate = minDate.startOf(timeUnit);
  920. }
  921. if (date.isAfter(maxDate) || date.isBefore(minDate)) {
  922. return true;
  923. }
  924. if (picker.options.disabledDates === false) {
  925. return false;
  926. }
  927. return picker.options.disabledDates[date.format('YYYY-MM-DD')] === true;
  928. },
  929. isInEnableDates = function (date) {
  930. moment.locale(picker.options.language);
  931. if (picker.options.enabledDates === false) {
  932. return true;
  933. }
  934. return picker.options.enabledDates[date.format('YYYY-MM-DD')] === true;
  935. },
  936. indexGivenDates = function (givenDatesArray) {
  937. // Store given enabledDates and disabledDates as keys.
  938. // This way we can check their existence in O(1) time instead of looping through whole array.
  939. // (for example: picker.options.enabledDates['2014-02-27'] === true)
  940. var givenDatesIndexed = {}, givenDatesCount = 0, i;
  941. for (i = 0; i < givenDatesArray.length; i++) {
  942. if (moment.isMoment(givenDatesArray[i]) || givenDatesArray[i] instanceof Date) {
  943. dDate = moment(givenDatesArray[i]);
  944. } else {
  945. dDate = moment(givenDatesArray[i], picker.format, picker.options.useStrict);
  946. }
  947. if (dDate.isValid()) {
  948. givenDatesIndexed[dDate.format('YYYY-MM-DD')] = true;
  949. givenDatesCount++;
  950. }
  951. }
  952. if (givenDatesCount > 0) {
  953. return givenDatesIndexed;
  954. }
  955. return false;
  956. },
  957. padLeft = function (string) {
  958. string = string.toString();
  959. if (string.length >= 2) {
  960. return string;
  961. }
  962. return '0' + string;
  963. },
  964. getTemplate = function () {
  965. var
  966. headTemplate =
  967. '<thead>' +
  968. '<tr>' +
  969. '<th class="prev">&lsaquo;</th><th colspan="' + (picker.options.calendarWeeks ? '6' : '5') + '" class="picker-switch"></th><th class="next">&rsaquo;</th>' +
  970. '</tr>' +
  971. '</thead>',
  972. contTemplate =
  973. '<tbody><tr><td colspan="' + (picker.options.calendarWeeks ? '8' : '7') + '"></td></tr></tbody>',
  974. template = '<div class="datepicker-days">' +
  975. '<table class="table-condensed">' + headTemplate + '<tbody></tbody></table>' +
  976. '</div>' +
  977. '<div class="datepicker-months">' +
  978. '<table class="table-condensed">' + headTemplate + contTemplate + '</table>' +
  979. '</div>' +
  980. '<div class="datepicker-years">' +
  981. '<table class="table-condensed">' + headTemplate + contTemplate + '</table>' +
  982. '</div>',
  983. ret = '';
  984. if (picker.options.pickDate && picker.options.pickTime) {
  985. ret = '<div class="bootstrap-datetimepicker-widget' + (picker.options.sideBySide ? ' timepicker-sbs' : '') + (picker.use24hours ? ' usetwentyfour' : '') + ' dropdown-menu" style="z-index:9999 !important;">';
  986. if (picker.options.sideBySide) {
  987. ret += '<div class="row">' +
  988. '<div class="col-sm-6 datepicker">' + template + '</div>' +
  989. '<div class="col-sm-6 timepicker">' + tpGlobal.getTemplate() + '</div>' +
  990. '</div>';
  991. } else {
  992. ret += '<ul class="list-unstyled">' +
  993. '<li' + (picker.options.collapse ? ' class="collapse in"' : '') + '>' +
  994. '<div class="datepicker">' + template + '</div>' +
  995. '</li>' +
  996. '<li class="picker-switch accordion-toggle"><a class="btn" style="width:100%"><span class="' + picker.options.icons.time + '"></span></a></li>' +
  997. '<li' + (picker.options.collapse ? ' class="collapse"' : '') + '>' +
  998. '<div class="timepicker">' + tpGlobal.getTemplate() + '</div>' +
  999. '</li>' +
  1000. '</ul>';
  1001. }
  1002. ret += '</div>';
  1003. return ret;
  1004. }
  1005. if (picker.options.pickTime) {
  1006. return (
  1007. '<div class="bootstrap-datetimepicker-widget dropdown-menu">' +
  1008. '<div class="timepicker">' + tpGlobal.getTemplate() + '</div>' +
  1009. '</div>'
  1010. );
  1011. }
  1012. return (
  1013. '<div class="bootstrap-datetimepicker-widget dropdown-menu">' +
  1014. '<div class="datepicker">' + template + '</div>' +
  1015. '</div>'
  1016. );
  1017. },
  1018. dpGlobal = {
  1019. modes: [
  1020. {
  1021. clsName: 'days',
  1022. navFnc: 'month',
  1023. navStep: 1
  1024. },
  1025. {
  1026. clsName: 'months',
  1027. navFnc: 'year',
  1028. navStep: 1
  1029. },
  1030. {
  1031. clsName: 'years',
  1032. navFnc: 'year',
  1033. navStep: 10
  1034. }
  1035. ]
  1036. },
  1037. tpGlobal = {
  1038. hourTemplate: '<span data-action="showHours" data-time-component="hours" class="timepicker-hour"></span>',
  1039. minuteTemplate: '<span data-action="showMinutes" data-time-component="minutes" class="timepicker-minute"></span>',
  1040. secondTemplate: '<span data-action="showSeconds" data-time-component="seconds" class="timepicker-second"></span>'
  1041. };
  1042. tpGlobal.getTemplate = function () {
  1043. return (
  1044. '<div class="timepicker-picker">' +
  1045. '<table class="table-condensed">' +
  1046. '<tr>' +
  1047. '<td><a href="#" class="btn" data-action="incrementHours"><span class="' + picker.options.icons.up + '"></span></a></td>' +
  1048. '<td class="separator"></td>' +
  1049. '<td>' + (picker.options.useMinutes ? '<a href="#" class="btn" data-action="incrementMinutes"><span class="' + picker.options.icons.up + '"></span></a>' : '') + '</td>' +
  1050. (picker.options.useSeconds ?
  1051. '<td class="separator"></td><td><a href="#" class="btn" data-action="incrementSeconds"><span class="' + picker.options.icons.up + '"></span></a></td>' : '') +
  1052. (picker.use24hours ? '' : '<td class="separator"></td>') +
  1053. '</tr>' +
  1054. '<tr>' +
  1055. '<td>' + tpGlobal.hourTemplate + '</td> ' +
  1056. '<td class="separator">:</td>' +
  1057. '<td>' + (picker.options.useMinutes ? tpGlobal.minuteTemplate : '<span class="timepicker-minute">00</span>') + '</td> ' +
  1058. (picker.options.useSeconds ?
  1059. '<td class="separator">:</td><td>' + tpGlobal.secondTemplate + '</td>' : '') +
  1060. (picker.use24hours ? '' : '<td class="separator"></td>' +
  1061. '<td><button type="button" class="btn btn-primary" data-action="togglePeriod"></button></td>') +
  1062. '</tr>' +
  1063. '<tr>' +
  1064. '<td><a href="#" class="btn" data-action="decrementHours"><span class="' + picker.options.icons.down + '"></span></a></td>' +
  1065. '<td class="separator"></td>' +
  1066. '<td>' + (picker.options.useMinutes ? '<a href="#" class="btn" data-action="decrementMinutes"><span class="' + picker.options.icons.down + '"></span></a>' : '') + '</td>' +
  1067. (picker.options.useSeconds ?
  1068. '<td class="separator"></td><td><a href="#" class="btn" data-action="decrementSeconds"><span class="' + picker.options.icons.down + '"></span></a></td>' : '') +
  1069. (picker.use24hours ? '' : '<td class="separator"></td>') +
  1070. '</tr>' +
  1071. '</table>' +
  1072. '</div>' +
  1073. '<div class="timepicker-hours" data-action="selectHour">' +
  1074. '<table class="table-condensed"></table>' +
  1075. '</div>' +
  1076. '<div class="timepicker-minutes" data-action="selectMinute">' +
  1077. '<table class="table-condensed"></table>' +
  1078. '</div>' +
  1079. (picker.options.useSeconds ?
  1080. '<div class="timepicker-seconds" data-action="selectSecond"><table class="table-condensed"></table></div>' : '')
  1081. );
  1082. };
  1083. picker.destroy = function () {
  1084. detachDatePickerEvents();
  1085. detachDatePickerGlobalEvents();
  1086. picker.widget.remove();
  1087. picker.element.removeData('DateTimePicker');
  1088. if (picker.component) {
  1089. picker.component.removeData('DateTimePicker');
  1090. }
  1091. };
  1092. picker.show = function (e) {
  1093. if (getPickerInput().prop('disabled')) {
  1094. return;
  1095. }
  1096. if (picker.options.useCurrent) {
  1097. if (getPickerInput().val() === '') {
  1098. if (picker.options.minuteStepping !== 1) {
  1099. var mDate = moment(),
  1100. rInterval = picker.options.minuteStepping;
  1101. mDate.minutes((Math.round(mDate.minutes() / rInterval) * rInterval) % 60).seconds(0);
  1102. picker.setValue(mDate.format(picker.format));
  1103. } else {
  1104. picker.setValue(moment().format(picker.format));
  1105. }
  1106. notifyChange('', e.type);
  1107. }
  1108. }
  1109. // if this is a click event on the input field and picker is already open don't hide it
  1110. if (e && e.type === 'click' && picker.isInput && picker.widget.hasClass('picker-open')) {
  1111. return;
  1112. }
  1113. if (picker.widget.hasClass('picker-open')) {
  1114. picker.widget.hide();
  1115. picker.widget.removeClass('picker-open');
  1116. }
  1117. else {
  1118. picker.widget.show();
  1119. picker.widget.addClass('picker-open');
  1120. }
  1121. picker.height = picker.component ? picker.component.outerHeight() : picker.element.outerHeight();
  1122. place();
  1123. picker.element.trigger({
  1124. type: 'dp.show',
  1125. date: moment(picker.date)
  1126. });
  1127. attachDatePickerGlobalEvents();
  1128. if (e) {
  1129. stopEvent(e);
  1130. }
  1131. };
  1132. picker.disable = function () {
  1133. var input = getPickerInput();
  1134. if (input.prop('disabled')) {
  1135. return;
  1136. }
  1137. input.prop('disabled', true);
  1138. detachDatePickerEvents();
  1139. };
  1140. picker.enable = function () {
  1141. var input = getPickerInput();
  1142. if (!input.prop('disabled')) {
  1143. return;
  1144. }
  1145. input.prop('disabled', false);
  1146. attachDatePickerEvents();
  1147. };
  1148. picker.hide = function () {
  1149. // Ignore event if in the middle of a picker transition
  1150. var collapse = picker.widget.find('.collapse'), i, collapseData;
  1151. for (i = 0; i < collapse.length; i++) {
  1152. collapseData = collapse.eq(i).data('collapse');
  1153. if (collapseData && collapseData.transitioning) {
  1154. return;
  1155. }
  1156. }
  1157. picker.widget.hide();
  1158. picker.widget.removeClass('picker-open');
  1159. picker.viewMode = picker.startViewMode;
  1160. showMode();
  1161. picker.element.trigger({
  1162. type: 'dp.hide',
  1163. date: moment(picker.date)
  1164. });
  1165. detachDatePickerGlobalEvents();
  1166. };
  1167. picker.setValue = function (newDate) {
  1168. moment.locale(picker.options.language);
  1169. if (!newDate) {
  1170. picker.unset = true;
  1171. set();
  1172. } else {
  1173. picker.unset = false;
  1174. }
  1175. if (!moment.isMoment(newDate)) {
  1176. newDate = (newDate instanceof Date) ? moment(newDate) : moment(newDate, picker.format, picker.options.useStrict);
  1177. } else {
  1178. newDate = newDate.locale(picker.options.language);
  1179. }
  1180. if (newDate.isValid()) {
  1181. picker.date = newDate;
  1182. set();
  1183. picker.viewDate = moment({y: picker.date.year(), M: picker.date.month()});
  1184. fillDate();
  1185. fillTime();
  1186. }
  1187. else {
  1188. notifyError(newDate);
  1189. }
  1190. };
  1191. picker.getDate = function () {
  1192. if (picker.unset) {
  1193. return null;
  1194. }
  1195. return moment(picker.date);
  1196. };
  1197. picker.setDate = function (date) {
  1198. var oldDate = moment(picker.date);
  1199. if (!date) {
  1200. picker.setValue(null);
  1201. } else {
  1202. picker.setValue(date);
  1203. }
  1204. notifyChange(oldDate, 'function');
  1205. };
  1206. picker.setDisabledDates = function (dates) {
  1207. picker.options.disabledDates = indexGivenDates(dates);
  1208. if (picker.viewDate) {
  1209. update();
  1210. }
  1211. };
  1212. picker.setEnabledDates = function (dates) {
  1213. picker.options.enabledDates = indexGivenDates(dates);
  1214. if (picker.viewDate) {
  1215. update();
  1216. }
  1217. };
  1218. picker.setMaxDate = function (date) {
  1219. if (date === undefined) {
  1220. return;
  1221. }
  1222. if (moment.isMoment(date) || date instanceof Date) {
  1223. picker.options.maxDate = moment(date);
  1224. } else {
  1225. picker.options.maxDate = moment(date, picker.format, picker.options.useStrict);
  1226. }
  1227. if (picker.viewDate) {
  1228. update();
  1229. }
  1230. };
  1231. picker.setMinDate = function (date) {
  1232. if (date === undefined) {
  1233. return;
  1234. }
  1235. if (moment.isMoment(date) || date instanceof Date) {
  1236. picker.options.minDate = moment(date);
  1237. } else {
  1238. picker.options.minDate = moment(date, picker.format, picker.options.useStrict);
  1239. }
  1240. if (picker.viewDate) {
  1241. update();
  1242. }
  1243. };
  1244. init();
  1245. };
  1246. $.fn.datetimepicker = function (options) {
  1247. return this.each(function () {
  1248. var $this = $(this),
  1249. data = $this.data('DateTimePicker');
  1250. if (!data) {
  1251. $this.data('DateTimePicker', new DateTimePicker(this, options));
  1252. }
  1253. });
  1254. };
  1255. $.fn.datetimepicker.defaults = {
  1256. format: false,
  1257. pickDate: true,
  1258. pickTime: true,
  1259. useMinutes: true,
  1260. useSeconds: false,
  1261. useCurrent: true,
  1262. calendarWeeks: false,
  1263. minuteStepping: 1,
  1264. minDate: moment({y: 1900}),
  1265. maxDate: moment().add(100, 'y'),
  1266. showToday: true,
  1267. collapse: true,
  1268. language: moment.locale(),
  1269. defaultDate: '',
  1270. disabledDates: false,
  1271. enabledDates: false,
  1272. icons: {},
  1273. useStrict: false,
  1274. direction: 'auto',
  1275. sideBySide: false,
  1276. daysOfWeekDisabled: [],
  1277. widgetParent: false
  1278. };
  1279. }));