You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1499 lines
64 KiB

2 years ago
  1. // daterangepicker.js
  2. // version : 0.0.5
  3. // author : Chunlong Liu
  4. // last updated at: 2014-05-27
  5. // license : MIT
  6. // www.jszen.com
  7. (function (factory) {
  8. if (typeof define === 'function' && define.amd) {
  9. // AMD. Register as an anonymous module.
  10. define(['jquery', 'moment'], factory);
  11. } else if (typeof exports === 'object' && typeof module !== 'undefined') {
  12. // CommonJS. Register as a module
  13. module.exports = factory(require('jquery'), require('moment'));
  14. } else {
  15. // Browser globals
  16. factory(jQuery, moment);
  17. }
  18. }(function ($, moment) {
  19. $.dateRangePickerLanguages =
  20. {
  21. 'az':
  22. {
  23. 'selected': 'Seçildi:',
  24. 'day': ' gün',
  25. 'days': ' gün',
  26. 'apply': 'tətbiq',
  27. 'week-1': '1',
  28. 'week-2': '2',
  29. 'week-3': '3',
  30. 'week-4': '4',
  31. 'week-5': '5',
  32. 'week-6': '6',
  33. 'week-7': '7',
  34. 'month-name': ['yanvar', 'fevral', 'mart', 'aprel', 'may', 'iyun', 'iyul', 'avqust', 'sentyabr', 'oktyabr', 'noyabr', 'dekabr'],
  35. 'shortcuts': 'Qısayollar',
  36. 'past': 'Keçmiş',
  37. 'following': 'Növbəti',
  38. 'previous': '   ',
  39. 'prev-week': 'Öncəki həftə',
  40. 'prev-month': 'Öncəki ay',
  41. 'prev-year': 'Öncəki il',
  42. 'next': '   ',
  43. 'next-week': 'Növbəti həftə',
  44. 'next-month': 'Növbəti ay',
  45. 'next-year': 'Növbəti il',
  46. 'less-than': 'Tarix aralığı %d gündən çox olmamalıdır',
  47. 'more-than': 'Tarix aralığı %d gündən az olmamalıdır',
  48. 'default-more': '%d gündən çox bir tarix seçin',
  49. 'default-single': 'Tarix seçin',
  50. 'default-less': '%d gündən az bir tarix seçin',
  51. 'default-range': '%d və %d gün aralığında tarixlər seçin',
  52. 'default-default': 'Tarix aralığı seçin'
  53. },
  54. 'cn':
  55. {
  56. 'selected': '已选择:',
  57. 'day': '天',
  58. 'days': '天',
  59. 'apply': '确定',
  60. 'week-1': '一',
  61. 'week-2': '二',
  62. 'week-3': '三',
  63. 'week-4': '四',
  64. 'week-5': '五',
  65. 'week-6': '六',
  66. 'week-7': '日',
  67. 'month-name': ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
  68. 'shortcuts': '快捷选择',
  69. 'past': '过去',
  70. 'following': '将来',
  71. 'previous': '   ',
  72. 'prev-week': '上周',
  73. 'prev-month': '上个月',
  74. 'prev-year': '去年',
  75. 'next': '   ',
  76. 'next-week': '下周',
  77. 'next-month': '下个月',
  78. 'next-year': '明年',
  79. 'less-than': '所选日期范围不能大于%d天',
  80. 'more-than': '所选日期范围不能小于%d天',
  81. 'default-more': '请选择大于%d天的日期范围',
  82. 'default-less': '请选择小于%d天的日期范围',
  83. 'default-range': '请选择%d天到%d天的日期范围',
  84. 'default-single': '请选择一个日期',
  85. 'default-default': '请选择一个日期范围'
  86. },
  87. 'zh-TW':
  88. {
  89. 'selected': '已選擇:',
  90. 'day': '天',
  91. 'days': '天',
  92. 'apply': '確定',
  93. 'week-1': '一',
  94. 'week-2': '二',
  95. 'week-3': '三',
  96. 'week-4': '四',
  97. 'week-5': '五',
  98. 'week-6': '六',
  99. 'week-7': '日',
  100. 'month-name': ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
  101. 'shortcuts': '快捷選擇',
  102. 'past': '過去',
  103. 'following': '將來',
  104. 'previous': '   ',
  105. 'prev-week': '上週',
  106. 'prev-month': '上个月',
  107. 'prev-year': '去年',
  108. 'next': '   ',
  109. 'next-week': '下週',
  110. 'next-month': '下个月',
  111. 'next-year': '明年',
  112. 'less-than': '所選日期範圍不能大於%d天',
  113. 'more-than': '所選日期範圍不能小於%d天',
  114. 'default-more': '請選擇大於%d天的日期範圍',
  115. 'default-less': '請選擇小於%d天的日期範圍',
  116. 'default-range': '請選擇%d天到%d天的日期範圍',
  117. 'default-single': '請選擇一個日期',
  118. 'default-default': '請選擇一個日期範圍'
  119. },
  120. 'cz':
  121. {
  122. 'selected': 'Vybráno:',
  123. 'day': 'Den',
  124. 'days': 'Dny',
  125. 'apply': 'Zavřít',
  126. 'week-1': 'po',
  127. 'week-2': 'út',
  128. 'week-3': 'st',
  129. 'week-4': 'čt',
  130. 'week-5': 'pá',
  131. 'week-6': 'so',
  132. 'week-7': 'ne',
  133. 'month-name': ['leden', 'únor', 'březen', 'duben', 'květen', 'červen', 'červenec', 'srpen', 'září', 'říjen', 'listopad', 'prosinec'],
  134. 'shortcuts': 'Zkratky',
  135. 'past': 'po',
  136. 'following': 'následující',
  137. 'previous': 'předchozí',
  138. 'prev-week': 'týden',
  139. 'prev-month': 'měsíc',
  140. 'prev-year': 'rok',
  141. 'next': 'další',
  142. 'next-week': 'týden',
  143. 'next-month': 'měsíc',
  144. 'next-year': 'rok',
  145. 'less-than': 'Rozsah data by neměl být větší než %d dnů',
  146. 'more-than': 'Rozsah data by neměl být menší než %d dnů',
  147. 'default-more': 'Prosím zvolte rozsah data větší než %d dnů',
  148. 'default-single': 'Prosím zvolte datum',
  149. 'default-less': 'Prosím zvolte rozsah data menší než %d dnů',
  150. 'default-range': 'Prosím zvolte rozsah data mezi %d a %d dny',
  151. 'default-default': 'Prosím zvolte rozsah data'
  152. },
  153. 'en':
  154. {
  155. 'selected': 'Selected:',
  156. 'day': 'Day',
  157. 'days': 'Days',
  158. 'apply': 'Close',
  159. 'week-1': 'mo',
  160. 'week-2': 'tu',
  161. 'week-3': 'we',
  162. 'week-4': 'th',
  163. 'week-5': 'fr',
  164. 'week-6': 'sa',
  165. 'week-7': 'su',
  166. 'month-name': ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december'],
  167. 'shortcuts': 'Shortcuts',
  168. 'custom-values': 'Custom Values',
  169. 'past': 'Past',
  170. 'following': 'Following',
  171. 'previous': 'Previous',
  172. 'prev-week': 'Week',
  173. 'prev-month': 'Month',
  174. 'prev-year': 'Year',
  175. 'next': 'Next',
  176. 'next-week': 'Week',
  177. 'next-month': 'Month',
  178. 'next-year': 'Year',
  179. 'less-than': 'Date range should not be more than %d days',
  180. 'more-than': 'Date range should not be less than %d days',
  181. 'default-more': 'Please select a date range longer than %d days',
  182. 'default-single': 'Please select a date',
  183. 'default-less': 'Please select a date range less than %d days',
  184. 'default-range': 'Please select a date range between %d and %d days',
  185. 'default-default': 'Please select a date range'
  186. },
  187. 'it':
  188. {
  189. 'selected': 'Selezionati:',
  190. 'day': 'Giorno',
  191. 'days': 'Giorni',
  192. 'apply': 'Chiudi',
  193. 'week-1': 'lu',
  194. 'week-2': 'ma',
  195. 'week-3': 'me',
  196. 'week-4': 'gi',
  197. 'week-5': 've',
  198. 'week-6': 'sa',
  199. 'week-7': 'do',
  200. 'month-name': ['gennaio', 'febbraio', 'marzo', 'aprile', 'maggio', 'giugno', 'luglio', 'agosto', 'settembre', 'ottobre', 'novembre', 'dicembre'],
  201. 'shortcuts': 'Scorciatoie',
  202. 'past': 'Scorso',
  203. 'following': 'Successivo',
  204. 'previous': 'Precedente',
  205. 'prev-week': 'Settimana',
  206. 'prev-month': 'Mese',
  207. 'prev-year': 'Anno',
  208. 'next': 'Prossimo',
  209. 'next-week': 'Settimana',
  210. 'next-month': 'Mese',
  211. 'next-year': 'Anno',
  212. 'less-than': 'L\'intervallo non dev\'essere maggiore di %d giorni',
  213. 'more-than': 'L\'intervallo non dev\'essere minore di %d giorni',
  214. 'default-more': 'Seleziona un intervallo maggiore di %d giorni',
  215. 'default-single': 'Seleziona una data',
  216. 'default-less': 'Seleziona un intervallo minore di %d giorni',
  217. 'default-range': 'Seleziona un intervallo compreso tra i %d e i %d giorni',
  218. 'default-default': 'Seleziona un intervallo di date'
  219. },
  220. 'es':
  221. {
  222. 'selected': 'Seleccionado:',
  223. 'day': 'Dia',
  224. 'days': 'Dias',
  225. 'apply': 'Cerrar',
  226. 'week-1': 'lu',
  227. 'week-2': 'ma',
  228. 'week-3': 'mi',
  229. 'week-4': 'ju',
  230. 'week-5': 'vi',
  231. 'week-6': 'sa',
  232. 'week-7': 'do',
  233. 'month-name': ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
  234. 'shortcuts': 'Accesos directos',
  235. 'past': 'Pasado',
  236. 'following': 'Siguiente',
  237. 'previous': 'Anterior',
  238. 'prev-week': 'Semana',
  239. 'prev-month': 'Mes',
  240. 'prev-year': 'Año',
  241. 'next': 'Siguiente',
  242. 'next-week': 'Semana',
  243. 'next-month': 'Mes',
  244. 'next-year': 'Año',
  245. 'less-than': 'El rango no deberia ser mayor de %d dias',
  246. 'more-than': 'El rango no deberia ser menor de %d dias',
  247. 'default-more': 'Por favor selecciona un rango mayor a %d dias',
  248. 'default-single': 'Por favor selecciona un dia',
  249. 'default-less': 'Por favor selecciona un rango menor a %d dias',
  250. 'default-range': 'Por favor selecciona un rango entre %d y %d dias',
  251. 'default-default': 'Por favor selecciona un rango de fechas.'
  252. },
  253. 'de':
  254. {
  255. 'selected': 'Auswahl:',
  256. 'day': 'Tag',
  257. 'days': 'Tage',
  258. 'apply': 'Schließen',
  259. 'week-1': 'mo',
  260. 'week-2': 'di',
  261. 'week-3': 'mi',
  262. 'week-4': 'do',
  263. 'week-5': 'fr',
  264. 'week-6': 'sa',
  265. 'week-7': 'so',
  266. 'month-name': ['januar', 'februar', 'märz', 'april', 'mai', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'dezember'],
  267. 'shortcuts': 'Schnellwahl',
  268. 'past': 'Vorherige',
  269. 'following': 'Folgende',
  270. 'previous': 'Vorherige',
  271. 'prev-week': 'Woche',
  272. 'prev-month': 'Monat',
  273. 'prev-year': 'Jahr',
  274. 'next': 'Nächste',
  275. 'next-week': 'Woche',
  276. 'next-month': 'Monat',
  277. 'next-year': 'Jahr',
  278. 'less-than': 'Datumsbereich darf nicht größer sein als %d Tage',
  279. 'more-than': 'Datumsbereich darf nicht kleiner sein als %d Tage',
  280. 'default-more': 'Bitte mindestens %d Tage auswählen',
  281. 'default-single': 'Bitte ein Datum auswählen',
  282. 'default-less': 'Bitte weniger als %d Tage auswählen',
  283. 'default-range': 'Bitte einen Datumsbereich zwischen %d und %d Tagen auswählen',
  284. 'default-default': 'Bitte ein Start- und Enddatum auswählen'
  285. },
  286. 'ru':
  287. {
  288. 'selected': 'Выбрано:',
  289. 'day': 'День',
  290. 'days': 'Дней',
  291. 'apply': 'Закрыть',
  292. 'week-1': 'пн',
  293. 'week-2': 'вт',
  294. 'week-3': 'ср',
  295. 'week-4': 'чт',
  296. 'week-5': 'пт',
  297. 'week-6': 'сб',
  298. 'week-7': 'вс',
  299. 'month-name': ['январь', 'февраль', 'март', 'апрель', 'май', 'июнь', 'июль', 'август', 'сентябрь', 'октябрь', 'ноябрь', 'декабрь'],
  300. 'shortcuts': 'Быстрый выбор',
  301. 'past': 'Прошедшие',
  302. 'following': 'Следующие',
  303. 'previous': '   ',
  304. 'prev-week': 'Неделя',
  305. 'prev-month': 'Месяц',
  306. 'prev-year': 'Год',
  307. 'next': '   ',
  308. 'next-week': 'Неделя',
  309. 'next-month': 'Месяц',
  310. 'next-year': 'Год',
  311. 'less-than': 'Диапазон не может быть больше %d дней',
  312. 'more-than': 'Диапазон не может быть меньше %d дней',
  313. 'default-more': 'Пожалуйста выберите диапазон больше %d дней',
  314. 'default-single': 'Пожалуйста выберите дату',
  315. 'default-less': 'Пожалуйста выберите диапазон меньше %d дней',
  316. 'default-range': 'Пожалуйста выберите диапазон между %d и %d днями',
  317. 'default-default': 'Пожалуйста выберите диапазон'
  318. },
  319. 'fr':
  320. {
  321. 'selected': 'Sélection:',
  322. 'day': 'Jour',
  323. 'days': 'Jours',
  324. 'apply': 'Fermer',
  325. 'week-1': 'lu',
  326. 'week-2': 'ma',
  327. 'week-3': 'me',
  328. 'week-4': 'je',
  329. 'week-5': 've',
  330. 'week-6': 'sa',
  331. 'week-7': 'di',
  332. 'month-name': ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre'],
  333. 'shortcuts': 'Raccourcis',
  334. 'past': 'Passé',
  335. 'following': 'Suivant',
  336. 'previous': 'Précédent',
  337. 'prev-week': 'Semaine',
  338. 'prev-month': 'Mois',
  339. 'prev-year': 'Année',
  340. 'next': 'Suivant',
  341. 'next-week': 'Semaine',
  342. 'next-month': 'Mois',
  343. 'next-year': 'Année',
  344. 'less-than': 'L\'intervalle ne doit pas être supérieure à %d jours',
  345. 'more-than': 'L\'intervalle ne doit pas être inférieure à %d jours',
  346. 'default-more': 'Merci de choisir une intervalle supérieure à %d jours',
  347. 'default-single': 'Merci de choisir une date',
  348. 'default-less': 'Merci de choisir une intervalle inférieure %d jours',
  349. 'default-range': 'Merci de choisir une intervalle comprise entre %d et %d jours',
  350. 'default-default': 'Merci de choisir une date'
  351. },
  352. 'hu':
  353. {
  354. 'selected': 'Kiválasztva:',
  355. 'day': 'Nap',
  356. 'days': 'Nap',
  357. 'apply': 'Ok',
  358. 'week-1': 'h',
  359. 'week-2': 'k',
  360. 'week-3': 'sz',
  361. 'week-4': 'cs',
  362. 'week-5': 'p',
  363. 'week-6': 'sz',
  364. 'week-7': 'v',
  365. 'month-name': ['január', 'február', 'március', 'április', 'május', 'június', 'július', 'augusztus', 'szeptember', 'október', 'november', 'december'],
  366. 'shortcuts': 'Gyorsválasztó',
  367. 'past': 'Múlt',
  368. 'following': 'Következő',
  369. 'previous': 'Előző',
  370. 'prev-week': 'Hét',
  371. 'prev-month': 'Hónap',
  372. 'prev-year': 'Év',
  373. 'next': 'Következő',
  374. 'next-week': 'Hét',
  375. 'next-month': 'Hónap',
  376. 'next-year': 'Év',
  377. 'less-than': 'A kiválasztás nem lehet több %d napnál',
  378. 'more-than': 'A kiválasztás nem lehet több %d napnál',
  379. 'default-more': 'Válassz ki egy időszakot ami hosszabb mint %d nap',
  380. 'default-single': 'Válassz egy napot',
  381. 'default-less': 'Válassz ki egy időszakot ami rövidebb mint %d nap',
  382. 'default-range': 'Válassz ki egy %d - %d nap hosszú időszakot',
  383. 'default-default': 'Válassz ki egy időszakot'
  384. }
  385. };
  386. $.fn.dateRangePicker = function (opt) {
  387. if (!opt) opt = {};
  388. opt = $.extend(true,
  389. {
  390. autoClose: false,
  391. format: 'YYYY-MM-DD',
  392. separator: ' to ',
  393. language: 'auto',
  394. startOfWeek: 'sunday',// or monday
  395. getValue: function () {
  396. return $(this).val();
  397. },
  398. setValue: function (s) {
  399. if (!$(this).attr('readonly') && !$(this).is(':disabled')) {
  400. $(this).val(s);
  401. }
  402. },
  403. startDate: false,
  404. endDate: false,
  405. time: {
  406. enabled: false
  407. },
  408. minDays: 0,
  409. maxDays: 0,
  410. showShortcuts: true,
  411. shortcuts:
  412. {
  413. //'prev-days': [1,3,5,7],
  414. 'next-days': [3, 5, 7],
  415. //'prev' : ['week','month','year'],
  416. 'next': ['week', 'month', 'year']
  417. },
  418. customShortcuts: [],
  419. inline: false,
  420. container: 'body',
  421. alwaysOpen: false,
  422. singleDate: false,
  423. lookBehind: false,
  424. batchMode: false,
  425. duration: 200,
  426. stickyMonths: false,
  427. dayDivAttrs: [],
  428. dayTdAttrs: [],
  429. applyBtnClass: ''
  430. }, opt);
  431. opt.start = false;
  432. opt.end = false;
  433. if (opt.startDate && typeof opt.startDate == 'string') opt.startDate = moment(opt.startDate, opt.format).toDate();
  434. if (opt.endDate && typeof opt.endDate == 'string') opt.endDate = moment(opt.endDate, opt.format).toDate();
  435. var langs = getLanguages();
  436. var box;
  437. var initiated = false;
  438. var self = this;
  439. var selfDom = $(self).get(0);
  440. $(this).unbind('.datepicker').bind('click.datepicker', function (evt) {
  441. var isOpen = box.is(':visible');
  442. $(document).trigger('click.datepicker');
  443. evt.stopPropagation();
  444. if (!isOpen) open(opt.duration);
  445. });
  446. init_datepicker.call(this);
  447. if (opt.alwaysOpen) {
  448. open(0);
  449. }
  450. // expose some api
  451. $(this).data('dateRangePicker',
  452. {
  453. setDateRange: function (d1, d2) {
  454. if (typeof d1 == 'string' && typeof d2 == 'string') {
  455. d1 = moment(d1, opt.format).toDate();
  456. d2 = moment(d2, opt.format).toDate();
  457. }
  458. setDateRange(d1, d2);
  459. },
  460. clear: clearSelection,
  461. close: closeDatePicker,
  462. open: open,
  463. getDatePicker: getDatePicker,
  464. destroy: function () {
  465. $(self).unbind('.datepicker');
  466. $(self).data('dateRangePicker', '');
  467. box.remove();
  468. $(window).unbind('resize.datepicker', calcPosition);
  469. $(document).unbind('click.datepicker', closeDatePicker);
  470. }
  471. });
  472. $(window).bind('resize.datepicker', calcPosition);
  473. return this;
  474. function init_datepicker() {
  475. var self = this;
  476. if ($(this).data('date-picker-opened')) {
  477. closeDatePicker();
  478. return;
  479. }
  480. $(this).data('date-picker-opened', true);
  481. box = createDom().hide();
  482. $(opt.container).append(box);
  483. if (!opt.inline) {
  484. calcPosition();
  485. }
  486. else {
  487. box.addClass("inline-wrapper").css({ position: 'static' });
  488. }
  489. if (opt.alwaysOpen) {
  490. box.find('.apply-btn').hide();
  491. }
  492. var defaultTime = opt.defaultTime ? opt.defaultTime : new Date();
  493. if (opt.lookBehind) {
  494. if (opt.startDate && compare_month(defaultTime, opt.startDate) < 0) defaultTime = nextMonth(moment(opt.startDate).toDate());
  495. if (opt.endDate && compare_month(defaultTime, opt.endDate) > 0) defaultTime = moment(opt.endDate).toDate();
  496. showMonth(prevMonth(defaultTime), 'month1');
  497. showMonth(defaultTime, 'month2');
  498. } else {
  499. if (opt.startDate && compare_month(defaultTime, opt.startDate) < 0) defaultTime = moment(opt.startDate).toDate();
  500. if (opt.endDate && compare_month(nextMonth(defaultTime), opt.endDate) > 0) defaultTime = prevMonth(moment(opt.endDate).toDate());
  501. showMonth(defaultTime, 'month1');
  502. showMonth(nextMonth(defaultTime), 'month2');
  503. }
  504. if (opt.time.enabled) {
  505. if ((opt.startDate && opt.endDate) || (opt.start && opt.end)) {
  506. showTime(moment(opt.start || opt.startDate).toDate(), 'time1');
  507. showTime(moment(opt.end || opt.endDate).toDate(), 'time2');
  508. } else {
  509. showTime(defaultTime, 'time1');
  510. showTime(defaultTime, 'time2');
  511. }
  512. }
  513. //showSelectedInfo();
  514. var defaultTopText = '';
  515. if (opt.singleDate)
  516. defaultTopText = lang('default-single');
  517. else if (opt.minDays && opt.maxDays)
  518. defaultTopText = lang('default-range');
  519. else if (opt.minDays)
  520. defaultTopText = lang('default-more');
  521. else if (opt.maxDays)
  522. defaultTopText = lang('default-less');
  523. else
  524. defaultTopText = lang('default-default');
  525. box.find('.default-top').html(defaultTopText.replace(/\%d/, opt.minDays).replace(/\%d/, opt.maxDays));
  526. setTimeout(function () {
  527. initiated = true;
  528. }, 0);
  529. box.click(function (evt) {
  530. evt.stopPropagation();
  531. });
  532. $(document).bind('click.datepicker', closeDatePicker);
  533. box.find('.next').click(function () {
  534. if (!opt.stickyMonths) gotoNextMonth(this);
  535. else gotoNextMonth_stickily(this)
  536. });
  537. function gotoNextMonth(self) {
  538. var isMonth2 = $(self).parents('table').hasClass('month2');
  539. var month = isMonth2 ? opt.month2 : opt.month1;
  540. month = nextMonth(month);
  541. if (!opt.singleDate && !isMonth2 && compare_month(month, opt.month2) >= 0 || isMonthOutOfBounds(month)) return;
  542. showMonth(month, isMonth2 ? 'month2' : 'month1');
  543. showGap();
  544. }
  545. function gotoNextMonth_stickily(self) {
  546. var nextMonth1 = nextMonth(opt.month1);
  547. var nextMonth2 = nextMonth(opt.month2);
  548. if (isMonthOutOfBounds(nextMonth2)) return;
  549. if (!opt.singleDate && compare_month(nextMonth1, nextMonth2) >= 0) return;
  550. showMonth(nextMonth1, 'month1');
  551. showMonth(nextMonth2, 'month2');
  552. }
  553. box.find('.prev').click(function () {
  554. if (!opt.stickyMonths) gotoPrevMonth(this);
  555. else gotoPrevMonth_stickily(this);
  556. });
  557. function gotoPrevMonth(self) {
  558. var isMonth2 = $(self).parents('table').hasClass('month2');
  559. var month = isMonth2 ? opt.month2 : opt.month1;
  560. month = prevMonth(month);
  561. //if (isMonth2 && month.getFullYear()+''+month.getMonth() <= opt.month1.getFullYear()+''+opt.month1.getMonth()) return;
  562. if (isMonth2 && compare_month(month, opt.month1) <= 0 || isMonthOutOfBounds(month)) return;
  563. showMonth(month, isMonth2 ? 'month2' : 'month1');
  564. showGap();
  565. }
  566. function gotoPrevMonth_stickily(self) {
  567. var prevMonth1 = prevMonth(opt.month1);
  568. var prevMonth2 = prevMonth(opt.month2);
  569. if (isMonthOutOfBounds(prevMonth1)) return;
  570. if (!opt.singleDate && compare_month(prevMonth2, prevMonth1) <= 0) return;
  571. showMonth(prevMonth2, 'month2');
  572. showMonth(prevMonth1, 'month1');
  573. }
  574. box.bind('click', function (evt) {
  575. if ($(evt.target).hasClass('day')) {
  576. dayClicked($(evt.target));
  577. }
  578. });
  579. box.attr('unselectable', 'on')
  580. .css('user-select', 'none')
  581. .bind('selectstart', function (e) {
  582. e.preventDefault(); return false;
  583. });
  584. box.find('.apply-btn').click(function () {
  585. closeDatePicker();
  586. var dateRange = getDateString(new Date(opt.start)) + opt.separator + getDateString(new Date(opt.end));
  587. $(self).trigger('datepicker-apply',
  588. {
  589. 'value': dateRange,
  590. 'date1': new Date(opt.start),
  591. 'date2': new Date(opt.end)
  592. });
  593. });
  594. box.find('[custom]').click(function () {
  595. var valueName = $(this).attr('custom');
  596. opt.start = false;
  597. opt.end = false;
  598. box.find('.day.checked').removeClass('checked');
  599. opt.setValue.call(selfDom, valueName);
  600. checkSelectionValid();
  601. showSelectedInfo(true);
  602. showSelectedDays();
  603. if (opt.autoClose) closeDatePicker();
  604. });
  605. box.find('[shortcut]').click(function () {
  606. var shortcut = $(this).attr('shortcut');
  607. var end = new Date(), start = false;
  608. if (shortcut.indexOf('day') != -1) {
  609. var day = parseInt(shortcut.split(',', 2)[1], 10);
  610. start = new Date(new Date().getTime() + 86400000 * day);
  611. end = new Date(end.getTime() + 86400000 * (day > 0 ? 1 : -1));
  612. }
  613. else if (shortcut.indexOf('week') != -1) {
  614. var dir = shortcut.indexOf('prev,') != -1 ? -1 : 1;
  615. if (dir == 1)
  616. var stopDay = opt.startOfWeek == 'monday' ? 1 : 0;
  617. else
  618. var stopDay = opt.startOfWeek == 'monday' ? 0 : 6;
  619. end = new Date(end.getTime() - 86400000);
  620. while (end.getDay() != stopDay) end = new Date(end.getTime() + dir * 86400000);
  621. start = new Date(end.getTime() + dir * 86400000 * 6);
  622. }
  623. else if (shortcut.indexOf('month') != -1) {
  624. var dir = shortcut.indexOf('prev,') != -1 ? -1 : 1;
  625. if (dir == 1)
  626. start = nextMonth(end);
  627. else
  628. start = prevMonth(end);
  629. start.setDate(1);
  630. end = nextMonth(start);
  631. end.setDate(1);
  632. end = new Date(end.getTime() - 86400000);
  633. }
  634. else if (shortcut.indexOf('year') != -1) {
  635. var dir = shortcut.indexOf('prev,') != -1 ? -1 : 1;
  636. start = new Date();
  637. start.setFullYear(end.getFullYear() + dir);
  638. start.setMonth(0);
  639. start.setDate(1);
  640. end.setFullYear(end.getFullYear() + dir);
  641. end.setMonth(11);
  642. end.setDate(31);
  643. }
  644. else if (shortcut == 'custom') {
  645. var name = $(this).html();
  646. if (opt.customShortcuts && opt.customShortcuts.length > 0) {
  647. for (var i = 0; i < opt.customShortcuts.length; i++) {
  648. var sh = opt.customShortcuts[i];
  649. if (sh.name == name) {
  650. var data = [];
  651. // try
  652. // {
  653. data = sh['dates'].call();
  654. //}catch(e){}
  655. if (data && data.length == 2) {
  656. start = data[0];
  657. end = data[1];
  658. }
  659. // if only one date is specified then just move calendars there
  660. // move calendars to show this date's month and next months
  661. if (data && data.length == 1) {
  662. movetodate = data[0];
  663. showMonth(movetodate, 'month1');
  664. showMonth(nextMonth(movetodate), 'month2');
  665. showGap();
  666. }
  667. break;
  668. }
  669. }
  670. }
  671. }
  672. if (start && end) {
  673. setDateRange(start, end);
  674. checkSelectionValid();
  675. }
  676. });
  677. box.find(".time1 input[type=range]").bind("change mousemove", function (e) {
  678. var target = e.target,
  679. hour = target.name == "hour" ? $(target).val().replace(/^(\d{1})$/, "0$1") : undefined,
  680. min = target.name == "minute" ? $(target).val().replace(/^(\d{1})$/, "0$1") : undefined;
  681. setTime("time1", hour, min);
  682. });
  683. box.find(".time2 input[type=range]").bind("change mousemove", function (e) {
  684. var target = e.target,
  685. hour = target.name == "hour" ? $(target).val().replace(/^(\d{1})$/, "0$1") : undefined,
  686. min = target.name == "minute" ? $(target).val().replace(/^(\d{1})$/, "0$1") : undefined;
  687. setTime("time2", hour, min);
  688. });
  689. }
  690. function calcPosition() {
  691. if (!opt.inline) {
  692. var offset = $(self).offset();
  693. if ($(opt.container).css("position") == "relative") {
  694. var containerOffset = $(opt.container).offset();
  695. box.css(
  696. {
  697. top: offset.top - containerOffset.top + $(self).outerHeight() + 4,
  698. left: offset.left - containerOffset.left
  699. });
  700. }
  701. else {
  702. if (offset.left < 460) //left to right
  703. {
  704. box.css(
  705. {
  706. top: offset.top + $(self).outerHeight() + parseInt($('body').css('border-top') || 0, 10),
  707. left: offset.left
  708. });
  709. }
  710. else {
  711. box.css(
  712. {
  713. top: offset.top + $(self).outerHeight() + parseInt($('body').css('border-top') || 0, 10),
  714. left: offset.left + $(self).width() - box.width() - 16
  715. });
  716. }
  717. }
  718. }
  719. }
  720. // Return the date picker wrapper element
  721. function getDatePicker() {
  722. return box;
  723. }
  724. function open(animationTime) {
  725. calcPosition();
  726. var __default_string = opt.getValue.call(selfDom);
  727. var defaults = __default_string ? __default_string.split(opt.separator) : '';
  728. if (defaults && ((defaults.length == 1 && opt.singleDate) || defaults.length >= 2)) {
  729. var ___format = opt.format;
  730. if (___format.match(/Do/)) {
  731. ___format = ___format.replace(/Do/, 'D');
  732. defaults[0] = defaults[0].replace(/(\d+)(th|nd|st)/, '$1');
  733. if (defaults.length >= 2) {
  734. defaults[1] = defaults[1].replace(/(\d+)(th|nd|st)/, '$1');
  735. }
  736. }
  737. // set initiated to avoid triggerring datepicker-change event
  738. initiated = false;
  739. if (defaults.length >= 2) {
  740. setDateRange(moment(defaults[0], ___format, moment.locale(opt.language)).toDate(), moment(defaults[1], ___format, moment.locale(opt.language)).toDate());
  741. }
  742. else if (defaults.length == 1 && opt.singleDate) {
  743. setSingleDate(moment(defaults[0], ___format, moment.locale(opt.language)).toDate());
  744. }
  745. initiated = true;
  746. }
  747. box.slideDown(animationTime);
  748. }
  749. function renderTime(name, date) {
  750. box.find("." + name + " input[type=range].hour-range").val(moment(date).hours());
  751. box.find("." + name + " input[type=range].minute-range").val(moment(date).minutes());
  752. setTime(name, moment(date).format("HH"), moment(date).format("mm"));
  753. }
  754. function changeTime(name, date) {
  755. opt[name] = parseInt(
  756. moment(parseInt(date))
  757. .startOf('day')
  758. .add(moment(opt[name + "Time"]).format("HH"), 'h')
  759. .add(moment(opt[name + "Time"]).format("mm"), 'm').valueOf()
  760. );
  761. }
  762. function swapTime() {
  763. renderTime("time1", opt.start);
  764. renderTime("time2", opt.end);
  765. }
  766. function setTime(name, hour, minute) {
  767. hour && (box.find("." + name + " .hour-val").text(hour));
  768. minute && (box.find("." + name + " .minute-val").text(minute));
  769. switch (name) {
  770. case "time1":
  771. if (opt.start) {
  772. setRange("start", moment(opt.start));
  773. }
  774. setRange("startTime", moment(opt.startTime || moment().valueOf()));
  775. break;
  776. case "time2":
  777. if (opt.end) {
  778. setRange("end", moment(opt.end));
  779. }
  780. setRange("endTime", moment(opt.endTime || moment().valueOf()));
  781. break;
  782. }
  783. function setRange(name, timePoint) {
  784. var h = timePoint.format("HH"),
  785. m = timePoint.format("mm");
  786. opt[name] = timePoint
  787. .startOf('day')
  788. .add(hour || h, "h")
  789. .add(minute || m, "m")
  790. .valueOf();
  791. }
  792. checkSelectionValid();
  793. showSelectedInfo();
  794. showSelectedDays();
  795. }
  796. function clearSelection() {
  797. opt.start = false;
  798. opt.end = false;
  799. box.find('.day.checked').removeClass('checked');
  800. opt.setValue.call(selfDom, '');
  801. checkSelectionValid();
  802. showSelectedInfo();
  803. showSelectedDays();
  804. }
  805. function handleStart(time) {
  806. var r = time;
  807. if (opt.batchMode === 'week-range') {
  808. if (opt.startOfWeek === 'monday') {
  809. r = moment(parseInt(time)).startOf('isoweek').valueOf();
  810. } else {
  811. r = moment(parseInt(time)).startOf('week').valueOf();
  812. }
  813. } else if (opt.batchMode === 'month-range') {
  814. r = moment(parseInt(time)).startOf('month').valueOf();
  815. }
  816. return r;
  817. }
  818. function handleEnd(time) {
  819. var r = time;
  820. if (opt.batchMode === 'week-range') {
  821. if (opt.startOfWeek === 'monday') {
  822. r = moment(parseInt(time)).endOf('isoweek').valueOf();
  823. } else {
  824. r = moment(parseInt(time)).endOf('week').valueOf();
  825. }
  826. } else if (opt.batchMode === 'month') {
  827. r = moment(parseInt(time)).endOf('month').valueOf();
  828. }
  829. return r;
  830. }
  831. function dayClicked(day) {
  832. if (day.hasClass('invalid')) return;
  833. var time = day.attr('time');
  834. day.addClass('checked');
  835. if (opt.singleDate) {
  836. opt.start = time;
  837. opt.end = false;
  838. if (opt.time.enabled) {
  839. changeTime("start", opt.start);
  840. }
  841. }
  842. else if (opt.batchMode === 'week') {
  843. if (opt.startOfWeek === 'monday') {
  844. opt.start = moment(parseInt(time)).startOf('isoweek').valueOf();
  845. opt.end = moment(parseInt(time)).endOf('isoweek').valueOf();
  846. } else {
  847. opt.end = moment(parseInt(time)).endOf('week').valueOf();
  848. opt.start = moment(parseInt(time)).startOf('week').valueOf();
  849. }
  850. }
  851. else if (opt.batchMode === 'month') {
  852. opt.start = moment(parseInt(time)).startOf('month').valueOf();
  853. opt.end = moment(parseInt(time)).endOf('month').valueOf();
  854. }
  855. else if ((opt.start && opt.end) || (!opt.start && !opt.end)) {
  856. opt.start = handleStart(time);
  857. opt.end = false;
  858. if (opt.time.enabled) {
  859. changeTime("start", opt.start);
  860. }
  861. }
  862. else if (opt.start) {
  863. opt.end = handleEnd(time);
  864. if (opt.time.enabled) {
  865. changeTime("end", opt.end);
  866. }
  867. }
  868. if (!opt.singleDate && opt.start && opt.end && opt.start > opt.end) {
  869. var tmp = opt.end;
  870. opt.end = handleEnd(opt.start);
  871. opt.start = handleStart(tmp);
  872. if (opt.time.enabled) {
  873. swapTime();
  874. }
  875. }
  876. opt.start = parseInt(opt.start);
  877. opt.end = parseInt(opt.end);
  878. checkSelectionValid();
  879. showSelectedInfo();
  880. showSelectedDays();
  881. autoclose();
  882. }
  883. function autoclose() {
  884. if (opt.singleDate === true) {
  885. if (initiated && opt.start) {
  886. if (opt.autoClose) closeDatePicker();
  887. }
  888. } else {
  889. if (initiated && opt.start && opt.end) {
  890. if (opt.autoClose) closeDatePicker();
  891. }
  892. }
  893. }
  894. function checkSelectionValid() {
  895. var days = Math.ceil((opt.end - opt.start) / 86400000) + 1;
  896. if (opt.singleDate) { // Validate if only start is there
  897. if (opt.start && !opt.end)
  898. box.find('.drp_top-bar').removeClass('error').addClass('normal');
  899. else
  900. box.find('.drp_top-bar').removeClass('error').removeClass('normal');
  901. }
  902. else if (opt.maxDays && days > opt.maxDays) {
  903. opt.start = false;
  904. opt.end = false;
  905. box.find('.day').removeClass('checked');
  906. box.find('.drp_top-bar').removeClass('normal').addClass('error').find('.error-top').html(lang('less-than').replace('%d', opt.maxDays));
  907. }
  908. else if (opt.minDays && days < opt.minDays) {
  909. opt.start = false;
  910. opt.end = false;
  911. box.find('.day').removeClass('checked');
  912. box.find('.drp_top-bar').removeClass('normal').addClass('error').find('.error-top').html(lang('more-than').replace('%d', opt.minDays));
  913. }
  914. else {
  915. if (opt.start || opt.end)
  916. box.find('.drp_top-bar').removeClass('error').addClass('normal');
  917. else
  918. box.find('.drp_top-bar').removeClass('error').removeClass('normal');
  919. }
  920. if ((opt.singleDate && opt.start && !opt.end) || (!opt.singleDate && opt.start && opt.end)) {
  921. box.find('.apply-btn').removeClass('disabled');
  922. }
  923. else {
  924. box.find('.apply-btn').addClass('disabled');
  925. }
  926. if (opt.batchMode) {
  927. if ((opt.start && opt.startDate && compare_day(opt.start, opt.startDate) < 0)
  928. || (opt.end && opt.endDate && compare_day(opt.end, opt.endDate) > 0)) {
  929. opt.start = false;
  930. opt.end = false;
  931. box.find('.day').removeClass('checked');
  932. }
  933. }
  934. }
  935. function showSelectedInfo(forceValid) {
  936. box.find('.start-day').html('...');
  937. box.find('.end-day').html('...');
  938. box.find('.selected-days').hide();
  939. if (opt.start) {
  940. box.find('.start-day').html(getDateString(new Date(parseInt(opt.start))));
  941. }
  942. if (opt.end) {
  943. box.find('.end-day').html(getDateString(new Date(parseInt(opt.end))));
  944. }
  945. if (opt.start && opt.singleDate) {
  946. box.find('.apply-btn').removeClass('disabled');
  947. var dateRange = getDateString(new Date(opt.start));
  948. opt.setValue.call(selfDom, dateRange, getDateString(new Date(opt.start)), getDateString(new Date(opt.end)));
  949. if (initiated) {
  950. $(self).trigger('datepicker-change',
  951. {
  952. 'value': dateRange,
  953. 'date1': new Date(opt.start)
  954. });
  955. }
  956. }
  957. else if (opt.start && opt.end) {
  958. box.find('.selected-days').show().find('.selected-days-num').html(Math.round((opt.end - opt.start) / 86400000) + 1);
  959. box.find('.apply-btn').removeClass('disabled');
  960. var dateRange = getDateString(new Date(opt.start)) + opt.separator + getDateString(new Date(opt.end));
  961. opt.setValue.call(selfDom, dateRange, getDateString(new Date(opt.start)), getDateString(new Date(opt.end)));
  962. if (initiated) {
  963. $(self).trigger('datepicker-change',
  964. {
  965. 'value': dateRange,
  966. 'date1': new Date(opt.start),
  967. 'date2': new Date(opt.end)
  968. });
  969. }
  970. }
  971. else if (forceValid) {
  972. box.find('.apply-btn').removeClass('disabled');
  973. }
  974. else {
  975. box.find('.apply-btn').addClass('disabled');
  976. }
  977. }
  978. function setDateRange(date1, date2) {
  979. if (date1.getTime() > date2.getTime()) {
  980. var tmp = date2;
  981. date2 = date1;
  982. date1 = tmp;
  983. tmp = null;
  984. }
  985. var valid = true;
  986. if (opt.startDate && compare_day(date1, opt.startDate) < 0) valid = false;
  987. if (opt.endDate && compare_day(date2, opt.endDate) > 0) valid = false;
  988. if (!valid) {
  989. showMonth(opt.startDate, 'month1');
  990. showMonth(nextMonth(opt.startDate), 'month2');
  991. showGap();
  992. return;
  993. }
  994. opt.start = date1.getTime();
  995. opt.end = date2.getTime();
  996. if (opt.stickyMonths || (compare_day(date1, date2) > 0 && compare_month(date1, date2) == 0)) {
  997. if (opt.lookBehind) {
  998. date1 = prevMonth(date2);
  999. } else {
  1000. date2 = nextMonth(date1);
  1001. }
  1002. }
  1003. if (opt.stickyMonths && compare_month(date2, opt.endDate) > 0) {
  1004. date1 = prevMonth(date1);
  1005. date2 = prevMonth(date2);
  1006. }
  1007. if (!opt.stickyMonths) {
  1008. if (compare_month(date1, date2) == 0) {
  1009. if (opt.lookBehind) {
  1010. date1 = prevMonth(date2);
  1011. } else {
  1012. date2 = nextMonth(date1);
  1013. }
  1014. }
  1015. }
  1016. if (opt.time.enabled) {
  1017. renderTime("time1", date1);
  1018. renderTime("time2", date2);
  1019. }
  1020. showMonth(date1, 'month1');
  1021. showMonth(date2, 'month2');
  1022. showGap();
  1023. showSelectedInfo();
  1024. autoclose();
  1025. }
  1026. function setSingleDate(date1) {
  1027. var valid = true;
  1028. if (opt.startDate && compare_day(date1, opt.startDate) < 0) valid = false;
  1029. if (opt.endDate && compare_day(date1, opt.endDate) > 0) valid = false;
  1030. if (!valid) {
  1031. showMonth(opt.startDate, 'month1');
  1032. //showGap();
  1033. return;
  1034. }
  1035. opt.start = date1.getTime();
  1036. if (opt.time.enabled) {
  1037. renderTime("time1", date1);
  1038. }
  1039. showMonth(date1, 'month1');
  1040. //showMonth(date2,'month2');
  1041. showGap();
  1042. showSelectedInfo();
  1043. autoclose();
  1044. }
  1045. function showSelectedDays() {
  1046. if (!opt.start && !opt.end) return;
  1047. box.find('.day').each(function () {
  1048. var time = parseInt($(this).attr('time')),
  1049. start = opt.start,
  1050. end = opt.end;
  1051. if (opt.time.enabled) {
  1052. time = moment(time).startOf('day').valueOf();
  1053. start = moment(start || moment().valueOf()).startOf('day').valueOf();
  1054. end = moment(end || moment().valueOf()).startOf('day').valueOf();
  1055. }
  1056. if (
  1057. (opt.start && opt.end && end >= time && start <= time)
  1058. || (opt.start && !opt.end && moment(start).format('YYYY-MM-DD') == moment(time).format('YYYY-MM-DD'))
  1059. ) {
  1060. $(this).addClass('checked');
  1061. }
  1062. else {
  1063. $(this).removeClass('checked');
  1064. }
  1065. });
  1066. }
  1067. function showMonth(date, month) {
  1068. date = moment(date).toDate();
  1069. var monthName = nameMonth(date.getMonth());
  1070. box.find('.' + month + ' .month-name').html(monthName + ' ' + date.getFullYear());
  1071. box.find('.' + month + ' tbody').html(createMonthHTML(date));
  1072. opt[month] = date;
  1073. }
  1074. function showTime(date, name) {
  1075. box.find('.' + name).append(getTimeHTML());
  1076. renderTime(name, date);
  1077. }
  1078. function nameMonth(m) {
  1079. return lang('month-name')[m];
  1080. }
  1081. function getDateString(d) {
  1082. return moment(d).format(opt.format);
  1083. }
  1084. function showGap() {
  1085. showSelectedDays();
  1086. var m1 = parseInt(moment(opt.month1).format('YYYYMM'));
  1087. var m2 = parseInt(moment(opt.month2).format('YYYYMM'));
  1088. var p = Math.abs(m1 - m2);
  1089. var shouldShow = (p > 1 && p != 89);
  1090. if (shouldShow)
  1091. box.find('.gap').show();
  1092. else
  1093. box.find('.gap').hide();
  1094. }
  1095. function closeDatePicker() {
  1096. if (opt.alwaysOpen) return;
  1097. $(box).slideUp(opt.duration, function () {
  1098. $(self).data('date-picker-opened', false);
  1099. });
  1100. //$(document).unbind('.datepicker');
  1101. $(self).trigger('datepicker-close');
  1102. }
  1103. function compare_month(m1, m2) {
  1104. var p = parseInt(moment(m1).format('YYYYMM')) - parseInt(moment(m2).format('YYYYMM'));
  1105. if (p > 0) return 1;
  1106. if (p == 0) return 0;
  1107. return -1;
  1108. }
  1109. function compare_day(m1, m2) {
  1110. var p = parseInt(moment(m1).format('YYYYMMDD')) - parseInt(moment(m2).format('YYYYMMDD'));
  1111. if (p > 0) return 1;
  1112. if (p == 0) return 0;
  1113. return -1;
  1114. }
  1115. function nextMonth(month) {
  1116. month = moment(month).toDate();
  1117. var toMonth = month.getMonth();
  1118. while (month.getMonth() == toMonth) month = new Date(month.getTime() + 86400000);
  1119. return month;
  1120. }
  1121. function prevMonth(month) {
  1122. month = moment(month).toDate();
  1123. var toMonth = month.getMonth();
  1124. while (month.getMonth() == toMonth) month = new Date(month.getTime() - 86400000);
  1125. return month;
  1126. }
  1127. function getTimeHTML() {
  1128. var timeHtml = '<div>'
  1129. + '<span>Time: <span class="hour-val">00</span>:<span class="minute-val">00</span></span>'
  1130. + '</div>'
  1131. + '<div class="hour">'
  1132. + '<label>Hour: <input type="range" class="hour-range" name="hour" min="0" max="23"></label>'
  1133. + '</div>'
  1134. + '<div class="minute">'
  1135. + '<label>Minute: <input type="range" class="minute-range" name="minute" min="0" max="59"></label>'
  1136. + '</div>';
  1137. return timeHtml;
  1138. }
  1139. function createDom() {
  1140. var html = '<div class="date-picker-wrapper'
  1141. if (opt.singleDate) html += ' single-date';
  1142. if (!opt.showShortcuts) html += ' no-shortcuts ';
  1143. html += '">'
  1144. + '<div class="drp_top-bar">\
  1145. <div class="normal-top">\
  1146. <span style="color:#333">'+ lang('selected') + ' </span> <b class="start-day">...</b>'
  1147. if (!opt.singleDate) {
  1148. html += ' <span class="separator-day">' + opt.separator + '</span> <b class="end-day">...</b> <i class="selected-days">(<span class="selected-days-num">3</span> ' + lang('days') + ')</i>'
  1149. }
  1150. html += '</div>\
  1151. <div class="error-top">error</div>\
  1152. <div class="default-top">default</div>\
  1153. <input type="button" class="apply-btn disabled'+ getApplyBtnClass() + '" value="' + lang('apply') + '" />\
  1154. </div>'
  1155. + '<div class="month-wrapper">'
  1156. + '<table class="month1" cellspacing="0" border="0" cellpadding="0"><thead><tr class="caption"><th style="width:27px;"><span class="prev">&lt;</span></th><th colspan="5" class="month-name">January, 2011</th><th style="width:27px;">' + (opt.singleDate || !opt.stickyMonths ? '<span class="next">&gt;</span>' : '') + '</th></tr><tr class="week-name">' + getWeekHead() + '</thead><tbody></tbody></table>'
  1157. if (!opt.singleDate) {
  1158. html += '<div class="gap">' + getGapHTML() + '</div>'
  1159. + '<table class="month2" cellspacing="0" border="0" cellpadding="0"><thead><tr class="caption"><th style="width:27px;">' + (!opt.stickyMonths ? '<span class="prev">&lt;</span>' : '') + '</th><th colspan="5" class="month-name">January, 2011</th><th style="width:27px;"><span class="next">&gt;</span></th></tr><tr class="week-name">' + getWeekHead() + '</thead><tbody></tbody></table>'
  1160. }
  1161. //+'</div>'
  1162. html += '<div style="clear:both;height:0;font-size:0;"></div>'
  1163. + '<div class="time">'
  1164. + '<div class="time1"></div>'
  1165. if (!opt.singleDate) {
  1166. html += '<div class="time2"></div>'
  1167. }
  1168. html += '</div>'
  1169. + '<div style="clear:both;height:0;font-size:0;"></div>'
  1170. + '</div>';
  1171. if (opt.showShortcuts) {
  1172. html += '<div class="footer"><b>' + lang('shortcuts') + '</b>';
  1173. var data = opt.shortcuts;
  1174. if (data) {
  1175. if (data['prev-days'] && data['prev-days'].length > 0) {
  1176. html += '&nbsp;<span class="prev-days">' + lang('past');
  1177. for (var i = 0; i < data['prev-days'].length; i++) {
  1178. var name = data['prev-days'][i];
  1179. name += (data['prev-days'][i] > 1) ? lang('days') : lang('day');
  1180. html += ' <a href="javascript:;" shortcut="day,-' + data['prev-days'][i] + '">' + name + '</a>';
  1181. }
  1182. html += '</span>';
  1183. }
  1184. if (data['next-days'] && data['next-days'].length > 0) {
  1185. html += '&nbsp;<span class="next-days">' + lang('following');
  1186. for (var i = 0; i < data['next-days'].length; i++) {
  1187. var name = data['next-days'][i];
  1188. name += (data['next-days'][i] > 1) ? lang('days') : lang('day');
  1189. html += ' <a href="javascript:;" shortcut="day,' + data['next-days'][i] + '">' + name + '</a>';
  1190. }
  1191. html += '</span>';
  1192. }
  1193. if (data['prev'] && data['prev'].length > 0) {
  1194. html += '&nbsp;<span class="prev-buttons">' + lang('previous');
  1195. for (var i = 0; i < data['prev'].length; i++) {
  1196. var name = lang('prev-' + data['prev'][i]);
  1197. html += ' <a href="javascript:;" shortcut="prev,' + data['prev'][i] + '">' + name + '</a>';
  1198. }
  1199. html += '</span>';
  1200. }
  1201. if (data['next'] && data['next'].length > 0) {
  1202. html += '&nbsp;<span class="next-buttons">' + lang('next');
  1203. for (var i = 0; i < data['next'].length; i++) {
  1204. var name = lang('next-' + data['next'][i]);
  1205. html += ' <a href="javascript:;" shortcut="next,' + data['next'][i] + '">' + name + '</a>';
  1206. }
  1207. html += '</span>';
  1208. }
  1209. }
  1210. if (opt.customShortcuts) {
  1211. for (var i = 0; i < opt.customShortcuts.length; i++) {
  1212. var sh = opt.customShortcuts[i];
  1213. html += '&nbsp;<span class="custom-shortcut"><a href="javascript:;" shortcut="custom">' + sh.name + '</a></span>';
  1214. }
  1215. }
  1216. // Add Custom Values Dom
  1217. if (opt.showCustomValues) {
  1218. html += '<div class="customValues"><b>' + (opt.customValueLabel || lang('custom-values')) + '</b>';
  1219. if (opt.customValues) {
  1220. for (var i = 0; i < opt.customValues.length; i++) {
  1221. var val = opt.customValues[i];
  1222. html += '&nbsp;<span class="custom-value"><a href="javascript:;" custom="' + val.value + '">' + val.name + '</a></span>';
  1223. }
  1224. }
  1225. }
  1226. html += '</div>';
  1227. }
  1228. html += '</div>';
  1229. return $(html);
  1230. }
  1231. function getApplyBtnClass() {
  1232. klass = ''
  1233. if (opt.autoClose === true) {
  1234. klass += ' hide';
  1235. }
  1236. if (opt.applyBtnClass !== '') {
  1237. klass += ' ' + opt.applyBtnClass;
  1238. }
  1239. return klass;
  1240. }
  1241. function getWeekHead() {
  1242. if (opt.startOfWeek == 'monday') {
  1243. return '<th>' + lang('week-1') + '</th>\
  1244. <th>'+ lang('week-2') + '</th>\
  1245. <th>'+ lang('week-3') + '</th>\
  1246. <th>'+ lang('week-4') + '</th>\
  1247. <th>'+ lang('week-5') + '</th>\
  1248. <th>'+ lang('week-6') + '</th>\
  1249. <th>'+ lang('week-7') + '</th>';
  1250. }
  1251. else {
  1252. return '<th>' + lang('week-7') + '</th>\
  1253. <th>'+ lang('week-1') + '</th>\
  1254. <th>'+ lang('week-2') + '</th>\
  1255. <th>'+ lang('week-3') + '</th>\
  1256. <th>'+ lang('week-4') + '</th>\
  1257. <th>'+ lang('week-5') + '</th>\
  1258. <th>'+ lang('week-6') + '</th>';
  1259. }
  1260. }
  1261. function isMonthOutOfBounds(month) {
  1262. var month = moment(month);
  1263. if (opt.startDate && month.endOf('month').isBefore(opt.startDate)) {
  1264. return true;
  1265. }
  1266. if (opt.endDate && month.startOf('month').isAfter(opt.endDate)) {
  1267. return true;
  1268. }
  1269. return false;
  1270. }
  1271. function getGapHTML() {
  1272. var html = ['<div class="gap-top-mask"></div><div class="gap-bottom-mask"></div><div class="gap-lines">'];
  1273. for (var i = 0; i < 20; i++) {
  1274. html.push('<div class="gap-line">\
  1275. <div class="gap-1"></div>\
  1276. <div class="gap-2"></div>\
  1277. <div class="gap-3"></div>\
  1278. </div>');
  1279. }
  1280. html.push('</div>');
  1281. return html.join('');
  1282. }
  1283. function attributesCallbacks(initialObject, callbacksArray, today) {
  1284. var resultObject = jQuery.extend(true, {}, initialObject);
  1285. callbacksArray.forEach(function (cbAttr, cbAttrIndex, cbAttrArray) {
  1286. var addAttributes = cbAttr(this);
  1287. for (var attr in addAttributes) {
  1288. if (resultObject.hasOwnProperty(attr)) {
  1289. resultObject[attr] += addAttributes[attr];
  1290. } else {
  1291. resultObject[attr] = addAttributes[attr];
  1292. }
  1293. }
  1294. }, today);
  1295. attrString = '';
  1296. for (var attr in resultObject) {
  1297. if (resultObject.hasOwnProperty(attr)) {
  1298. attrString += attr + '="' + resultObject[attr] + '" ';
  1299. }
  1300. }
  1301. return attrString;
  1302. }
  1303. function createMonthHTML(d) {
  1304. var days = [];
  1305. d.setDate(1);
  1306. var lastMonth = new Date(d.getTime() - 86400000);
  1307. var now = new Date();
  1308. var dayOfWeek = d.getDay();
  1309. if ((dayOfWeek == 0) && (opt.startOfWeek == 'monday')) {
  1310. // add one week
  1311. dayOfWeek = 7;
  1312. }
  1313. if (dayOfWeek > 0) {
  1314. for (var i = dayOfWeek; i > 0; i--) {
  1315. var day = new Date(d.getTime() - 86400000 * i);
  1316. var valid = true;
  1317. if (opt.startDate && compare_day(day, opt.startDate) < 0) valid = false;
  1318. if (opt.endDate && compare_day(day, opt.endDate) > 0) valid = false;
  1319. days.push({ type: 'lastMonth', day: day.getDate(), time: day.getTime(), valid: valid });
  1320. }
  1321. }
  1322. var toMonth = d.getMonth();
  1323. for (var i = 0; i < 40; i++) {
  1324. var today = moment(d).add(i, 'days').toDate();
  1325. var valid = true;
  1326. if (opt.startDate && compare_day(today, opt.startDate) < 0) valid = false;
  1327. if (opt.endDate && compare_day(today, opt.endDate) > 0) valid = false;
  1328. days.push({ type: today.getMonth() == toMonth ? 'toMonth' : 'nextMonth', day: today.getDate(), time: today.getTime(), valid: valid });
  1329. }
  1330. var html = [];
  1331. for (var week = 0; week < 6; week++) {
  1332. if (days[week * 7].type == 'nextMonth') break;
  1333. html.push('<tr>');
  1334. for (var day = 0; day < 7; day++) {
  1335. var _day = (opt.startOfWeek == 'monday') ? day + 1 : day;
  1336. var today = days[week * 7 + _day];
  1337. var highlightToday = moment(today.time).format('L') == moment(now).format('L');
  1338. today.extraClass = '';
  1339. today.tooltip = '';
  1340. if (opt.beforeShowDay && typeof opt.beforeShowDay == 'function') {
  1341. var _r = opt.beforeShowDay(moment(today.time).toDate());
  1342. today.valid = _r[0];
  1343. today.extraClass = _r[1] || '';
  1344. today.tooltip = _r[2] || '';
  1345. if (today.tooltip != '') today.extraClass += ' has-tooltip ';
  1346. }
  1347. todayDivAttr = {
  1348. time: today.time,
  1349. title: today.tooltip,
  1350. class: 'day ' + today.type + ' ' + today.extraClass + ' ' + (today.valid ? 'valid' : 'invalid') + ' ' + (highlightToday ? 'real-today' : '')
  1351. };
  1352. html.push('<td ' + attributesCallbacks({}, opt.dayTdAttrs, today) + '><div ' + attributesCallbacks(todayDivAttr, opt.dayDivAttrs, today) + '>' + today.day + '</div></td>');
  1353. }
  1354. html.push('</tr>');
  1355. }
  1356. return html.join('');
  1357. }
  1358. function getLanguages() {
  1359. if (opt.language == 'auto') {
  1360. var language = navigator.language ? navigator.language : navigator.browserLanguage;
  1361. if (!language) return $.dateRangePickerLanguages['en'];
  1362. var language = language.toLowerCase();
  1363. for (var key in $.dateRangePickerLanguages) {
  1364. if (language.indexOf(key) != -1) {
  1365. return $.dateRangePickerLanguages[key];
  1366. }
  1367. }
  1368. return $.dateRangePickerLanguages['en'];
  1369. }
  1370. else if (opt.language && opt.language in $.dateRangePickerLanguages) {
  1371. return $.dateRangePickerLanguages[opt.language];
  1372. }
  1373. else {
  1374. return $.dateRangePickerLanguages['en'];
  1375. }
  1376. }
  1377. function lang(t) {
  1378. return (t in langs) ? langs[t] : t;
  1379. }
  1380. };
  1381. }));