bootstrap-material-datetimepicker.js 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177
  1. (function ($, moment)
  2. {
  3. var pluginName = "bootstrapMaterialDatePicker";
  4. var pluginDataName = "plugin_" + pluginName;
  5. moment.locale('en');
  6. function Plugin(element, options)
  7. {
  8. this.currentView = 0;
  9. this.minDate;
  10. this.maxDate;
  11. this._attachedEvents = [];
  12. this.element = element;
  13. this.$element = $(element);
  14. this.params = {date: true, time: true, format: 'YYYY-MM-DD', minDate: null, maxDate: null, currentDate: null, lang: 'en', weekStart: 0, shortTime: false, clearButton: false, nowButton: false, cancelText: 'Cancel', okText: 'OK', clearText: 'Clear', nowText: 'Now', switchOnClick: false};
  15. this.params = $.fn.extend(this.params, options);
  16. this.name = "dtp_" + this.setName();
  17. this.$element.attr("data-dtp", this.name);
  18. moment.locale(this.params.lang);
  19. this.init();
  20. }
  21. $.fn[pluginName] = function (options, p)
  22. {
  23. this.each(function ()
  24. {
  25. if (!$.data(this, pluginDataName))
  26. {
  27. $.data(this, pluginDataName, new Plugin(this, options));
  28. } else
  29. {
  30. if (typeof ($.data(this, pluginDataName)[options]) === 'function')
  31. {
  32. $.data(this, pluginDataName)[options](p);
  33. }
  34. if (options === 'destroy')
  35. {
  36. delete $.data(this, pluginDataName);
  37. }
  38. }
  39. });
  40. return this;
  41. };
  42. Plugin.prototype =
  43. {
  44. init: function ()
  45. {
  46. this.initDays();
  47. this.initDates();
  48. this.initTemplate();
  49. this.initButtons();
  50. this._attachEvent($(window), 'resize', this._centerBox.bind(this));
  51. this._attachEvent(this.$dtpElement.find('.dtp-content'), 'click', this._onElementClick.bind(this));
  52. this._attachEvent(this.$dtpElement, 'click', this._onBackgroundClick.bind(this));
  53. this._attachEvent(this.$dtpElement.find('.dtp-close > a'), 'click', this._onCloseClick.bind(this));
  54. this._attachEvent(this.$element, 'focus', this._onFocus.bind(this));
  55. },
  56. initDays: function ()
  57. {
  58. this.days = [];
  59. for (var i = this.params.weekStart; this.days.length < 7; i++)
  60. {
  61. if (i > 6)
  62. {
  63. i = 0;
  64. }
  65. this.days.push(i.toString());
  66. }
  67. },
  68. initDates: function ()
  69. {
  70. if (this.$element.val().length > 0)
  71. {
  72. if (typeof (this.params.format) !== 'undefined' && this.params.format !== null)
  73. {
  74. this.currentDate = moment(this.$element.val(), this.params.format).locale(this.params.lang);
  75. } else
  76. {
  77. this.currentDate = moment(this.$element.val()).locale(this.params.lang);
  78. }
  79. } else
  80. {
  81. if (typeof (this.$element.attr('value')) !== 'undefined' && this.$element.attr('value') !== null && this.$element.attr('value') !== "")
  82. {
  83. if (typeof (this.$element.attr('value')) === 'string')
  84. {
  85. if (typeof (this.params.format) !== 'undefined' && this.params.format !== null)
  86. {
  87. this.currentDate = moment(this.$element.attr('value'), this.params.format).locale(this.params.lang);
  88. } else
  89. {
  90. this.currentDate = moment(this.$element.attr('value')).locale(this.params.lang);
  91. }
  92. }
  93. } else
  94. {
  95. if (typeof (this.params.currentDate) !== 'undefined' && this.params.currentDate !== null)
  96. {
  97. if (typeof (this.params.currentDate) === 'string')
  98. {
  99. if (typeof (this.params.format) !== 'undefined' && this.params.format !== null)
  100. {
  101. this.currentDate = moment(this.params.currentDate, this.params.format).locale(this.params.lang);
  102. } else
  103. {
  104. this.currentDate = moment(this.params.currentDate).locale(this.params.lang);
  105. }
  106. } else
  107. {
  108. if (typeof (this.params.currentDate.isValid) === 'undefined' || typeof (this.params.currentDate.isValid) !== 'function')
  109. {
  110. var x = this.params.currentDate.getTime();
  111. this.currentDate = moment(x, "x").locale(this.params.lang);
  112. } else
  113. {
  114. this.currentDate = this.params.currentDate;
  115. }
  116. }
  117. this.$element.val(this.currentDate.format(this.params.format));
  118. } else
  119. this.currentDate = moment();
  120. }
  121. }
  122. if (typeof (this.params.minDate) !== 'undefined' && this.params.minDate !== null)
  123. {
  124. if (typeof (this.params.minDate) === 'string')
  125. {
  126. if (typeof (this.params.format) !== 'undefined' && this.params.format !== null)
  127. {
  128. this.minDate = moment(this.params.minDate, this.params.format).locale(this.params.lang);
  129. } else
  130. {
  131. this.minDate = moment(this.params.minDate).locale(this.params.lang);
  132. }
  133. } else
  134. {
  135. if (typeof (this.params.minDate.isValid) === 'undefined' || typeof (this.params.minDate.isValid) !== 'function')
  136. {
  137. var x = this.params.minDate.getTime();
  138. this.minDate = moment(x, "x").locale(this.params.lang);
  139. } else
  140. {
  141. this.minDate = this.params.minDate;
  142. }
  143. }
  144. } else if (this.params.minDate === null)
  145. {
  146. this.minDate = null;
  147. }
  148. if (typeof (this.params.maxDate) !== 'undefined' && this.params.maxDate !== null)
  149. {
  150. if (typeof (this.params.maxDate) === 'string')
  151. {
  152. if (typeof (this.params.format) !== 'undefined' && this.params.format !== null)
  153. {
  154. this.maxDate = moment(this.params.maxDate, this.params.format).locale(this.params.lang);
  155. } else
  156. {
  157. this.maxDate = moment(this.params.maxDate).locale(this.params.lang);
  158. }
  159. } else
  160. {
  161. if (typeof (this.params.maxDate.isValid) === 'undefined' || typeof (this.params.maxDate.isValid) !== 'function')
  162. {
  163. var x = this.params.maxDate.getTime();
  164. this.maxDate = moment(x, "x").locale(this.params.lang);
  165. } else
  166. {
  167. this.maxDate = this.params.maxDate;
  168. }
  169. }
  170. } else if (this.params.maxDate === null)
  171. {
  172. this.maxDate = null;
  173. }
  174. if (!this.isAfterMinDate(this.currentDate))
  175. {
  176. this.currentDate = moment(this.minDate);
  177. }
  178. if (!this.isBeforeMaxDate(this.currentDate))
  179. {
  180. this.currentDate = moment(this.maxDate);
  181. }
  182. },
  183. initTemplate: function ()
  184. {
  185. this.template = '<div class="dtp hidden" id="' + this.name + '">' +
  186. '<div class="dtp-content">' +
  187. '<div class="dtp-date-view">' +
  188. '<header class="dtp-header">' +
  189. '<div class="dtp-actual-day">Lundi</div>' +
  190. '<div class="dtp-close"><a href="javascript:void(0);"><i class="material-icons">clear</i></</div>' +
  191. '</header>' +
  192. '<div class="dtp-date hidden">' +
  193. '<div>' +
  194. '<div class="left center p10">' +
  195. '<a href="javascript:void(0);" class="dtp-select-month-before"><i class="material-icons">chevron_left</i></a>' +
  196. '</div>' +
  197. '<div class="dtp-actual-month p80">MAR</div>' +
  198. '<div class="right center p10">' +
  199. '<a href="javascript:void(0);" class="dtp-select-month-after"><i class="material-icons">chevron_right</i></a>' +
  200. '</div>' +
  201. '<div class="clearfix"></div>' +
  202. '</div>' +
  203. '<div class="dtp-actual-num">13</div>' +
  204. '<div>' +
  205. '<div class="left center p10">' +
  206. '<a href="javascript:void(0);" class="dtp-select-year-before"><i class="material-icons">chevron_left</i></a>' +
  207. '</div>' +
  208. '<div class="dtp-actual-year p80">2014</div>' +
  209. '<div class="right center p10">' +
  210. '<a href="javascript:void(0);" class="dtp-select-year-after"><i class="material-icons">chevron_right</i></a>' +
  211. '</div>' +
  212. '<div class="clearfix"></div>' +
  213. '</div>' +
  214. '</div>' +
  215. '<div class="dtp-time hidden">' +
  216. '<div class="dtp-actual-maxtime">23:55</div>' +
  217. '</div>' +
  218. '<div class="dtp-picker">' +
  219. '<div class="dtp-picker-calendar"></div>' +
  220. '<div class="dtp-picker-datetime hidden">' +
  221. '<div class="dtp-actual-meridien">' +
  222. '<div class="left p20">' +
  223. '<a class="dtp-meridien-am" href="javascript:void(0);">AM</a>' +
  224. '</div>' +
  225. '<div class="dtp-actual-time p60"></div>' +
  226. '<div class="right p20">' +
  227. '<a class="dtp-meridien-pm" href="javascript:void(0);">PM</a>' +
  228. '</div>' +
  229. '<div class="clearfix"></div>' +
  230. '</div>' +
  231. '<div id="dtp-svg-clock">' +
  232. '</div>' +
  233. '</div>' +
  234. '</div>' +
  235. '</div>' +
  236. '<div class="dtp-buttons">' +
  237. '<button class="dtp-btn-now btn btn-flat hidden">' + this.params.nowText + '</button>' +
  238. '<button class="dtp-btn-clear btn btn-flat hidden">' + this.params.clearText + '</button>' +
  239. '<button class="dtp-btn-cancel btn btn-flat">' + this.params.cancelText + '</button>' +
  240. '<button class="dtp-btn-ok btn btn-flat">' + this.params.okText + '</button>' +
  241. '<div class="clearfix"></div>' +
  242. '</div>' +
  243. '</div>' +
  244. '</div>';
  245. if ($('body').find("#" + this.name).length <= 0)
  246. {
  247. $('body').append(this.template);
  248. if (this)
  249. this.dtpElement = $('body').find("#" + this.name);
  250. this.$dtpElement = $(this.dtpElement);
  251. }
  252. },
  253. initButtons: function ()
  254. {
  255. this._attachEvent(this.$dtpElement.find('.dtp-btn-cancel'), 'click', this._onCancelClick.bind(this));
  256. this._attachEvent(this.$dtpElement.find('.dtp-btn-ok'), 'click', this._onOKClick.bind(this));
  257. this._attachEvent(this.$dtpElement.find('a.dtp-select-month-before'), 'click', this._onMonthBeforeClick.bind(this));
  258. this._attachEvent(this.$dtpElement.find('a.dtp-select-month-after'), 'click', this._onMonthAfterClick.bind(this));
  259. this._attachEvent(this.$dtpElement.find('a.dtp-select-year-before'), 'click', this._onYearBeforeClick.bind(this));
  260. this._attachEvent(this.$dtpElement.find('a.dtp-select-year-after'), 'click', this._onYearAfterClick.bind(this));
  261. if (this.params.clearButton === true)
  262. {
  263. this._attachEvent(this.$dtpElement.find('.dtp-btn-clear'), 'click', this._onClearClick.bind(this));
  264. this.$dtpElement.find('.dtp-btn-clear').removeClass('hidden');
  265. }
  266. if (this.params.nowButton === true)
  267. {
  268. this._attachEvent(this.$dtpElement.find('.dtp-btn-now'), 'click', this._onNowClick.bind(this));
  269. this.$dtpElement.find('.dtp-btn-now').removeClass('hidden');
  270. }
  271. if ((this.params.nowButton === true) && (this.params.clearButton === true))
  272. {
  273. this.$dtpElement.find('.dtp-btn-clear, .dtp-btn-now, .dtp-btn-cancel, .dtp-btn-ok').addClass('btn-xs');
  274. } else if ((this.params.nowButton === true) || (this.params.clearButton === true))
  275. {
  276. this.$dtpElement.find('.dtp-btn-clear, .dtp-btn-now, .dtp-btn-cancel, .dtp-btn-ok').addClass('btn-sm');
  277. }
  278. },
  279. initMeridienButtons: function ()
  280. {
  281. this.$dtpElement.find('a.dtp-meridien-am').off('click').on('click', this._onSelectAM.bind(this));
  282. this.$dtpElement.find('a.dtp-meridien-pm').off('click').on('click', this._onSelectPM.bind(this));
  283. },
  284. initDate: function (d)
  285. {
  286. this.currentView = 0;
  287. this.$dtpElement.find('.dtp-picker-calendar').removeClass('hidden');
  288. this.$dtpElement.find('.dtp-picker-datetime').addClass('hidden');
  289. var _date = ((typeof (this.currentDate) !== 'undefined' && this.currentDate !== null) ? this.currentDate : null);
  290. var _calendar = this.generateCalendar(this.currentDate);
  291. if (typeof (_calendar.week) !== 'undefined' && typeof (_calendar.days) !== 'undefined')
  292. {
  293. var _template = this.constructHTMLCalendar(_date, _calendar);
  294. this.$dtpElement.find('a.dtp-select-day').off('click');
  295. this.$dtpElement.find('.dtp-picker-calendar').html(_template);
  296. this.$dtpElement.find('a.dtp-select-day').on('click', this._onSelectDate.bind(this));
  297. this.toggleButtons(_date);
  298. }
  299. this._centerBox();
  300. this.showDate(_date);
  301. },
  302. initHours: function ()
  303. {
  304. this.currentView = 1;
  305. this.showTime(this.currentDate);
  306. this.initMeridienButtons();
  307. if (this.currentDate.hour() < 12)
  308. {
  309. this.$dtpElement.find('a.dtp-meridien-am').click();
  310. } else
  311. {
  312. this.$dtpElement.find('a.dtp-meridien-pm').click();
  313. }
  314. var hFormat = ((this.params.shortTime) ? 'h' : 'H');
  315. this.$dtpElement.find('.dtp-picker-datetime').removeClass('hidden');
  316. this.$dtpElement.find('.dtp-picker-calendar').addClass('hidden');
  317. var svgClockElement = this.createSVGClock(true);
  318. for (var i = 0; i < 12; i++)
  319. {
  320. var x = -(162 * (Math.sin(-Math.PI * 2 * (i / 12))));
  321. var y = -(162 * (Math.cos(-Math.PI * 2 * (i / 12))));
  322. var fill = ((this.currentDate.format(hFormat) == i) ? "#007d72" : 'transparent');
  323. var color = ((this.currentDate.format(hFormat) == i) ? "#fff" : '#000');
  324. var svgHourCircle = this.createSVGElement("circle", {'id': 'h-' + i, 'class': 'dtp-select-hour', 'style': 'cursor:pointer', r: '30', cx: x, cy: y, fill: fill, 'data-hour': i});
  325. var svgHourText = this.createSVGElement("text", {'id': 'th-' + i, 'class': 'dtp-select-hour-text', 'text-anchor': 'middle', 'style': 'cursor:pointer', 'font-weight': 'bold', 'font-size': '20', x: x, y: y + 7, fill: color, 'data-hour': i});
  326. svgHourText.textContent = ((i === 0) ? ((this.params.shortTime) ? 12 : i) : i);
  327. if (!this.toggleTime(i, true))
  328. {
  329. svgHourCircle.className += " disabled";
  330. svgHourText.className += " disabled";
  331. svgHourText.setAttribute('fill', '#bdbdbd');
  332. } else
  333. {
  334. svgHourCircle.addEventListener('click', this._onSelectHour.bind(this));
  335. svgHourText.addEventListener('click', this._onSelectHour.bind(this));
  336. }
  337. svgClockElement.appendChild(svgHourCircle)
  338. svgClockElement.appendChild(svgHourText)
  339. }
  340. if (!this.params.shortTime)
  341. {
  342. for (var i = 0; i < 12; i++)
  343. {
  344. var x = -(110 * (Math.sin(-Math.PI * 2 * (i / 12))));
  345. var y = -(110 * (Math.cos(-Math.PI * 2 * (i / 12))));
  346. var fill = ((this.currentDate.format(hFormat) == (i + 12)) ? "#007d72" : 'transparent');
  347. var color = ((this.currentDate.format(hFormat) == (i + 12)) ? "#fff" : '#000');
  348. var svgHourCircle = this.createSVGElement("circle", {'id': 'h-' + (i + 12), 'class': 'dtp-select-hour', 'style': 'cursor:pointer', r: '30', cx: x, cy: y, fill: fill, 'data-hour': (i + 12)});
  349. var svgHourText = this.createSVGElement("text", {'id': 'th-' + (i + 12), 'class': 'dtp-select-hour-text', 'text-anchor': 'middle', 'style': 'cursor:pointer', 'font-weight': 'bold', 'font-size': '22', x: x, y: y + 7, fill: color, 'data-hour': (i + 12)});
  350. svgHourText.textContent = i + 12;
  351. if (!this.toggleTime(i + 12, true))
  352. {
  353. svgHourCircle.className += " disabled";
  354. svgHourText.className += " disabled";
  355. svgHourText.setAttribute('fill', '#bdbdbd');
  356. } else
  357. {
  358. svgHourCircle.addEventListener('click', this._onSelectHour.bind(this));
  359. svgHourText.addEventListener('click', this._onSelectHour.bind(this));
  360. }
  361. svgClockElement.appendChild(svgHourCircle)
  362. svgClockElement.appendChild(svgHourText)
  363. }
  364. this.$dtpElement.find('a.dtp-meridien-am').addClass('hidden');
  365. this.$dtpElement.find('a.dtp-meridien-pm').addClass('hidden');
  366. }
  367. this._centerBox();
  368. },
  369. initMinutes: function ()
  370. {
  371. this.currentView = 2;
  372. this.showTime(this.currentDate);
  373. this.initMeridienButtons();
  374. if (this.currentDate.hour() < 12)
  375. {
  376. this.$dtpElement.find('a.dtp-meridien-am').click();
  377. } else
  378. {
  379. this.$dtpElement.find('a.dtp-meridien-pm').click();
  380. }
  381. this.$dtpElement.find('.dtp-picker-calendar').addClass('hidden');
  382. this.$dtpElement.find('.dtp-picker-datetime').removeClass('hidden');
  383. var svgClockElement = this.createSVGClock(false);
  384. for (var i = 0; i < 60; i++)
  385. {
  386. var s = ((i % 5 === 0) ? 162 : 158);
  387. var r = ((i % 5 === 0) ? 30 : 20);
  388. var x = -(s * (Math.sin(-Math.PI * 2 * (i / 60))));
  389. var y = -(s * (Math.cos(-Math.PI * 2 * (i / 60))));
  390. var color = ((this.currentDate.format("m") == i) ? "#007d72" : 'transparent');
  391. var svgMinuteCircle = this.createSVGElement("circle", {'id': 'm-' + i, 'class': 'dtp-select-minute', 'style': 'cursor:pointer', r: r, cx: x, cy: y, fill: color, 'data-minute': i});
  392. if (!this.toggleTime(i, false))
  393. {
  394. svgMinuteCircle.className += " disabled";
  395. } else
  396. {
  397. svgMinuteCircle.addEventListener('click', this._onSelectMinute.bind(this));
  398. }
  399. svgClockElement.appendChild(svgMinuteCircle)
  400. }
  401. for (var i = 0; i < 60; i++)
  402. {
  403. if ((i % 5) === 0)
  404. {
  405. var x = -(162 * (Math.sin(-Math.PI * 2 * (i / 60))));
  406. var y = -(162 * (Math.cos(-Math.PI * 2 * (i / 60))));
  407. var color = ((this.currentDate.format("m") == i) ? "#fff" : '#000');
  408. var svgMinuteText = this.createSVGElement("text", {'id': 'tm-' + i, 'class': 'dtp-select-minute-text', 'text-anchor': 'middle', 'style': 'cursor:pointer', 'font-weight': 'bold', 'font-size': '20', x: x, y: y + 7, fill: color, 'data-minute': i});
  409. svgMinuteText.textContent = i;
  410. if (!this.toggleTime(i, false))
  411. {
  412. svgMinuteText.className += " disabled";
  413. svgMinuteText.setAttribute('fill', '#bdbdbd');
  414. } else
  415. {
  416. svgMinuteText.addEventListener('click', this._onSelectMinute.bind(this));
  417. }
  418. svgClockElement.appendChild(svgMinuteText)
  419. }
  420. }
  421. this._centerBox();
  422. },
  423. animateHands: function ()
  424. {
  425. var H = this.currentDate.hour();
  426. var M = this.currentDate.minute();
  427. var hh = this.$dtpElement.find('.hour-hand');
  428. hh[0].setAttribute('transform', "rotate(" + 360 * H / 12 + ")");
  429. var mh = this.$dtpElement.find('.minute-hand');
  430. mh[0].setAttribute('transform', "rotate(" + 360 * M / 60 + ")");
  431. },
  432. createSVGClock: function (isHour)
  433. {
  434. var hl = ((this.params.shortTime) ? -120 : -90);
  435. var svgElement = this.createSVGElement("svg", {class: 'svg-clock', viewBox: '0,0,400,400'});
  436. var svgGElement = this.createSVGElement("g", {transform: 'translate(200,200) '});
  437. var svgClockFace = this.createSVGElement("circle", {r: '192', fill: '#eee', stroke: '#bdbdbd', 'stroke-width': 2});
  438. var svgClockCenter = this.createSVGElement("circle", {r: '15', fill: '#757575'});
  439. svgGElement.appendChild(svgClockFace)
  440. if (isHour)
  441. {
  442. var svgMinuteHand = this.createSVGElement("line", {class: 'minute-hand', x1: 0, y1: 0, x2: 0, y2: -150, stroke: '#bdbdbd', 'stroke-width': 2});
  443. var svgHourHand = this.createSVGElement("line", {class: 'hour-hand', x1: 0, y1: 0, x2: 0, y2: hl, stroke: '#007d72', 'stroke-width': 8});
  444. svgGElement.appendChild(svgMinuteHand);
  445. svgGElement.appendChild(svgHourHand);
  446. } else
  447. {
  448. var svgMinuteHand = this.createSVGElement("line", {class: 'minute-hand', x1: 0, y1: 0, x2: 0, y2: -150, stroke: '#007d72', 'stroke-width': 2});
  449. var svgHourHand = this.createSVGElement("line", {class: 'hour-hand', x1: 0, y1: 0, x2: 0, y2: hl, stroke: '#bdbdbd', 'stroke-width': 8});
  450. svgGElement.appendChild(svgHourHand);
  451. svgGElement.appendChild(svgMinuteHand);
  452. }
  453. svgGElement.appendChild(svgClockCenter)
  454. svgElement.appendChild(svgGElement)
  455. this.$dtpElement.find("#dtp-svg-clock").empty();
  456. this.$dtpElement.find("#dtp-svg-clock")[0].appendChild(svgElement);
  457. this.animateHands();
  458. return svgGElement;
  459. },
  460. createSVGElement: function (tag, attrs)
  461. {
  462. var el = document.createElementNS('http://www.w3.org/2000/svg', tag);
  463. for (var k in attrs)
  464. {
  465. el.setAttribute(k, attrs[k]);
  466. }
  467. return el;
  468. },
  469. isAfterMinDate: function (date, checkHour, checkMinute)
  470. {
  471. var _return = true;
  472. if (typeof (this.minDate) !== 'undefined' && this.minDate !== null)
  473. {
  474. var _minDate = moment(this.minDate);
  475. var _date = moment(date);
  476. if (!checkHour && !checkMinute)
  477. {
  478. _minDate.hour(0);
  479. _minDate.minute(0);
  480. _date.hour(0);
  481. _date.minute(0);
  482. }
  483. _minDate.second(0);
  484. _date.second(0);
  485. _minDate.millisecond(0);
  486. _date.millisecond(0);
  487. if (!checkMinute)
  488. {
  489. _date.minute(0);
  490. _minDate.minute(0);
  491. _return = (parseInt(_date.format("X")) >= parseInt(_minDate.format("X")));
  492. } else
  493. {
  494. _return = (parseInt(_date.format("X")) >= parseInt(_minDate.format("X")));
  495. }
  496. }
  497. return _return;
  498. },
  499. isBeforeMaxDate: function (date, checkTime, checkMinute)
  500. {
  501. var _return = true;
  502. if (typeof (this.maxDate) !== 'undefined' && this.maxDate !== null)
  503. {
  504. var _maxDate = moment(this.maxDate);
  505. var _date = moment(date);
  506. if (!checkTime && !checkMinute)
  507. {
  508. _maxDate.hour(0);
  509. _maxDate.minute(0);
  510. _date.hour(0);
  511. _date.minute(0);
  512. }
  513. _maxDate.second(0);
  514. _date.second(0);
  515. _maxDate.millisecond(0);
  516. _date.millisecond(0);
  517. if (!checkMinute)
  518. {
  519. _date.minute(0);
  520. _maxDate.minute(0);
  521. _return = (parseInt(_date.format("X")) <= parseInt(_maxDate.format("X")));
  522. } else
  523. {
  524. _return = (parseInt(_date.format("X")) <= parseInt(_maxDate.format("X")));
  525. }
  526. }
  527. return _return;
  528. },
  529. rotateElement: function (el, deg)
  530. {
  531. $(el).css
  532. ({
  533. WebkitTransform: 'rotate(' + deg + 'deg)',
  534. '-moz-transform': 'rotate(' + deg + 'deg)'
  535. });
  536. },
  537. showDate: function (date)
  538. {
  539. if (date)
  540. {
  541. this.$dtpElement.find('.dtp-actual-day').html(date.locale(this.params.lang).format('dddd'));
  542. this.$dtpElement.find('.dtp-actual-month').html(date.locale(this.params.lang).format('MMM').toUpperCase());
  543. this.$dtpElement.find('.dtp-actual-num').html(date.locale(this.params.lang).format('DD'));
  544. this.$dtpElement.find('.dtp-actual-year').html(date.locale(this.params.lang).format('YYYY'));
  545. }
  546. },
  547. showTime: function (date)
  548. {
  549. if (date)
  550. {
  551. var minutes = date.minute();
  552. var content = ((this.params.shortTime) ? date.format('hh') : date.format('HH')) + ':' + ((minutes.toString().length == 2) ? minutes : '0' + minutes) + ((this.params.shortTime) ? ' ' + date.format('A') : '');
  553. if (this.params.date)
  554. this.$dtpElement.find('.dtp-actual-time').html(content);
  555. else
  556. {
  557. if (this.params.shortTime)
  558. this.$dtpElement.find('.dtp-actual-day').html(date.format('A'));
  559. else
  560. this.$dtpElement.find('.dtp-actual-day').html('&nbsp;');
  561. this.$dtpElement.find('.dtp-actual-maxtime').html(content);
  562. }
  563. }
  564. },
  565. selectDate: function (date)
  566. {
  567. if (date)
  568. {
  569. this.currentDate.date(date);
  570. this.showDate(this.currentDate);
  571. this.$element.trigger('dateSelected', this.currentDate);
  572. }
  573. },
  574. generateCalendar: function (date)
  575. {
  576. var _calendar = {};
  577. if (date !== null)
  578. {
  579. var startOfMonth = moment(date).locale(this.params.lang).startOf('month');
  580. var endOfMonth = moment(date).locale(this.params.lang).endOf('month');
  581. var iNumDay = startOfMonth.format('d');
  582. _calendar.week = this.days;
  583. _calendar.days = [];
  584. for (var i = startOfMonth.date(); i <= endOfMonth.date(); i++)
  585. {
  586. if (i === startOfMonth.date())
  587. {
  588. var iWeek = _calendar.week.indexOf(iNumDay.toString());
  589. if (iWeek > 0)
  590. {
  591. for (var x = 0; x < iWeek; x++)
  592. {
  593. _calendar.days.push(0);
  594. }
  595. }
  596. }
  597. _calendar.days.push(moment(startOfMonth).locale(this.params.lang).date(i));
  598. }
  599. }
  600. return _calendar;
  601. },
  602. constructHTMLCalendar: function (date, calendar)
  603. {
  604. var _template = "";
  605. _template += '<div class="dtp-picker-month">' + date.locale(this.params.lang).format('MMMM YYYY') + '</div>';
  606. _template += '<table class="table dtp-picker-days"><thead>';
  607. for (var i = 0; i < calendar.week.length; i++)
  608. {
  609. _template += '<th>' + moment(parseInt(calendar.week[i]), "d").locale(this.params.lang).format("dd").substring(0, 1) + '</th>';
  610. }
  611. _template += '</thead>';
  612. _template += '<tbody><tr>';
  613. for (var i = 0; i < calendar.days.length; i++)
  614. {
  615. if (i % 7 == 0)
  616. _template += '</tr><tr>';
  617. _template += '<td data-date="' + moment(calendar.days[i]).locale(this.params.lang).format("D") + '">';
  618. if (calendar.days[i] != 0)
  619. {
  620. if (this.isBeforeMaxDate(moment(calendar.days[i]), false, false) === false || this.isAfterMinDate(moment(calendar.days[i]), false, false) === false)
  621. {
  622. _template += '<span class="dtp-select-day">' + moment(calendar.days[i]).locale(this.params.lang).format("DD") + '</span>';
  623. } else
  624. {
  625. if (moment(calendar.days[i]).locale(this.params.lang).format("DD") === moment(this.currentDate).locale(this.params.lang).format("DD"))
  626. {
  627. _template += '<a href="javascript:void(0);" class="dtp-select-day selected">' + moment(calendar.days[i]).locale(this.params.lang).format("DD") + '</a>';
  628. } else
  629. {
  630. _template += '<a href="javascript:void(0);" class="dtp-select-day">' + moment(calendar.days[i]).locale(this.params.lang).format("DD") + '</a>';
  631. }
  632. }
  633. _template += '</td>';
  634. }
  635. }
  636. _template += '</tr></tbody></table>';
  637. return _template;
  638. },
  639. setName: function ()
  640. {
  641. var text = "";
  642. var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  643. for (var i = 0; i < 5; i++)
  644. {
  645. text += possible.charAt(Math.floor(Math.random() * possible.length));
  646. }
  647. return text;
  648. },
  649. isPM: function ()
  650. {
  651. return this.$dtpElement.find('a.dtp-meridien-pm').hasClass('selected');
  652. },
  653. setElementValue: function ()
  654. {
  655. this.$element.trigger('beforeChange', this.currentDate);
  656. if (typeof ($.material) !== 'undefined')
  657. {
  658. this.$element.removeClass('empty');
  659. }
  660. this.$element.val(moment(this.currentDate).locale(this.params.lang).format(this.params.format));
  661. this.$element.trigger('change', this.currentDate);
  662. },
  663. toggleButtons: function (date)
  664. {
  665. if (date && date.isValid())
  666. {
  667. var startOfMonth = moment(date).locale(this.params.lang).startOf('month');
  668. var endOfMonth = moment(date).locale(this.params.lang).endOf('month');
  669. if (!this.isAfterMinDate(startOfMonth, false, false))
  670. {
  671. this.$dtpElement.find('a.dtp-select-month-before').addClass('invisible');
  672. } else
  673. {
  674. this.$dtpElement.find('a.dtp-select-month-before').removeClass('invisible');
  675. }
  676. if (!this.isBeforeMaxDate(endOfMonth, false, false))
  677. {
  678. this.$dtpElement.find('a.dtp-select-month-after').addClass('invisible');
  679. } else
  680. {
  681. this.$dtpElement.find('a.dtp-select-month-after').removeClass('invisible');
  682. }
  683. var startOfYear = moment(date).locale(this.params.lang).startOf('year');
  684. var endOfYear = moment(date).locale(this.params.lang).endOf('year');
  685. if (!this.isAfterMinDate(startOfYear, false, false))
  686. {
  687. this.$dtpElement.find('a.dtp-select-year-before').addClass('invisible');
  688. } else
  689. {
  690. this.$dtpElement.find('a.dtp-select-year-before').removeClass('invisible');
  691. }
  692. if (!this.isBeforeMaxDate(endOfYear, false, false))
  693. {
  694. this.$dtpElement.find('a.dtp-select-year-after').addClass('invisible');
  695. } else
  696. {
  697. this.$dtpElement.find('a.dtp-select-year-after').removeClass('invisible');
  698. }
  699. }
  700. },
  701. toggleTime: function (value, isHours)
  702. {
  703. var result = false;
  704. if (isHours)
  705. {
  706. var _date = moment(this.currentDate);
  707. _date.hour(this.convertHours(value)).minute(0).second(0);
  708. result = !(this.isAfterMinDate(_date, true, false) === false || this.isBeforeMaxDate(_date, true, false) === false);
  709. } else
  710. {
  711. var _date = moment(this.currentDate);
  712. _date.minute(value).second(0);
  713. result = !(this.isAfterMinDate(_date, true, true) === false || this.isBeforeMaxDate(_date, true, true) === false);
  714. }
  715. return result;
  716. },
  717. _attachEvent: function (el, ev, fn)
  718. {
  719. el.on(ev, null, null, fn);
  720. this._attachedEvents.push([el, ev, fn]);
  721. },
  722. _detachEvents: function ()
  723. {
  724. for (var i = this._attachedEvents.length - 1; i >= 0; i--)
  725. {
  726. this._attachedEvents[i][0].off(this._attachedEvents[i][1], this._attachedEvents[i][2]);
  727. this._attachedEvents.splice(i, 1);
  728. }
  729. },
  730. _onFocus: function ()
  731. {
  732. this.currentView = 0;
  733. this.$element.blur();
  734. this.initDates();
  735. this.show();
  736. if (this.params.date)
  737. {
  738. this.$dtpElement.find('.dtp-date').removeClass('hidden');
  739. this.initDate();
  740. } else
  741. {
  742. if (this.params.time)
  743. {
  744. this.$dtpElement.find('.dtp-time').removeClass('hidden');
  745. this.initHours();
  746. }
  747. }
  748. },
  749. _onBackgroundClick: function (e)
  750. {
  751. e.stopPropagation();
  752. this.hide();
  753. },
  754. _onElementClick: function (e)
  755. {
  756. e.stopPropagation();
  757. },
  758. _onKeydown: function (e)
  759. {
  760. if (e.which === 27)
  761. {
  762. this.hide();
  763. }
  764. },
  765. _onCloseClick: function ()
  766. {
  767. this.hide();
  768. },
  769. _onClearClick: function ()
  770. {
  771. this.currentDate = null;
  772. this.$element.trigger('beforeChange', this.currentDate);
  773. this.hide();
  774. if (typeof ($.material) !== 'undefined')
  775. {
  776. this.$element.addClass('empty');
  777. }
  778. this.$element.val('');
  779. this.$element.trigger('change', this.currentDate);
  780. },
  781. _onNowClick: function ()
  782. {
  783. this.currentDate = moment();
  784. if (this.params.date === true)
  785. {
  786. this.showDate(this.currentDate);
  787. if (this.currentView === 0)
  788. {
  789. this.initDate();
  790. }
  791. }
  792. if (this.params.time === true)
  793. {
  794. this.showTime(this.currentDate);
  795. switch (this.currentView)
  796. {
  797. case 1 :
  798. this.initHours();
  799. break;
  800. case 2 :
  801. this.initMinutes();
  802. break;
  803. }
  804. this.animateHands();
  805. }
  806. },
  807. _onOKClick: function ()
  808. {
  809. switch (this.currentView)
  810. {
  811. case 0:
  812. if (this.params.time === true)
  813. {
  814. this.initHours();
  815. } else
  816. {
  817. this.setElementValue();
  818. this.hide();
  819. }
  820. break;
  821. case 1:
  822. this.initMinutes();
  823. break;
  824. case 2:
  825. this.setElementValue();
  826. this.hide();
  827. break;
  828. }
  829. },
  830. _onCancelClick: function ()
  831. {
  832. if (this.params.time)
  833. {
  834. switch (this.currentView)
  835. {
  836. case 0:
  837. this.hide();
  838. break;
  839. case 1:
  840. if (this.params.date)
  841. {
  842. this.initDate();
  843. } else
  844. {
  845. this.hide();
  846. }
  847. break;
  848. case 2:
  849. this.initHours();
  850. break;
  851. }
  852. } else
  853. {
  854. this.hide();
  855. }
  856. },
  857. _onMonthBeforeClick: function ()
  858. {
  859. this.currentDate.subtract(1, 'months');
  860. this.initDate(this.currentDate);
  861. },
  862. _onMonthAfterClick: function ()
  863. {
  864. this.currentDate.add(1, 'months');
  865. this.initDate(this.currentDate);
  866. },
  867. _onYearBeforeClick: function ()
  868. {
  869. this.currentDate.subtract(1, 'years');
  870. this.initDate(this.currentDate);
  871. },
  872. _onYearAfterClick: function ()
  873. {
  874. this.currentDate.add(1, 'years');
  875. this.initDate(this.currentDate);
  876. },
  877. _onSelectDate: function (e)
  878. {
  879. this.$dtpElement.find('a.dtp-select-day').removeClass('selected');
  880. $(e.currentTarget).addClass('selected');
  881. this.selectDate($(e.currentTarget).parent().data("date"));
  882. if (this.params.switchOnClick === true && this.params.time === true)
  883. setTimeout(this.initHours.bind(this), 200);
  884. if(this.params.switchOnClick === true && this.params.time === false) {
  885. setTimeout(this._onOKClick.bind(this), 200);
  886. }
  887. },
  888. _onSelectHour: function (e)
  889. {
  890. if (!$(e.target).hasClass('disabled'))
  891. {
  892. var value = $(e.target).data('hour');
  893. var parent = $(e.target).parent();
  894. var h = parent.find('.dtp-select-hour');
  895. for (var i = 0; i < h.length; i++)
  896. {
  897. $(h[i]).attr('fill', 'transparent');
  898. }
  899. var th = parent.find('.dtp-select-hour-text');
  900. for (var i = 0; i < th.length; i++)
  901. {
  902. $(th[i]).attr('fill', '#000');
  903. }
  904. $(parent.find('#h-' + value)).attr('fill', '#007d72');
  905. $(parent.find('#th-' + value)).attr('fill', '#fff');
  906. this.currentDate.hour(parseInt(value));
  907. if (this.params.shortTime === true && this.isPM())
  908. {
  909. this.currentDate.add(12, 'hours');
  910. }
  911. this.showTime(this.currentDate);
  912. this.animateHands();
  913. if (this.params.switchOnClick === true)
  914. setTimeout(this.initMinutes.bind(this), 200);
  915. }
  916. },
  917. _onSelectMinute: function (e)
  918. {
  919. if (!$(e.target).hasClass('disabled'))
  920. {
  921. var value = $(e.target).data('minute');
  922. var parent = $(e.target).parent();
  923. var m = parent.find('.dtp-select-minute');
  924. for (var i = 0; i < m.length; i++)
  925. {
  926. $(m[i]).attr('fill', 'transparent');
  927. }
  928. var tm = parent.find('.dtp-select-minute-text');
  929. for (var i = 0; i < tm.length; i++)
  930. {
  931. $(tm[i]).attr('fill', '#000');
  932. }
  933. $(parent.find('#m-' + value)).attr('fill', '#007d72');
  934. $(parent.find('#tm-' + value)).attr('fill', '#fff');
  935. this.currentDate.minute(parseInt(value));
  936. this.showTime(this.currentDate);
  937. this.animateHands();
  938. if (this.params.switchOnClick === true)
  939. setTimeout(function ()
  940. {
  941. this.setElementValue();
  942. this.hide();
  943. }.bind(this), 200);
  944. }
  945. },
  946. _onSelectAM: function (e)
  947. {
  948. $('.dtp-actual-meridien').find('a').removeClass('selected');
  949. $(e.currentTarget).addClass('selected');
  950. if (this.currentDate.hour() >= 12)
  951. {
  952. if (this.currentDate.subtract(12, 'hours'))
  953. this.showTime(this.currentDate);
  954. }
  955. this.toggleTime((this.currentView === 1));
  956. },
  957. _onSelectPM: function (e)
  958. {
  959. $('.dtp-actual-meridien').find('a').removeClass('selected');
  960. $(e.currentTarget).addClass('selected');
  961. if (this.currentDate.hour() < 12)
  962. {
  963. if (this.currentDate.add(12, 'hours'))
  964. this.showTime(this.currentDate);
  965. }
  966. this.toggleTime((this.currentView === 1));
  967. },
  968. convertHours: function (h)
  969. {
  970. var _return = h;
  971. if (this.params.shortTime === true)
  972. {
  973. if ((h < 12) && this.isPM())
  974. {
  975. _return += 12;
  976. }
  977. }
  978. return _return;
  979. },
  980. setDate: function (date)
  981. {
  982. this.params.currentDate = date;
  983. this.initDates();
  984. },
  985. setMinDate: function (date)
  986. {
  987. this.params.minDate = date;
  988. this.initDates();
  989. },
  990. setMaxDate: function (date)
  991. {
  992. this.params.maxDate = date;
  993. this.initDates();
  994. },
  995. destroy: function ()
  996. {
  997. this._detachEvents();
  998. this.$dtpElement.remove();
  999. },
  1000. show: function ()
  1001. {
  1002. this.$dtpElement.removeClass('hidden');
  1003. this._attachEvent($(window), 'keydown', this._onKeydown.bind(this));
  1004. this._centerBox();
  1005. },
  1006. hide: function ()
  1007. {
  1008. $(window).off('keydown', null, null, this._onKeydown.bind(this));
  1009. this.$dtpElement.addClass('hidden');
  1010. },
  1011. _centerBox: function ()
  1012. {
  1013. var h = (this.$dtpElement.height() - this.$dtpElement.find('.dtp-content').height()) / 2;
  1014. this.$dtpElement.find('.dtp-content').css('marginLeft', -(this.$dtpElement.find('.dtp-content').width() / 2) + 'px');
  1015. this.$dtpElement.find('.dtp-content').css('top', h + 'px');
  1016. },
  1017. enableDays: function ()
  1018. {
  1019. var enableDays = this.params.enableDays;
  1020. if (enableDays) {
  1021. $(".dtp-picker-days tbody tr td").each(function () {
  1022. if (!(($.inArray($(this).index(), enableDays)) >= 0)) {
  1023. $(this).find('a').css({
  1024. "background": "#e3e3e3",
  1025. "cursor": "no-drop",
  1026. "opacity": "0.5"
  1027. }).off("click");
  1028. }
  1029. });
  1030. }
  1031. }
  1032. };
  1033. })(jQuery, moment);