jquery.datepick.validation.js 8.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /* http://keith-wood.name/datepick.html
  2. Datepicker Validation extension for jQuery 4.1.0.
  3. Requires Jörn Zaefferer's Validation plugin (http://plugins.jquery.com/project/validate).
  4. Written by Keith Wood (kbwood{at}iinet.com.au).
  5. Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and
  6. MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses.
  7. Please attribute the author if you use it. */
  8. (function($) { // Hide the namespace
  9. /* Add validation methods if validation plugin available. */
  10. if ($.fn.validate) {
  11. $.datepick.selectDateOrig = $.datepick.selectDate;
  12. $.extend($.datepick.regional[''], {
  13. validateDate: 'Please enter a valid date',
  14. validateDateMin: 'Please enter a date on or after {0}',
  15. validateDateMax: 'Please enter a date on or before {0}',
  16. validateDateMinMax: 'Please enter a date between {0} and {1}',
  17. validateDateCompare: 'Please enter a date {0} {1}',
  18. validateDateToday: 'today',
  19. validateDateOther: 'the other date',
  20. validateDateEQ: 'equal to',
  21. validateDateNE: 'not equal to',
  22. validateDateLT: 'before',
  23. validateDateGT: 'after',
  24. validateDateLE: 'not after',
  25. validateDateGE: 'not before'
  26. });
  27. $.extend($.datepick._defaults, $.datepick.regional['']);
  28. $.extend($.datepick, {
  29. /* Trigger a validation after updating the input field with the selected date.
  30. @param target (element) the control to examine
  31. @param elem (element) the selected datepicker element */
  32. selectDate: function(target, elem) {
  33. this.selectDateOrig(target, elem);
  34. var inst = $.data(target, $.datepick.propertyName);
  35. if (!inst.inline && $.fn.validate) {
  36. var validation = $(target).parents('form').validate();
  37. if (validation) {
  38. validation.element('#' + target.id);
  39. }
  40. }
  41. },
  42. /* Correct error placement for validation errors - after any trigger.
  43. @param error (jQuery) the error message
  44. @param element (jQuery) the field in error */
  45. errorPlacement: function(error, element) {
  46. var inst = $.data(element[0], $.datepick.propertyName);
  47. if (inst) {
  48. error[inst.options.isRTL ? 'insertBefore' : 'insertAfter'](
  49. inst.trigger.length > 0 ? inst.trigger : element);
  50. }
  51. else {
  52. error.insertAfter(element);
  53. }
  54. },
  55. /* Format a validation error message involving dates.
  56. @param source (string) the error message
  57. @param params (Date[]) the dates
  58. @return (string) the formatted message */
  59. errorFormat: function(source, params) {
  60. var format = ($.datepick.curInst ?
  61. $.datepick.curInst.options.dateFormat :
  62. $.datepick._defaults.dateFormat);
  63. $.each(params, function(index, value) {
  64. source = source.replace(new RegExp('\\{' + index + '\\}', 'g'),
  65. $.datepick.formatDate(format, value) || 'nothing');
  66. });
  67. return source;
  68. }
  69. });
  70. var lastElement = null;
  71. /* Validate date field. */
  72. $.validator.addMethod('dpDate', function(value, element) {
  73. lastElement = element;
  74. return this.optional(element) || validateEach(value, element);
  75. },
  76. function(params) {
  77. var inst = $.data(lastElement, $.datepick.propertyName);
  78. var minDate = inst.get('minDate');
  79. var maxDate = inst.get('maxDate');
  80. var messages = $.datepick._defaults;
  81. return (minDate && maxDate ?
  82. $.datepick.errorFormat(messages.validateDateMinMax, [minDate, maxDate]) :
  83. (minDate ? $.datepick.errorFormat(messages.validateDateMin, [minDate]) :
  84. (maxDate ? $.datepick.errorFormat(messages.validateDateMax, [maxDate]) :
  85. messages.validateDate)));
  86. });
  87. /* Apply a validation test to each date provided.
  88. @param value (string) the current field value
  89. @param element (element) the field control
  90. @return (boolean) true if OK, false if failed validation */
  91. function validateEach(value, element) {
  92. var inst = $.data(element, $.datepick.propertyName);
  93. var dates = (inst.options.multiSelect ? value.split(inst.options.multiSeparator) :
  94. (inst.options.rangeSelect ? value.split(inst.options.rangeSeparator) : [value]));
  95. var ok = (inst.options.multiSelect && dates.length <= inst.options.multiSelect) ||
  96. (!inst.options.multiSelect && inst.options.rangeSelect && dates.length == 2) ||
  97. (!inst.options.multiSelect && !inst.options.rangeSelect && dates.length == 1);
  98. if (ok) {
  99. try {
  100. var dateFormat = inst.options.dateFormat;
  101. var minDate = inst.get('minDate');
  102. var maxDate = inst.get('maxDate');
  103. var dp = $(element);
  104. $.each(dates, function(i, v) {
  105. dates[i] = $.datepick.parseDate(dateFormat, v);
  106. ok = ok && (!dates[i] || (dp.datepick('isSelectable', dates[i]) &&
  107. (!minDate || dates[i].getTime() >= minDate.getTime()) &&
  108. (!maxDate || dates[i].getTime() <= maxDate.getTime())));
  109. });
  110. }
  111. catch (e) {
  112. ok = false;
  113. }
  114. }
  115. if (ok && inst.options.rangeSelect) {
  116. ok = (dates[0].getTime() <= dates[1].getTime());
  117. }
  118. return ok;
  119. }
  120. /* And allow as a class rule. */
  121. $.validator.addClassRules('dpDate', {dpDate: true});
  122. var comparisons = {equal: 'eq', same: 'eq', notEqual: 'ne', notSame: 'ne',
  123. lessThan: 'lt', before: 'lt', greaterThan: 'gt', after: 'gt',
  124. notLessThan: 'ge', notBefore: 'ge', notGreaterThan: 'le', notAfter: 'le'};
  125. /* Cross-validate date fields.
  126. params should be an array with [0] comparison type eq/ne/lt/gt/le/ge or synonyms,
  127. [1] 'today' or date string or Date or other field selector/element/jQuery OR
  128. an object with one attribute with name eq/ne/lt/gt/le/ge or synonyms
  129. and value 'today' or date string or Date or other field selector/element/jQuery OR
  130. a string with eq/ne/lt/gt/le/ge or synonyms followed by 'today' or date string or jQuery selector */
  131. $.validator.addMethod('dpCompareDate', function(value, element, params) {
  132. if (this.optional(element)) {
  133. return true;
  134. }
  135. params = normaliseParams(params);
  136. var thisDate = $(element).datepick('getDate');
  137. var thatDate = extractOtherDate(element, params[1]);
  138. if (thisDate.length == 0 || thatDate.length == 0) {
  139. return true;
  140. }
  141. lastElement = element;
  142. var finalResult = true;
  143. for (var i = 0; i < thisDate.length; i++) {
  144. switch (comparisons[params[0]] || params[0]) {
  145. case 'eq': finalResult = (thisDate[i].getTime() == thatDate[0].getTime()); break;
  146. case 'ne': finalResult = (thisDate[i].getTime() != thatDate[0].getTime()); break;
  147. case 'lt': finalResult = (thisDate[i].getTime() < thatDate[0].getTime()); break;
  148. case 'gt': finalResult = (thisDate[i].getTime() > thatDate[0].getTime()); break;
  149. case 'le': finalResult = (thisDate[i].getTime() <= thatDate[0].getTime()); break;
  150. case 'ge': finalResult = (thisDate[i].getTime() >= thatDate[0].getTime()); break;
  151. default: finalResult = true;
  152. }
  153. if (!finalResult) {
  154. break;
  155. }
  156. }
  157. return finalResult;
  158. },
  159. function(params) {
  160. var messages = $.datepick._defaults;
  161. var inst = $.data(lastElement, $.datepick.propertyName);
  162. params = normaliseParams(params);
  163. var thatDate = extractOtherDate(lastElement, params[1], true);
  164. thatDate = (params[1] == 'today' ? messages.validateDateToday : (thatDate.length ?
  165. $.datepick.formatDate(inst.options.dateFormat, thatDate[0], inst.getConfig()) :
  166. messages.validateDateOther));
  167. return messages.validateDateCompare.replace(/\{0\}/,
  168. messages['validateDate' + (comparisons[params[0]] || params[0]).toUpperCase()]).
  169. replace(/\{1\}/, thatDate);
  170. });
  171. /* Normalise the comparison parameters to an array.
  172. @param params (array or object or string) the original parameters
  173. @return (array) the normalised parameters */
  174. function normaliseParams(params) {
  175. if (typeof params == 'string') {
  176. params = params.split(' ');
  177. }
  178. else if (!$.isArray(params)) {
  179. var opts = [];
  180. for (var name in params) {
  181. opts[0] = name;
  182. opts[1] = params[name];
  183. }
  184. params = opts;
  185. }
  186. return params;
  187. }
  188. /* Determine the comparison date.
  189. @param element (element) the current datepicker element
  190. @param source (string or Date or jQuery or element) the source of the other date
  191. @param noOther (boolean) true to not get the date from another field
  192. @return (Date[1]) the date for comparison */
  193. function extractOtherDate(element, source, noOther) {
  194. if (source.constructor == Date) {
  195. return [source];
  196. }
  197. var inst = $.data(element, $.datepick.propertyName);
  198. var thatDate = null;
  199. try {
  200. if (typeof source == 'string' && source != 'today') {
  201. thatDate = $.datepick.parseDate(inst.options.dateFormat, source, inst.getConfig());
  202. }
  203. }
  204. catch (e) {
  205. // Ignore
  206. }
  207. thatDate = (thatDate ? [thatDate] : (source == 'today' ?
  208. [$.datepick.today()] : (noOther ? [] : $(source).datepick('getDate'))));
  209. return thatDate;
  210. }
  211. }
  212. })(jQuery);