inputmask.date.extensions.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603
  1. /*
  2. Input Mask plugin extensions
  3. http://github.com/RobinHerbots/jquery.inputmask
  4. Copyright (c) 2010 - Robin Herbots
  5. Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
  6. Version: 0.0.0-dev
  7. Optional extensions on the jquery.inputmask base
  8. */
  9. (function($) {
  10. //date & time aliases
  11. inputmask.extendDefinitions({
  12. 'h': { //hours
  13. validator: "[01][0-9]|2[0-3]",
  14. cardinality: 2,
  15. prevalidator: [{
  16. validator: "[0-2]",
  17. cardinality: 1
  18. }]
  19. },
  20. 's': { //seconds || minutes
  21. validator: "[0-5][0-9]",
  22. cardinality: 2,
  23. prevalidator: [{
  24. validator: "[0-5]",
  25. cardinality: 1
  26. }]
  27. },
  28. 'd': { //basic day
  29. validator: "0[1-9]|[12][0-9]|3[01]",
  30. cardinality: 2,
  31. prevalidator: [{
  32. validator: "[0-3]",
  33. cardinality: 1
  34. }]
  35. },
  36. 'm': { //basic month
  37. validator: "0[1-9]|1[012]",
  38. cardinality: 2,
  39. prevalidator: [{
  40. validator: "[01]",
  41. cardinality: 1
  42. }]
  43. },
  44. 'y': { //basic year
  45. validator: "(19|20)\\d{2}",
  46. cardinality: 4,
  47. prevalidator: [{
  48. validator: "[12]",
  49. cardinality: 1
  50. }, {
  51. validator: "(19|20)",
  52. cardinality: 2
  53. }, {
  54. validator: "(19|20)\\d",
  55. cardinality: 3
  56. }]
  57. }
  58. });
  59. inputmask.extendAliases({
  60. 'dd/mm/yyyy': {
  61. mask: "1/2/y",
  62. placeholder: "dd/mm/yyyy",
  63. regex: {
  64. val1pre: new RegExp("[0-3]"), //daypre
  65. val1: new RegExp("0[1-9]|[12][0-9]|3[01]"), //day
  66. val2pre: function(separator) {
  67. var escapedSeparator = $.inputmask.escapeRegex.call(this, separator);
  68. return new RegExp("((0[1-9]|[12][0-9]|3[01])" + escapedSeparator + "[01])");
  69. }, //monthpre
  70. val2: function(separator) {
  71. var escapedSeparator = $.inputmask.escapeRegex.call(this, separator);
  72. return new RegExp("((0[1-9]|[12][0-9])" + escapedSeparator + "(0[1-9]|1[012]))|(30" + escapedSeparator + "(0[13-9]|1[012]))|(31" + escapedSeparator + "(0[13578]|1[02]))");
  73. } //month
  74. },
  75. leapday: "29/02/",
  76. separator: '/',
  77. yearrange: {
  78. minyear: 1900,
  79. maxyear: 2099
  80. },
  81. isInYearRange: function(chrs, minyear, maxyear) {
  82. if (isNaN(chrs)) return false;
  83. var enteredyear = parseInt(chrs.concat(minyear.toString().slice(chrs.length)));
  84. var enteredyear2 = parseInt(chrs.concat(maxyear.toString().slice(chrs.length)));
  85. return (!isNaN(enteredyear) ? minyear <= enteredyear && enteredyear <= maxyear : false) ||
  86. (!isNaN(enteredyear2) ? minyear <= enteredyear2 && enteredyear2 <= maxyear : false);
  87. },
  88. determinebaseyear: function(minyear, maxyear, hint) {
  89. var currentyear = (new Date()).getFullYear();
  90. if (minyear > currentyear) return minyear;
  91. if (maxyear < currentyear) {
  92. var maxYearPrefix = maxyear.toString().slice(0, 2);
  93. var maxYearPostfix = maxyear.toString().slice(2, 4);
  94. while (maxyear < maxYearPrefix + hint) {
  95. maxYearPrefix--;
  96. }
  97. var maxxYear = maxYearPrefix + maxYearPostfix;
  98. return minyear > maxxYear ? minyear : maxxYear;
  99. }
  100. return currentyear;
  101. },
  102. onKeyDown: function(e, buffer, caretPos, opts) {
  103. var $input = $(this);
  104. if (e.ctrlKey && e.keyCode == $.inputmask.keyCode.RIGHT) {
  105. var today = new Date();
  106. $input.val(today.getDate().toString() + (today.getMonth() + 1).toString() + today.getFullYear().toString());
  107. $input.triggerHandler('setvalue.inputmask');
  108. }
  109. },
  110. getFrontValue: function(mask, buffer, opts) {
  111. var start = 0,
  112. length = 0;
  113. for (var i = 0; i < mask.length; i++) {
  114. if (mask.charAt(i) == "2")
  115. break;
  116. var definition = opts.definitions[mask.charAt(i)];
  117. if (definition) {
  118. start += length;
  119. length = definition.cardinality;
  120. } else length++;
  121. }
  122. return buffer.join('').substr(start, length);
  123. },
  124. definitions: {
  125. '1': { //val1 ~ day or month
  126. validator: function(chrs, maskset, pos, strict, opts) {
  127. var isValid = opts.regex.val1.test(chrs);
  128. if (!strict && !isValid) {
  129. if (chrs.charAt(1) == opts.separator || "-./".indexOf(chrs.charAt(1)) != -1) {
  130. isValid = opts.regex.val1.test("0" + chrs.charAt(0));
  131. if (isValid) {
  132. maskset.buffer[pos - 1] = "0";
  133. return {
  134. "refreshFromBuffer": {
  135. start: pos - 1,
  136. end: pos
  137. },
  138. "pos": pos,
  139. "c": chrs.charAt(0)
  140. };
  141. }
  142. }
  143. }
  144. return isValid;
  145. },
  146. cardinality: 2,
  147. prevalidator: [{
  148. validator: function(chrs, maskset, pos, strict, opts) {
  149. var pchrs = chrs;
  150. if (!isNaN(maskset.buffer[pos + 1])) pchrs += maskset.buffer[pos + 1];
  151. var isValid = pchrs.length == 1 ? opts.regex.val1pre.test(pchrs) : opts.regex.val1.test(pchrs);
  152. if (!strict && !isValid) {
  153. isValid = opts.regex.val1.test(chrs + "0");
  154. if (isValid) {
  155. maskset.buffer[pos] = chrs;
  156. maskset.buffer[++pos] = "0";
  157. return {
  158. "pos": pos,
  159. "c": "0"
  160. };
  161. }
  162. isValid = opts.regex.val1.test("0" + chrs);
  163. if (isValid) {
  164. maskset.buffer[pos] = "0";
  165. pos++;
  166. return {
  167. "pos": pos
  168. };
  169. }
  170. }
  171. return isValid;
  172. },
  173. cardinality: 1
  174. }]
  175. },
  176. '2': { //val2 ~ day or month
  177. validator: function(chrs, maskset, pos, strict, opts) {
  178. var frontValue = opts.getFrontValue(maskset.mask, maskset.buffer, opts);
  179. if (frontValue.indexOf(opts.placeholder[0]) != -1) frontValue = "01" + opts.separator;
  180. var isValid = opts.regex.val2(opts.separator).test(frontValue + chrs);
  181. if (!strict && !isValid) {
  182. if (chrs.charAt(1) == opts.separator || "-./".indexOf(chrs.charAt(1)) != -1) {
  183. isValid = opts.regex.val2(opts.separator).test(frontValue + "0" + chrs.charAt(0));
  184. if (isValid) {
  185. maskset.buffer[pos - 1] = "0";
  186. return {
  187. "refreshFromBuffer": {
  188. start: pos - 1,
  189. end: pos
  190. },
  191. "pos": pos,
  192. "c": chrs.charAt(0)
  193. };
  194. }
  195. }
  196. }
  197. //check leap yeap
  198. if ((opts.mask.indexOf("2") == opts.mask.length - 1) && isValid) {
  199. var dayMonthValue = maskset.buffer.join('').substr(4, 4) + chrs;
  200. if (dayMonthValue != opts.leapday)
  201. return true;
  202. else {
  203. var year = parseInt(maskset.buffer.join('').substr(0, 4), 10); //detect leap year
  204. if (year % 4 === 0)
  205. if (year % 100 === 0)
  206. if (year % 400 === 0)
  207. return true;
  208. else return false;
  209. else return true;
  210. else return false;
  211. }
  212. }
  213. return isValid;
  214. },
  215. cardinality: 2,
  216. prevalidator: [{
  217. validator: function(chrs, maskset, pos, strict, opts) {
  218. if (!isNaN(maskset.buffer[pos + 1])) chrs += maskset.buffer[pos + 1];
  219. var frontValue = opts.getFrontValue(maskset.mask, maskset.buffer, opts);
  220. if (frontValue.indexOf(opts.placeholder[0]) != -1) frontValue = "01" + opts.separator;
  221. var isValid = chrs.length == 1 ? opts.regex.val2pre(opts.separator).test(frontValue + chrs) : opts.regex.val2(opts.separator).test(frontValue + chrs);
  222. if (!strict && !isValid) {
  223. isValid = opts.regex.val2(opts.separator).test(frontValue + "0" + chrs);
  224. if (isValid) {
  225. maskset.buffer[pos] = "0";
  226. pos++;
  227. return {
  228. "pos": pos
  229. };
  230. }
  231. }
  232. return isValid;
  233. },
  234. cardinality: 1
  235. }]
  236. },
  237. 'y': { //year
  238. validator: function(chrs, maskset, pos, strict, opts) {
  239. if (opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear)) {
  240. var dayMonthValue = maskset.buffer.join('').substr(0, 6);
  241. if (dayMonthValue != opts.leapday)
  242. return true;
  243. else {
  244. var year = parseInt(chrs, 10); //detect leap year
  245. if (year % 4 === 0)
  246. if (year % 100 === 0)
  247. if (year % 400 === 0)
  248. return true;
  249. else return false;
  250. else return true;
  251. else return false;
  252. }
  253. } else return false;
  254. },
  255. cardinality: 4,
  256. prevalidator: [{
  257. validator: function(chrs, maskset, pos, strict, opts) {
  258. var isValid = opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
  259. if (!strict && !isValid) {
  260. var yearPrefix = opts.determinebaseyear(opts.yearrange.minyear, opts.yearrange.maxyear, chrs + "0").toString().slice(0, 1);
  261. isValid = opts.isInYearRange(yearPrefix + chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
  262. if (isValid) {
  263. maskset.buffer[pos++] = yearPrefix.charAt(0);
  264. return {
  265. "pos": pos
  266. };
  267. }
  268. yearPrefix = opts.determinebaseyear(opts.yearrange.minyear, opts.yearrange.maxyear, chrs + "0").toString().slice(0, 2);
  269. isValid = opts.isInYearRange(yearPrefix + chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
  270. if (isValid) {
  271. maskset.buffer[pos++] = yearPrefix.charAt(0);
  272. maskset.buffer[pos++] = yearPrefix.charAt(1);
  273. return {
  274. "pos": pos
  275. };
  276. }
  277. }
  278. return isValid;
  279. },
  280. cardinality: 1
  281. }, {
  282. validator: function(chrs, maskset, pos, strict, opts) {
  283. var isValid = opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
  284. if (!strict && !isValid) {
  285. var yearPrefix = opts.determinebaseyear(opts.yearrange.minyear, opts.yearrange.maxyear, chrs).toString().slice(0, 2);
  286. isValid = opts.isInYearRange(chrs[0] + yearPrefix[1] + chrs[1], opts.yearrange.minyear, opts.yearrange.maxyear);
  287. if (isValid) {
  288. maskset.buffer[pos++] = yearPrefix.charAt(1);
  289. return {
  290. "pos": pos
  291. };
  292. }
  293. yearPrefix = opts.determinebaseyear(opts.yearrange.minyear, opts.yearrange.maxyear, chrs).toString().slice(0, 2);
  294. if (opts.isInYearRange(yearPrefix + chrs, opts.yearrange.minyear, opts.yearrange.maxyear)) {
  295. var dayMonthValue = maskset.buffer.join('').substr(0, 6);
  296. if (dayMonthValue != opts.leapday)
  297. isValid = true;
  298. else {
  299. var year = parseInt(chrs, 10); //detect leap year
  300. if (year % 4 === 0)
  301. if (year % 100 === 0)
  302. if (year % 400 === 0)
  303. isValid = true;
  304. else isValid = false;
  305. else isValid = true;
  306. else isValid = false;
  307. }
  308. } else isValid = false;
  309. if (isValid) {
  310. maskset.buffer[pos - 1] = yearPrefix.charAt(0);
  311. maskset.buffer[pos++] = yearPrefix.charAt(1);
  312. maskset.buffer[pos++] = chrs.charAt(0);
  313. return {
  314. "refreshFromBuffer": {
  315. start: pos - 3,
  316. end: pos
  317. },
  318. "pos": pos
  319. };
  320. }
  321. }
  322. return isValid;
  323. },
  324. cardinality: 2
  325. }, {
  326. validator: function(chrs, maskset, pos, strict, opts) {
  327. return opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
  328. },
  329. cardinality: 3
  330. }]
  331. }
  332. },
  333. insertMode: false,
  334. autoUnmask: false
  335. },
  336. 'mm/dd/yyyy': {
  337. placeholder: "mm/dd/yyyy",
  338. alias: "dd/mm/yyyy", //reuse functionality of dd/mm/yyyy alias
  339. regex: {
  340. val2pre: function(separator) {
  341. var escapedSeparator = $.inputmask.escapeRegex.call(this, separator);
  342. return new RegExp("((0[13-9]|1[012])" + escapedSeparator + "[0-3])|(02" + escapedSeparator + "[0-2])");
  343. }, //daypre
  344. val2: function(separator) {
  345. var escapedSeparator = $.inputmask.escapeRegex.call(this, separator);
  346. return new RegExp("((0[1-9]|1[012])" + escapedSeparator + "(0[1-9]|[12][0-9]))|((0[13-9]|1[012])" + escapedSeparator + "30)|((0[13578]|1[02])" + escapedSeparator + "31)");
  347. }, //day
  348. val1pre: new RegExp("[01]"), //monthpre
  349. val1: new RegExp("0[1-9]|1[012]") //month
  350. },
  351. leapday: "02/29/",
  352. onKeyDown: function(e, buffer, caretPos, opts) {
  353. var $input = $(this);
  354. if (e.ctrlKey && e.keyCode == $.inputmask.keyCode.RIGHT) {
  355. var today = new Date();
  356. $input.val((today.getMonth() + 1).toString() + today.getDate().toString() + today.getFullYear().toString());
  357. $input.triggerHandler('setvalue.inputmask');
  358. }
  359. }
  360. },
  361. 'yyyy/mm/dd': {
  362. mask: "y/1/2",
  363. placeholder: "yyyy/mm/dd",
  364. alias: "mm/dd/yyyy",
  365. leapday: "/02/29",
  366. onKeyDown: function(e, buffer, caretPos, opts) {
  367. var $input = $(this);
  368. if (e.ctrlKey && e.keyCode == $.inputmask.keyCode.RIGHT) {
  369. var today = new Date();
  370. $input.val(today.getFullYear().toString() + (today.getMonth() + 1).toString() + today.getDate().toString());
  371. $input.triggerHandler('setvalue.inputmask');
  372. }
  373. }
  374. },
  375. 'dd.mm.yyyy': {
  376. mask: "1.2.y",
  377. placeholder: "dd.mm.yyyy",
  378. leapday: "29.02.",
  379. separator: '.',
  380. alias: "dd/mm/yyyy"
  381. },
  382. 'dd-mm-yyyy': {
  383. mask: "1-2-y",
  384. placeholder: "dd-mm-yyyy",
  385. leapday: "29-02-",
  386. separator: '-',
  387. alias: "dd/mm/yyyy"
  388. },
  389. 'mm.dd.yyyy': {
  390. mask: "1.2.y",
  391. placeholder: "mm.dd.yyyy",
  392. leapday: "02.29.",
  393. separator: '.',
  394. alias: "mm/dd/yyyy"
  395. },
  396. 'mm-dd-yyyy': {
  397. mask: "1-2-y",
  398. placeholder: "mm-dd-yyyy",
  399. leapday: "02-29-",
  400. separator: '-',
  401. alias: "mm/dd/yyyy"
  402. },
  403. 'yyyy.mm.dd': {
  404. mask: "y.1.2",
  405. placeholder: "yyyy.mm.dd",
  406. leapday: ".02.29",
  407. separator: '.',
  408. alias: "yyyy/mm/dd"
  409. },
  410. 'yyyy-mm-dd': {
  411. mask: "y-1-2",
  412. placeholder: "yyyy-mm-dd",
  413. leapday: "-02-29",
  414. separator: '-',
  415. alias: "yyyy/mm/dd"
  416. },
  417. 'datetime': {
  418. mask: "1/2/y h:s",
  419. placeholder: "dd/mm/yyyy hh:mm",
  420. alias: "dd/mm/yyyy",
  421. regex: {
  422. hrspre: new RegExp("[012]"), //hours pre
  423. hrs24: new RegExp("2[0-4]|1[3-9]"),
  424. hrs: new RegExp("[01][0-9]|2[0-4]"), //hours
  425. ampm: new RegExp("^[a|p|A|P][m|M]"),
  426. mspre: new RegExp("[0-5]"), //minutes/seconds pre
  427. ms: new RegExp("[0-5][0-9]")
  428. },
  429. timeseparator: ':',
  430. hourFormat: "24", // or 12
  431. definitions: {
  432. 'h': { //hours
  433. validator: function(chrs, maskset, pos, strict, opts) {
  434. if (opts.hourFormat == "24") {
  435. if (parseInt(chrs, 10) == 24) {
  436. maskset.buffer[pos - 1] = "0";
  437. maskset.buffer[pos] = "0";
  438. return {
  439. "refreshFromBuffer": {
  440. start: pos - 1,
  441. end: pos
  442. },
  443. "c": "0"
  444. };
  445. }
  446. }
  447. var isValid = opts.regex.hrs.test(chrs);
  448. if (!strict && !isValid) {
  449. if (chrs.charAt(1) == opts.timeseparator || "-.:".indexOf(chrs.charAt(1)) != -1) {
  450. isValid = opts.regex.hrs.test("0" + chrs.charAt(0));
  451. if (isValid) {
  452. maskset.buffer[pos - 1] = "0";
  453. maskset.buffer[pos] = chrs.charAt(0);
  454. pos++;
  455. return {
  456. "refreshFromBuffer": {
  457. start: pos - 2,
  458. end: pos
  459. },
  460. "pos": pos,
  461. "c": opts.timeseparator
  462. };
  463. }
  464. }
  465. }
  466. if (isValid && opts.hourFormat !== "24" && opts.regex.hrs24.test(chrs)) {
  467. var tmp = parseInt(chrs, 10);
  468. if (tmp == 24) {
  469. maskset.buffer[pos + 5] = "a";
  470. maskset.buffer[pos + 6] = "m";
  471. } else {
  472. maskset.buffer[pos + 5] = "p";
  473. maskset.buffer[pos + 6] = "m";
  474. }
  475. tmp = tmp - 12;
  476. if (tmp < 10) {
  477. maskset.buffer[pos] = tmp.toString();
  478. maskset.buffer[pos - 1] = "0";
  479. } else {
  480. maskset.buffer[pos] = tmp.toString().charAt(1);
  481. maskset.buffer[pos - 1] = tmp.toString().charAt(0);
  482. }
  483. return {
  484. "refreshFromBuffer": {
  485. start: pos - 1,
  486. end: pos + 6
  487. },
  488. "c": maskset.buffer[pos]
  489. };
  490. }
  491. return isValid;
  492. },
  493. cardinality: 2,
  494. prevalidator: [{
  495. validator: function(chrs, maskset, pos, strict, opts) {
  496. var isValid = opts.regex.hrspre.test(chrs);
  497. if (!strict && !isValid) {
  498. isValid = opts.regex.hrs.test("0" + chrs);
  499. if (isValid) {
  500. maskset.buffer[pos] = "0";
  501. pos++;
  502. return {
  503. "pos": pos
  504. };
  505. }
  506. }
  507. return isValid;
  508. },
  509. cardinality: 1
  510. }]
  511. },
  512. 's': { //seconds || minutes
  513. validator: "[0-5][0-9]",
  514. cardinality: 2,
  515. prevalidator: [{
  516. validator: function(chrs, maskset, pos, strict, opts) {
  517. var isValid = opts.regex.mspre.test(chrs);
  518. if (!strict && !isValid) {
  519. isValid = opts.regex.ms.test("0" + chrs);
  520. if (isValid) {
  521. maskset.buffer[pos] = "0";
  522. pos++;
  523. return {
  524. "pos": pos
  525. };
  526. }
  527. }
  528. return isValid;
  529. },
  530. cardinality: 1
  531. }]
  532. },
  533. 't': { //am/pm
  534. validator: function(chrs, maskset, pos, strict, opts) {
  535. return opts.regex.ampm.test(chrs + "m");
  536. },
  537. casing: "lower",
  538. cardinality: 1
  539. }
  540. },
  541. insertMode: false,
  542. autoUnmask: false
  543. },
  544. 'datetime12': {
  545. mask: "1/2/y h:s t\\m",
  546. placeholder: "dd/mm/yyyy hh:mm xm",
  547. alias: "datetime",
  548. hourFormat: "12"
  549. },
  550. 'hh:mm t': {
  551. mask: "h:s t\\m",
  552. placeholder: "hh:mm xm",
  553. alias: "datetime",
  554. hourFormat: "12"
  555. },
  556. 'h:s t': {
  557. mask: "h:s t\\m",
  558. placeholder: "hh:mm xm",
  559. alias: "datetime",
  560. hourFormat: "12"
  561. },
  562. 'hh:mm:ss': {
  563. mask: "h:s:s",
  564. placeholder: "hh:mm:ss",
  565. alias: "datetime",
  566. autoUnmask: false
  567. },
  568. 'hh:mm': {
  569. mask: "h:s",
  570. placeholder: "hh:mm",
  571. alias: "datetime",
  572. autoUnmask: false
  573. },
  574. 'date': {
  575. alias: "dd/mm/yyyy" // "mm/dd/yyyy"
  576. },
  577. 'mm/yyyy': {
  578. mask: "1/y",
  579. placeholder: "mm/yyyy",
  580. leapday: "donotuse",
  581. separator: '/',
  582. alias: "mm/dd/yyyy"
  583. }
  584. });
  585. return inputmask;
  586. })(jQuery);