/ajax/libs/later/1.1.7/later-core.js

https://gitlab.com/Mirros/cdnjs · JavaScript · 912 lines · 912 code · 0 blank · 0 comment · 218 complexity · 41a2ca371db626c765b22a467ce6b4fc MD5 · raw file

  1. later = function() {
  2. "use strict";
  3. var later = {
  4. version: "1.1.7"
  5. };
  6. if (!Array.prototype.indexOf) {
  7. Array.prototype.indexOf = function(searchElement) {
  8. "use strict";
  9. if (this == null) {
  10. throw new TypeError();
  11. }
  12. var t = Object(this);
  13. var len = t.length >>> 0;
  14. if (len === 0) {
  15. return -1;
  16. }
  17. var n = 0;
  18. if (arguments.length > 1) {
  19. n = Number(arguments[1]);
  20. if (n != n) {
  21. n = 0;
  22. } else if (n != 0 && n != Infinity && n != -Infinity) {
  23. n = (n > 0 || -1) * Math.floor(Math.abs(n));
  24. }
  25. }
  26. if (n >= len) {
  27. return -1;
  28. }
  29. var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
  30. for (;k < len; k++) {
  31. if (k in t && t[k] === searchElement) {
  32. return k;
  33. }
  34. }
  35. return -1;
  36. };
  37. }
  38. if (!String.prototype.trim) {
  39. String.prototype.trim = function() {
  40. return this.replace(/^\s+|\s+$/g, "");
  41. };
  42. }
  43. later.array = {};
  44. later.array.sort = function(arr, zeroIsLast) {
  45. arr.sort(function(a, b) {
  46. return +a - +b;
  47. });
  48. if (zeroIsLast && arr[0] === 0) {
  49. arr.push(arr.shift());
  50. }
  51. };
  52. later.array.next = function(val, values, extent) {
  53. var cur, zeroIsLargest = extent[0] !== 0, nextIdx = 0;
  54. for (var i = values.length - 1; i > -1; --i) {
  55. cur = values[i];
  56. if (cur === val) {
  57. return cur;
  58. }
  59. if (cur > val || cur === 0 && zeroIsLargest && extent[1] > val) {
  60. nextIdx = i;
  61. continue;
  62. }
  63. break;
  64. }
  65. return values[nextIdx];
  66. };
  67. later.array.nextInvalid = function(val, values, extent) {
  68. var min = extent[0], max = extent[1], len = values.length, zeroVal = values[len - 1] === 0 && min !== 0 ? max : 0, next = val, i = values.indexOf(val), start = next;
  69. while (next === (values[i] || zeroVal)) {
  70. next++;
  71. if (next > max) {
  72. next = min;
  73. }
  74. i++;
  75. if (i === len) {
  76. i = 0;
  77. }
  78. if (next === start) {
  79. return undefined;
  80. }
  81. }
  82. return next;
  83. };
  84. later.array.prev = function(val, values, extent) {
  85. var cur, len = values.length, zeroIsLargest = extent[0] !== 0, prevIdx = len - 1;
  86. for (var i = 0; i < len; i++) {
  87. cur = values[i];
  88. if (cur === val) {
  89. return cur;
  90. }
  91. if (cur < val || cur === 0 && zeroIsLargest && extent[1] < val) {
  92. prevIdx = i;
  93. continue;
  94. }
  95. break;
  96. }
  97. return values[prevIdx];
  98. };
  99. later.array.prevInvalid = function(val, values, extent) {
  100. var min = extent[0], max = extent[1], len = values.length, zeroVal = values[len - 1] === 0 && min !== 0 ? max : 0, next = val, i = values.indexOf(val), start = next;
  101. while (next === (values[i] || zeroVal)) {
  102. next--;
  103. if (next < min) {
  104. next = max;
  105. }
  106. i--;
  107. if (i === -1) {
  108. i = len - 1;
  109. }
  110. if (next === start) {
  111. return undefined;
  112. }
  113. }
  114. return next;
  115. };
  116. later.day = later.D = {
  117. name: "day",
  118. range: 86400,
  119. val: function(d) {
  120. return d.D || (d.D = later.date.getDate.call(d));
  121. },
  122. isValid: function(d, val) {
  123. return later.D.val(d) === (val || later.D.extent(d)[1]);
  124. },
  125. extent: function(d) {
  126. if (d.DExtent) return d.DExtent;
  127. var month = later.M.val(d), max = later.DAYS_IN_MONTH[month - 1];
  128. if (month === 2 && later.dy.extent(d)[1] === 366) {
  129. max = max + 1;
  130. }
  131. return d.DExtent = [ 1, max ];
  132. },
  133. start: function(d) {
  134. return d.DStart || (d.DStart = later.date.next(later.Y.val(d), later.M.val(d), later.D.val(d)));
  135. },
  136. end: function(d) {
  137. return d.DEnd || (d.DEnd = later.date.prev(later.Y.val(d), later.M.val(d), later.D.val(d)));
  138. },
  139. next: function(d, val) {
  140. val = val > later.D.extent(d)[1] ? 1 : val;
  141. var month = later.date.nextRollover(d, val, later.D, later.M), DMax = later.D.extent(month)[1];
  142. val = val > DMax ? 1 : val || DMax;
  143. return later.date.next(later.Y.val(month), later.M.val(month), val);
  144. },
  145. prev: function(d, val) {
  146. var month = later.date.prevRollover(d, val, later.D, later.M), DMax = later.D.extent(month)[1];
  147. return later.date.prev(later.Y.val(month), later.M.val(month), val > DMax ? DMax : val || DMax);
  148. }
  149. };
  150. later.dayOfWeekCount = later.dc = {
  151. name: "day of week count",
  152. range: 604800,
  153. val: function(d) {
  154. return d.dc || (d.dc = Math.floor((later.D.val(d) - 1) / 7) + 1);
  155. },
  156. isValid: function(d, val) {
  157. return later.dc.val(d) === val || val === 0 && later.D.val(d) > later.D.extent(d)[1] - 7;
  158. },
  159. extent: function(d) {
  160. return d.dcExtent || (d.dcExtent = [ 1, Math.ceil(later.D.extent(d)[1] / 7) ]);
  161. },
  162. start: function(d) {
  163. return d.dcStart || (d.dcStart = later.date.next(later.Y.val(d), later.M.val(d), Math.max(1, (later.dc.val(d) - 1) * 7 + 1 || 1)));
  164. },
  165. end: function(d) {
  166. return d.dcEnd || (d.dcEnd = later.date.prev(later.Y.val(d), later.M.val(d), Math.min(later.dc.val(d) * 7, later.D.extent(d)[1])));
  167. },
  168. next: function(d, val) {
  169. val = val > later.dc.extent(d)[1] ? 1 : val;
  170. var month = later.date.nextRollover(d, val, later.dc, later.M), dcMax = later.dc.extent(month)[1];
  171. val = val > dcMax ? 1 : val;
  172. var next = later.date.next(later.Y.val(month), later.M.val(month), val === 0 ? later.D.extent(month)[1] - 6 : 1 + 7 * (val - 1));
  173. if (next.getTime() <= d.getTime()) {
  174. month = later.M.next(d, later.M.val(d) + 1);
  175. return later.date.next(later.Y.val(month), later.M.val(month), val === 0 ? later.D.extent(month)[1] - 6 : 1 + 7 * (val - 1));
  176. }
  177. return next;
  178. },
  179. prev: function(d, val) {
  180. var month = later.date.prevRollover(d, val, later.dc, later.M), dcMax = later.dc.extent(month)[1];
  181. val = val > dcMax ? dcMax : val || dcMax;
  182. return later.dc.end(later.date.prev(later.Y.val(month), later.M.val(month), 1 + 7 * (val - 1)));
  183. }
  184. };
  185. later.dayOfWeek = later.dw = later.d = {
  186. name: "day of week",
  187. range: 86400,
  188. val: function(d) {
  189. return d.dw || (d.dw = later.date.getDay.call(d) + 1);
  190. },
  191. isValid: function(d, val) {
  192. return later.dw.val(d) === (val || 7);
  193. },
  194. extent: function() {
  195. return [ 1, 7 ];
  196. },
  197. start: function(d) {
  198. return later.D.start(d);
  199. },
  200. end: function(d) {
  201. return later.D.end(d);
  202. },
  203. next: function(d, val) {
  204. val = val > 7 ? 1 : val || 7;
  205. return later.date.next(later.Y.val(d), later.M.val(d), later.D.val(d) + (val - later.dw.val(d)) + (val <= later.dw.val(d) ? 7 : 0));
  206. },
  207. prev: function(d, val) {
  208. val = val > 7 ? 7 : val || 7;
  209. return later.date.prev(later.Y.val(d), later.M.val(d), later.D.val(d) + (val - later.dw.val(d)) + (val >= later.dw.val(d) ? -7 : 0));
  210. }
  211. };
  212. later.dayOfYear = later.dy = {
  213. name: "day of year",
  214. range: 86400,
  215. val: function(d) {
  216. return d.dy || (d.dy = Math.ceil(1 + (later.D.start(d).getTime() - later.Y.start(d).getTime()) / later.DAY));
  217. },
  218. isValid: function(d, val) {
  219. return later.dy.val(d) === (val || later.dy.extent(d)[1]);
  220. },
  221. extent: function(d) {
  222. var year = later.Y.val(d);
  223. return d.dyExtent || (d.dyExtent = [ 1, year % 4 ? 365 : 366 ]);
  224. },
  225. start: function(d) {
  226. return later.D.start(d);
  227. },
  228. end: function(d) {
  229. return later.D.end(d);
  230. },
  231. next: function(d, val) {
  232. val = val > later.dy.extent(d)[1] ? 1 : val;
  233. var year = later.date.nextRollover(d, val, later.dy, later.Y), dyMax = later.dy.extent(year)[1];
  234. val = val > dyMax ? 1 : val || dyMax;
  235. return later.date.next(later.Y.val(year), later.M.val(year), val);
  236. },
  237. prev: function(d, val) {
  238. var year = later.date.prevRollover(d, val, later.dy, later.Y), dyMax = later.dy.extent(year)[1];
  239. val = val > dyMax ? dyMax : val || dyMax;
  240. return later.date.prev(later.Y.val(year), later.M.val(year), val);
  241. }
  242. };
  243. later.hour = later.h = {
  244. name: "hour",
  245. range: 3600,
  246. val: function(d) {
  247. return d.h || (d.h = later.date.getHour.call(d));
  248. },
  249. isValid: function(d, val) {
  250. return later.h.val(d) === val;
  251. },
  252. extent: function() {
  253. return [ 0, 23 ];
  254. },
  255. start: function(d) {
  256. return d.hStart || (d.hStart = later.date.next(later.Y.val(d), later.M.val(d), later.D.val(d), later.h.val(d)));
  257. },
  258. end: function(d) {
  259. return d.hEnd || (d.hEnd = later.date.prev(later.Y.val(d), later.M.val(d), later.D.val(d), later.h.val(d)));
  260. },
  261. next: function(d, val) {
  262. val = val > 23 ? 0 : val;
  263. var next = later.date.next(later.Y.val(d), later.M.val(d), later.D.val(d) + (val <= later.h.val(d) ? 1 : 0), val);
  264. if (!later.date.isUTC && next.getTime() <= d.getTime()) {
  265. next = later.date.next(later.Y.val(next), later.M.val(next), later.D.val(next), val + 1);
  266. }
  267. return next;
  268. },
  269. prev: function(d, val) {
  270. val = val > 23 ? 23 : val;
  271. return later.date.prev(later.Y.val(d), later.M.val(d), later.D.val(d) + (val >= later.h.val(d) ? -1 : 0), val);
  272. }
  273. };
  274. later.minute = later.m = {
  275. name: "minute",
  276. range: 60,
  277. val: function(d) {
  278. return d.m || (d.m = later.date.getMin.call(d));
  279. },
  280. isValid: function(d, val) {
  281. return later.m.val(d) === val;
  282. },
  283. extent: function(d) {
  284. return [ 0, 59 ];
  285. },
  286. start: function(d) {
  287. return d.mStart || (d.mStart = later.date.next(later.Y.val(d), later.M.val(d), later.D.val(d), later.h.val(d), later.m.val(d)));
  288. },
  289. end: function(d) {
  290. return d.mEnd || (d.mEnd = later.date.prev(later.Y.val(d), later.M.val(d), later.D.val(d), later.h.val(d), later.m.val(d)));
  291. },
  292. next: function(d, val) {
  293. var m = later.m.val(d), s = later.s.val(d), inc = val > 59 ? 60 - m : val <= m ? 60 - m + val : val - m, next = new Date(d.getTime() + inc * later.MIN - s * later.SEC);
  294. if (!later.date.isUTC && next.getTime() <= d.getTime()) {
  295. next = new Date(d.getTime() + (inc + 120) * later.MIN - s * later.SEC);
  296. }
  297. return next;
  298. },
  299. prev: function(d, val) {
  300. val = val > 59 ? 59 : val;
  301. return later.date.prev(later.Y.val(d), later.M.val(d), later.D.val(d), later.h.val(d) + (val >= later.m.val(d) ? -1 : 0), val);
  302. }
  303. };
  304. later.month = later.M = {
  305. name: "month",
  306. range: 2629740,
  307. val: function(d) {
  308. return d.M || (d.M = later.date.getMonth.call(d) + 1);
  309. },
  310. isValid: function(d, val) {
  311. return later.M.val(d) === (val || 12);
  312. },
  313. extent: function() {
  314. return [ 1, 12 ];
  315. },
  316. start: function(d) {
  317. return d.MStart || (d.MStart = later.date.next(later.Y.val(d), later.M.val(d)));
  318. },
  319. end: function(d) {
  320. return d.MEnd || (d.MEnd = later.date.prev(later.Y.val(d), later.M.val(d)));
  321. },
  322. next: function(d, val) {
  323. val = val > 12 ? 1 : val || 12;
  324. return later.date.next(later.Y.val(d) + (val > later.M.val(d) ? 0 : 1), val);
  325. },
  326. prev: function(d, val) {
  327. val = val > 12 ? 12 : val || 12;
  328. return later.date.prev(later.Y.val(d) - (val >= later.M.val(d) ? 1 : 0), val);
  329. }
  330. };
  331. later.second = later.s = {
  332. name: "second",
  333. range: 1,
  334. val: function(d) {
  335. return d.s || (d.s = later.date.getSec.call(d));
  336. },
  337. isValid: function(d, val) {
  338. return later.s.val(d) === val;
  339. },
  340. extent: function() {
  341. return [ 0, 59 ];
  342. },
  343. start: function(d) {
  344. return d;
  345. },
  346. end: function(d) {
  347. return d;
  348. },
  349. next: function(d, val) {
  350. var s = later.s.val(d), inc = val > 59 ? 60 - s : val <= s ? 60 - s + val : val - s, next = new Date(d.getTime() + inc * later.SEC);
  351. if (!later.date.isUTC && next.getTime() <= d.getTime()) {
  352. next = new Date(d.getTime() + (inc + 7200) * later.SEC);
  353. }
  354. return next;
  355. },
  356. prev: function(d, val, cache) {
  357. val = val > 59 ? 59 : val;
  358. return later.date.prev(later.Y.val(d), later.M.val(d), later.D.val(d), later.h.val(d), later.m.val(d) + (val >= later.s.val(d) ? -1 : 0), val);
  359. }
  360. };
  361. later.time = later.t = {
  362. name: "time",
  363. range: 1,
  364. val: function(d) {
  365. return d.t || (d.t = later.h.val(d) * 3600 + later.m.val(d) * 60 + later.s.val(d));
  366. },
  367. isValid: function(d, val) {
  368. return later.t.val(d) === val;
  369. },
  370. extent: function() {
  371. return [ 0, 86399 ];
  372. },
  373. start: function(d) {
  374. return d;
  375. },
  376. end: function(d) {
  377. return d;
  378. },
  379. next: function(d, val) {
  380. val = val > 86399 ? 0 : val;
  381. var next = later.date.next(later.Y.val(d), later.M.val(d), later.D.val(d) + (val <= later.t.val(d) ? 1 : 0), 0, 0, val);
  382. if (!later.date.isUTC && next.getTime() < d.getTime()) {
  383. next = later.date.next(later.Y.val(next), later.M.val(next), later.D.val(next), later.h.val(next), later.m.val(next), val + 7200);
  384. }
  385. return next;
  386. },
  387. prev: function(d, val) {
  388. val = val > 86399 ? 86399 : val;
  389. return later.date.next(later.Y.val(d), later.M.val(d), later.D.val(d) + (val >= later.t.val(d) ? -1 : 0), 0, 0, val);
  390. }
  391. };
  392. later.weekOfMonth = later.wm = {
  393. name: "week of month",
  394. range: 604800,
  395. val: function(d) {
  396. return d.wm || (d.wm = (later.D.val(d) + (later.dw.val(later.M.start(d)) - 1) + (7 - later.dw.val(d))) / 7);
  397. },
  398. isValid: function(d, val) {
  399. return later.wm.val(d) === (val || later.wm.extent(d)[1]);
  400. },
  401. extent: function(d) {
  402. return d.wmExtent || (d.wmExtent = [ 1, (later.D.extent(d)[1] + (later.dw.val(later.M.start(d)) - 1) + (7 - later.dw.val(later.M.end(d)))) / 7 ]);
  403. },
  404. start: function(d) {
  405. return d.wmStart || (d.wmStart = later.date.next(later.Y.val(d), later.M.val(d), Math.max(later.D.val(d) - later.dw.val(d) + 1, 1)));
  406. },
  407. end: function(d) {
  408. return d.wmEnd || (d.wmEnd = later.date.prev(later.Y.val(d), later.M.val(d), Math.min(later.D.val(d) + (7 - later.dw.val(d)), later.D.extent(d)[1])));
  409. },
  410. next: function(d, val) {
  411. val = val > later.wm.extent(d)[1] ? 1 : val;
  412. var month = later.date.nextRollover(d, val, later.wm, later.M), wmMax = later.wm.extent(month)[1];
  413. val = val > wmMax ? 1 : val || wmMax;
  414. return later.date.next(later.Y.val(month), later.M.val(month), Math.max(1, (val - 1) * 7 - (later.dw.val(month) - 2)));
  415. },
  416. prev: function(d, val) {
  417. var month = later.date.prevRollover(d, val, later.wm, later.M), wmMax = later.wm.extent(month)[1];
  418. val = val > wmMax ? wmMax : val || wmMax;
  419. return later.wm.end(later.date.next(later.Y.val(month), later.M.val(month), Math.max(1, (val - 1) * 7 - (later.dw.val(month) - 2))));
  420. }
  421. };
  422. later.weekOfYear = later.wy = {
  423. name: "week of year (ISO)",
  424. range: 604800,
  425. val: function(d) {
  426. if (d.wy) return d.wy;
  427. var wThur = later.dw.next(later.wy.start(d), 5), YThur = later.dw.next(later.Y.prev(wThur, later.Y.val(wThur) - 1), 5);
  428. return d.wy = 1 + Math.ceil((wThur.getTime() - YThur.getTime()) / later.WEEK);
  429. },
  430. isValid: function(d, val) {
  431. return later.wy.val(d) === (val || later.wy.extent(d)[1]);
  432. },
  433. extent: function(d) {
  434. if (d.wyExtent) return d.wyExtent;
  435. var year = later.dw.next(later.wy.start(d), 5), dwFirst = later.dw.val(later.Y.start(year)), dwLast = later.dw.val(later.Y.end(year));
  436. return d.wyExtent = [ 1, dwFirst === 5 || dwLast === 5 ? 53 : 52 ];
  437. },
  438. start: function(d) {
  439. return d.wyStart || (d.wyStart = later.date.next(later.Y.val(d), later.M.val(d), later.D.val(d) - (later.dw.val(d) > 1 ? later.dw.val(d) - 2 : 6)));
  440. },
  441. end: function(d) {
  442. return d.wyEnd || (d.wyEnd = later.date.prev(later.Y.val(d), later.M.val(d), later.D.val(d) + (later.dw.val(d) > 1 ? 8 - later.dw.val(d) : 0)));
  443. },
  444. next: function(d, val) {
  445. val = val > later.wy.extent(d)[1] ? 1 : val;
  446. var wyThur = later.dw.next(later.wy.start(d), 5), year = later.date.nextRollover(wyThur, val, later.wy, later.Y);
  447. if (later.wy.val(year) !== 1) {
  448. year = later.dw.next(year, 2);
  449. }
  450. var wyMax = later.wy.extent(year)[1], wyStart = later.wy.start(year);
  451. val = val > wyMax ? 1 : val || wyMax;
  452. return later.date.next(later.Y.val(wyStart), later.M.val(wyStart), later.D.val(wyStart) + 7 * (val - 1));
  453. },
  454. prev: function(d, val) {
  455. var wyThur = later.dw.next(later.wy.start(d), 5), year = later.date.prevRollover(wyThur, val, later.wy, later.Y);
  456. if (later.wy.val(year) !== 1) {
  457. year = later.dw.next(year, 2);
  458. }
  459. var wyMax = later.wy.extent(year)[1], wyEnd = later.wy.end(year);
  460. val = val > wyMax ? wyMax : val || wyMax;
  461. return later.wy.end(later.date.next(later.Y.val(wyEnd), later.M.val(wyEnd), later.D.val(wyEnd) + 7 * (val - 1)));
  462. }
  463. };
  464. later.year = later.Y = {
  465. name: "year",
  466. range: 31556900,
  467. val: function(d) {
  468. return d.Y || (d.Y = later.date.getYear.call(d));
  469. },
  470. isValid: function(d, val) {
  471. return later.Y.val(d) === val;
  472. },
  473. extent: function() {
  474. return [ 1970, 2099 ];
  475. },
  476. start: function(d) {
  477. return d.YStart || (d.YStart = later.date.next(later.Y.val(d)));
  478. },
  479. end: function(d) {
  480. return d.YEnd || (d.YEnd = later.date.prev(later.Y.val(d)));
  481. },
  482. next: function(d, val) {
  483. return val > later.Y.val(d) && val <= later.Y.extent()[1] ? later.date.next(val) : later.NEVER;
  484. },
  485. prev: function(d, val) {
  486. return val < later.Y.val(d) && val >= later.Y.extent()[0] ? later.date.prev(val) : later.NEVER;
  487. }
  488. };
  489. later.fullDate = later.fd = {
  490. name: "full date",
  491. range: 1,
  492. val: function(d) {
  493. return d.fd || (d.fd = d.getTime());
  494. },
  495. isValid: function(d, val) {
  496. return later.fd.val(d) === val;
  497. },
  498. extent: function() {
  499. return [ 0, 3250368e7 ];
  500. },
  501. start: function(d) {
  502. return d;
  503. },
  504. end: function(d) {
  505. return d;
  506. },
  507. next: function(d, val) {
  508. return later.fd.val(d) < val ? new Date(val) : later.NEVER;
  509. },
  510. prev: function(d, val) {
  511. return later.fd.val(d) > val ? new Date(val) : later.NEVER;
  512. }
  513. };
  514. later.modifier = {};
  515. later.modifier.after = later.modifier.a = function(constraint, values) {
  516. var value = values[0];
  517. return {
  518. name: "after " + constraint.name,
  519. range: (constraint.extent(new Date())[1] - value) * constraint.range,
  520. val: constraint.val,
  521. isValid: function(d, val) {
  522. return this.val(d) >= value;
  523. },
  524. extent: constraint.extent,
  525. start: constraint.start,
  526. end: constraint.end,
  527. next: function(startDate, val) {
  528. if (val != value) val = constraint.extent(startDate)[0];
  529. return constraint.next(startDate, val);
  530. },
  531. prev: function(startDate, val) {
  532. val = val === value ? constraint.extent(startDate)[1] : value - 1;
  533. return constraint.prev(startDate, val);
  534. }
  535. };
  536. };
  537. later.modifier.before = later.modifier.b = function(constraint, values) {
  538. var value = values[values.length - 1];
  539. return {
  540. name: "before " + constraint.name,
  541. range: constraint.range * (value - 1),
  542. val: constraint.val,
  543. isValid: function(d, val) {
  544. return this.val(d) < value;
  545. },
  546. extent: constraint.extent,
  547. start: constraint.start,
  548. end: constraint.end,
  549. next: function(startDate, val) {
  550. val = val === value ? constraint.extent(startDate)[0] : value;
  551. return constraint.next(startDate, val);
  552. },
  553. prev: function(startDate, val) {
  554. val = val === value ? value - 1 : constraint.extent(startDate)[1];
  555. return constraint.prev(startDate, val);
  556. }
  557. };
  558. };
  559. later.compile = function(schedDef) {
  560. var constraints = [], constraintsLen = 0, tickConstraint;
  561. for (var key in schedDef) {
  562. var nameParts = key.split("_"), name = nameParts[0], mod = nameParts[1], vals = schedDef[key], constraint = mod ? later.modifier[mod](later[name], vals) : later[name];
  563. constraints.push({
  564. constraint: constraint,
  565. vals: vals
  566. });
  567. constraintsLen++;
  568. }
  569. constraints.sort(function(a, b) {
  570. var ra = a.constraint.range, rb = b.constraint.range;
  571. return rb < ra ? -1 : rb > ra ? 1 : 0;
  572. });
  573. tickConstraint = constraints[constraintsLen - 1].constraint;
  574. function compareFn(dir) {
  575. return dir === "next" ? function(a, b) {
  576. return a.getTime() > b.getTime();
  577. } : function(a, b) {
  578. return b.getTime() > a.getTime();
  579. };
  580. }
  581. return {
  582. start: function(dir, startDate) {
  583. var next = startDate, nextVal = later.array[dir], maxAttempts = 1e3, done;
  584. while (maxAttempts-- && !done && next) {
  585. done = true;
  586. for (var i = 0; i < constraintsLen; i++) {
  587. var constraint = constraints[i].constraint, curVal = constraint.val(next), extent = constraint.extent(next), newVal = nextVal(curVal, constraints[i].vals, extent);
  588. if (!constraint.isValid(next, newVal)) {
  589. next = constraint[dir](next, newVal);
  590. done = false;
  591. break;
  592. }
  593. }
  594. }
  595. if (next !== later.NEVER) {
  596. next = dir === "next" ? tickConstraint.start(next) : tickConstraint.end(next);
  597. }
  598. return next;
  599. },
  600. end: function(dir, startDate) {
  601. var result, nextVal = later.array[dir + "Invalid"], compare = compareFn(dir);
  602. for (var i = constraintsLen - 1; i >= 0; i--) {
  603. var constraint = constraints[i].constraint, curVal = constraint.val(startDate), extent = constraint.extent(startDate), newVal = nextVal(curVal, constraints[i].vals, extent), next;
  604. if (newVal !== undefined) {
  605. next = constraint[dir](startDate, newVal);
  606. if (next && (!result || compare(result, next))) {
  607. result = next;
  608. }
  609. }
  610. }
  611. return result;
  612. },
  613. tick: function(dir, date) {
  614. return new Date(dir === "next" ? tickConstraint.end(date).getTime() + later.SEC : tickConstraint.start(date).getTime() - later.SEC);
  615. },
  616. tickStart: function(date) {
  617. return tickConstraint.start(date);
  618. }
  619. };
  620. };
  621. later.schedule = function(sched) {
  622. if (!sched) throw new Error("Missing schedule definition.");
  623. if (!sched.schedules) throw new Error("Definition must include at least one schedule.");
  624. var schedules = [], schedulesLen = sched.schedules.length, exceptions = [], exceptionsLen = sched.exceptions ? sched.exceptions.length : 0;
  625. for (var i = 0; i < schedulesLen; i++) {
  626. schedules.push(later.compile(sched.schedules[i]));
  627. }
  628. for (var j = 0; j < exceptionsLen; j++) {
  629. exceptions.push(later.compile(sched.exceptions[j]));
  630. }
  631. function getInstances(dir, count, startDate, endDate, isRange) {
  632. var compare = compareFn(dir), loopCount = count, maxAttempts = 1e3, schedStarts = [], exceptStarts = [], next, end, results = [], isForward = dir === "next", lastResult, rStart = isForward ? 0 : 1, rEnd = isForward ? 1 : 0;
  633. startDate = startDate ? new Date(startDate) : new Date();
  634. if (!startDate || !startDate.getTime()) throw new Error("Invalid start date.");
  635. setNextStarts(dir, schedules, schedStarts, startDate);
  636. setRangeStarts(dir, exceptions, exceptStarts, startDate);
  637. while (maxAttempts-- && loopCount && (next = findNext(schedStarts, compare))) {
  638. if (endDate && compare(next, endDate)) {
  639. break;
  640. }
  641. if (exceptionsLen) {
  642. updateRangeStarts(dir, exceptions, exceptStarts, next);
  643. if (end = calcRangeOverlap(dir, exceptStarts, next)) {
  644. updateNextStarts(dir, schedules, schedStarts, end);
  645. continue;
  646. }
  647. }
  648. if (isRange) {
  649. var maxEndDate = calcMaxEndDate(exceptStarts, compare);
  650. end = calcEnd(dir, schedules, schedStarts, next, maxEndDate);
  651. var r = isForward ? [ new Date(Math.max(startDate, next)), end ? new Date(endDate ? Math.min(end, endDate) : end) : undefined ] : [ end ? new Date(endDate ? Math.max(endDate, end.getTime() + later.SEC) : end.getTime() + later.SEC) : undefined, new Date(Math.min(startDate, next.getTime() + later.SEC)) ];
  652. if (lastResult && r[rStart].getTime() === lastResult[rEnd].getTime()) {
  653. lastResult[rEnd] = r[rEnd];
  654. loopCount++;
  655. } else {
  656. lastResult = r;
  657. results.push(lastResult);
  658. }
  659. if (!end) break;
  660. updateNextStarts(dir, schedules, schedStarts, end);
  661. } else {
  662. results.push(isForward ? new Date(Math.max(startDate, next)) : getStart(schedules, schedStarts, next, endDate));
  663. tickStarts(dir, schedules, schedStarts, next);
  664. }
  665. loopCount--;
  666. }
  667. for (var i = 0, len = results.length; i < len; i++) {
  668. var result = results[i];
  669. results[i] = Object.prototype.toString.call(result) === "[object Array]" ? [ cleanDate(result[0]), cleanDate(result[1]) ] : cleanDate(result);
  670. }
  671. return results.length === 0 ? later.NEVER : count === 1 ? results[0] : results;
  672. }
  673. function cleanDate(d) {
  674. if (d instanceof Date && !isNaN(d.valueOf())) {
  675. return new Date(d);
  676. }
  677. return undefined;
  678. }
  679. function setNextStarts(dir, schedArr, startsArr, startDate) {
  680. for (var i = 0, len = schedArr.length; i < len; i++) {
  681. startsArr[i] = schedArr[i].start(dir, startDate);
  682. }
  683. }
  684. function updateNextStarts(dir, schedArr, startsArr, startDate) {
  685. var compare = compareFn(dir);
  686. for (var i = 0, len = schedArr.length; i < len; i++) {
  687. if (startsArr[i] && !compare(startsArr[i], startDate)) {
  688. startsArr[i] = schedArr[i].start(dir, startDate);
  689. }
  690. }
  691. }
  692. function setRangeStarts(dir, schedArr, rangesArr, startDate) {
  693. var compare = compareFn(dir);
  694. for (var i = 0, len = schedArr.length; i < len; i++) {
  695. var nextStart = schedArr[i].start(dir, startDate);
  696. if (!nextStart) {
  697. rangesArr[i] = later.NEVER;
  698. } else {
  699. rangesArr[i] = [ nextStart, schedArr[i].end(dir, nextStart) ];
  700. }
  701. }
  702. }
  703. function updateRangeStarts(dir, schedArr, rangesArr, startDate) {
  704. var compare = compareFn(dir);
  705. for (var i = 0, len = schedArr.length; i < len; i++) {
  706. if (rangesArr[i] && !compare(rangesArr[i][0], startDate)) {
  707. var nextStart = schedArr[i].start(dir, startDate);
  708. if (!nextStart) {
  709. rangesArr[i] = later.NEVER;
  710. } else {
  711. rangesArr[i] = [ nextStart, schedArr[i].end(dir, nextStart) ];
  712. }
  713. }
  714. }
  715. }
  716. function tickStarts(dir, schedArr, startsArr, startDate) {
  717. for (var i = 0, len = schedArr.length; i < len; i++) {
  718. if (startsArr[i] && startsArr[i].getTime() === startDate.getTime()) {
  719. startsArr[i] = schedArr[i].start(dir, schedArr[i].tick(dir, startDate));
  720. }
  721. }
  722. }
  723. function getStart(schedArr, startsArr, startDate, minEndDate) {
  724. var result;
  725. for (var i = 0, len = startsArr.length; i < len; i++) {
  726. if (startsArr[i] && startsArr[i].getTime() === startDate.getTime()) {
  727. var start = schedArr[i].tickStart(startDate);
  728. if (minEndDate && start < minEndDate) {
  729. return minEndDate;
  730. }
  731. if (!result || start > result) {
  732. result = start;
  733. }
  734. }
  735. }
  736. return result;
  737. }
  738. function calcRangeOverlap(dir, rangesArr, startDate) {
  739. var compare = compareFn(dir), result;
  740. for (var i = 0, len = rangesArr.length; i < len; i++) {
  741. var range = rangesArr[i];
  742. if (range && !compare(range[0], startDate) && (!range[1] || compare(range[1], startDate))) {
  743. if (!result || compare(range[1], result)) {
  744. result = range[1];
  745. }
  746. }
  747. }
  748. return result;
  749. }
  750. function calcMaxEndDate(exceptsArr, compare) {
  751. var result;
  752. for (var i = 0, len = exceptsArr.length; i < len; i++) {
  753. if (exceptsArr[i] && (!result || compare(result, exceptsArr[i][0]))) {
  754. result = exceptsArr[i][0];
  755. }
  756. }
  757. return result;
  758. }
  759. function calcEnd(dir, schedArr, startsArr, startDate, maxEndDate) {
  760. var compare = compareFn(dir), result;
  761. for (var i = 0, len = schedArr.length; i < len; i++) {
  762. var start = startsArr[i];
  763. if (start && start.getTime() === startDate.getTime()) {
  764. var end = schedArr[i].end(dir, start);
  765. if (maxEndDate && (!end || compare(end, maxEndDate))) {
  766. return maxEndDate;
  767. }
  768. if (!result || compare(end, result)) {
  769. result = end;
  770. }
  771. }
  772. }
  773. return result;
  774. }
  775. function compareFn(dir) {
  776. return dir === "next" ? function(a, b) {
  777. return !b || a.getTime() > b.getTime();
  778. } : function(a, b) {
  779. return !a || b.getTime() > a.getTime();
  780. };
  781. }
  782. function findNext(arr, compare) {
  783. var next = arr[0];
  784. for (var i = 1, len = arr.length; i < len; i++) {
  785. if (arr[i] && compare(next, arr[i])) {
  786. next = arr[i];
  787. }
  788. }
  789. return next;
  790. }
  791. return {
  792. isValid: function(d) {
  793. return getInstances("next", 1, d, d) !== later.NEVER;
  794. },
  795. next: function(count, startDate, endDate) {
  796. return getInstances("next", count || 1, startDate, endDate);
  797. },
  798. prev: function(count, startDate, endDate) {
  799. return getInstances("prev", count || 1, startDate, endDate);
  800. },
  801. nextRange: function(count, startDate, endDate) {
  802. return getInstances("next", count || 1, startDate, endDate, true);
  803. },
  804. prevRange: function(count, startDate, endDate) {
  805. return getInstances("prev", count || 1, startDate, endDate, true);
  806. }
  807. };
  808. };
  809. later.setTimeout = function(fn, sched) {
  810. var s = later.schedule(sched), t;
  811. if (fn) {
  812. scheduleTimeout();
  813. }
  814. function scheduleTimeout() {
  815. var now = Date.now(), next = s.next(2, now);
  816. if (!next[0] || !next[1]) {
  817. t = undefined;
  818. return;
  819. }
  820. var diff = next[0].getTime() - now;
  821. if (diff < 1e3) {
  822. diff = next[1].getTime() - now;
  823. }
  824. if (diff < 2147483647) {
  825. t = setTimeout(fn, diff);
  826. } else {
  827. t = setTimeout(scheduleTimeout, 2147483647);
  828. }
  829. }
  830. return {
  831. isDone: function() {
  832. return !t;
  833. },
  834. clear: function() {
  835. clearTimeout(t);
  836. }
  837. };
  838. };
  839. later.setInterval = function(fn, sched) {
  840. if (!fn) {
  841. return;
  842. }
  843. var t = later.setTimeout(scheduleTimeout, sched), done = t.isDone();
  844. function scheduleTimeout() {
  845. if (!done) {
  846. fn();
  847. t = later.setTimeout(scheduleTimeout, sched);
  848. }
  849. }
  850. return {
  851. isDone: function() {
  852. return t.isDone();
  853. },
  854. clear: function() {
  855. done = true;
  856. t.clear();
  857. }
  858. };
  859. };
  860. later.date = {};
  861. later.date.timezone = function(useLocalTime) {
  862. later.date.build = useLocalTime ? function(Y, M, D, h, m, s) {
  863. return new Date(Y, M, D, h, m, s);
  864. } : function(Y, M, D, h, m, s) {
  865. return new Date(Date.UTC(Y, M, D, h, m, s));
  866. };
  867. var get = useLocalTime ? "get" : "getUTC", d = Date.prototype;
  868. later.date.getYear = d[get + "FullYear"];
  869. later.date.getMonth = d[get + "Month"];
  870. later.date.getDate = d[get + "Date"];
  871. later.date.getDay = d[get + "Day"];
  872. later.date.getHour = d[get + "Hours"];
  873. later.date.getMin = d[get + "Minutes"];
  874. later.date.getSec = d[get + "Seconds"];
  875. later.date.isUTC = !useLocalTime;
  876. };
  877. later.date.UTC = function() {
  878. later.date.timezone(false);
  879. };
  880. later.date.localTime = function() {
  881. later.date.timezone(true);
  882. };
  883. later.date.UTC();
  884. later.SEC = 1e3;
  885. later.MIN = later.SEC * 60;
  886. later.HOUR = later.MIN * 60;
  887. later.DAY = later.HOUR * 24;
  888. later.WEEK = later.DAY * 7;
  889. later.DAYS_IN_MONTH = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];
  890. later.NEVER = 0;
  891. later.date.next = function(Y, M, D, h, m, s) {
  892. return later.date.build(Y, M !== undefined ? M - 1 : 0, D !== undefined ? D : 1, h || 0, m || 0, s || 0);
  893. };
  894. later.date.nextRollover = function(d, val, constraint, period) {
  895. var cur = constraint.val(d), max = constraint.extent(d)[1];
  896. return (val || max) <= cur || val > max ? new Date(period.end(d).getTime() + later.SEC) : period.start(d);
  897. };
  898. later.date.prev = function(Y, M, D, h, m, s) {
  899. var len = arguments.length;
  900. M = len < 2 ? 11 : M - 1;
  901. D = len < 3 ? later.D.extent(later.date.next(Y, M + 1))[1] : D;
  902. h = len < 4 ? 23 : h;
  903. m = len < 5 ? 59 : m;
  904. s = len < 6 ? 59 : s;
  905. return later.date.build(Y, M, D, h, m, s);
  906. };
  907. later.date.prevRollover = function(d, val, constraint, period) {
  908. var cur = constraint.val(d);
  909. return val >= cur || !val ? period.start(period.prev(d, period.val(d) - 1)) : period.start(d);
  910. };
  911. return later;
  912. }();