bootstrapValidator.js 96 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385
  1. /**
  2. * BootstrapValidator (http://bootstrapvalidator.com)
  3. *
  4. * A jQuery plugin to validate form fields. Use with Bootstrap 3
  5. *
  6. * @version v0.4.3-dev
  7. * @author https://twitter.com/nghuuphuoc
  8. * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc
  9. * @license MIT
  10. */
  11. (function($) {
  12. var BootstrapValidator = function(form, options) {
  13. this.$form = $(form);
  14. this.options = $.extend({}, BootstrapValidator.DEFAULT_OPTIONS, options);
  15. this.$invalidField = null; // First invalid field
  16. this.$submitButton = null; // The submit button which is clicked to submit form
  17. // Validating status
  18. this.STATUS_NOT_VALIDATED = 'NOT_VALIDATED';
  19. this.STATUS_VALIDATING = 'VALIDATING';
  20. this.STATUS_INVALID = 'INVALID';
  21. this.STATUS_VALID = 'VALID';
  22. // Determine the event that is fired when user change the field value
  23. // Most modern browsers supports input event except IE 7, 8.
  24. // IE 9 supports input event but the event is still not fired if I press the backspace key.
  25. // In that case I will use the keydown event
  26. var el = document.createElement('div');
  27. this._changeEvent = ('oninput' in el) ? 'input' : 'keydown';
  28. // The flag to indicate that the form is ready to submit when a remote/callback validator returns
  29. this._submitIfValid = null;
  30. this._init();
  31. };
  32. // The default options
  33. BootstrapValidator.DEFAULT_OPTIONS = {
  34. // The form CSS class
  35. elementClass: 'bootstrap-validator-form',
  36. // Default invalid message
  37. message: 'This value is not valid',
  38. // Indicate fields which won't be validated
  39. // By default, the plugin will not validate the following kind of fields:
  40. // - disabled
  41. // - hidden
  42. // - invisible
  43. //
  44. // The setting consists of jQuery filters. Accept 3 formats:
  45. // - A string. Use a comma to separate filter
  46. // - An array. Each element is a filter
  47. // - An array. Each element can be a callback function
  48. // function($field, validator) {
  49. // $field is jQuery object representing the field element
  50. // validator is the BootstrapValidator instance
  51. // return true or false;
  52. // }
  53. //
  54. // The 3 following settings are equivalent:
  55. //
  56. // 1) ':disabled, :hidden, :not(:visible)'
  57. // 2) [':disabled', ':hidden', ':not(:visible)']
  58. // 3) [':disabled', ':hidden', function($field) {
  59. // return !$field.is(':visible');
  60. // }]
  61. excluded: [':disabled', ':hidden', ':not(:visible)'],
  62. // Shows ok/error/loading icons based on the field validity.
  63. // This feature requires Bootstrap v3.1.0 or later (http://getbootstrap.com/css/#forms-control-validation).
  64. // Since Bootstrap doesn't provide any methods to know its version, this option cannot be on/off automatically.
  65. // In other word, to use this feature you have to upgrade your Bootstrap to v3.1.0 or later.
  66. //
  67. // Examples:
  68. // - Use Glyphicons icons:
  69. // feedbackIcons: {
  70. // valid: 'glyphicon glyphicon-ok',
  71. // invalid: 'glyphicon glyphicon-remove',
  72. // validating: 'glyphicon glyphicon-refresh'
  73. // }
  74. // - Use FontAwesome icons:
  75. // feedbackIcons: {
  76. // valid: 'fa fa-check',
  77. // invalid: 'fa fa-times',
  78. // validating: 'fa fa-refresh'
  79. // }
  80. feedbackIcons: {
  81. valid: null,
  82. invalid: null,
  83. validating: null
  84. },
  85. // The submit buttons selector
  86. // These buttons will be disabled to prevent the valid form from multiple submissions
  87. submitButtons: 'button[type="submit"]',
  88. // The custom submit handler
  89. // It will prevent the form from the default submission
  90. //
  91. // submitHandler: function(validator, form) {
  92. // - validator is the BootstrapValidator instance
  93. // - form is the jQuery object present the current form
  94. // }
  95. submitHandler: null,
  96. // Live validating option
  97. // Can be one of 3 values:
  98. // - enabled: The plugin validates fields as soon as they are changed
  99. // - disabled: Disable the live validating. The error messages are only shown after the form is submitted
  100. // - submitted: The live validating is enabled after the form is submitted
  101. live: 'enabled',
  102. // Map the field name with validator rules
  103. fields: null
  104. };
  105. BootstrapValidator.prototype = {
  106. constructor: BootstrapValidator,
  107. /**
  108. * Init form
  109. */
  110. _init: function() {
  111. var that = this,
  112. options = {
  113. excluded: this.$form.attr('data-bv-excluded'),
  114. trigger: this.$form.attr('data-bv-trigger'),
  115. message: this.$form.attr('data-bv-message'),
  116. submitButtons: this.$form.attr('data-bv-submitbuttons'),
  117. live: this.$form.attr('data-bv-live'),
  118. fields: {},
  119. feedbackIcons: {
  120. valid: this.$form.attr('data-bv-feedbackicons-valid'),
  121. invalid: this.$form.attr('data-bv-feedbackicons-invalid'),
  122. validating: this.$form.attr('data-bv-feedbackicons-validating')
  123. }
  124. },
  125. validator,
  126. v, // Validator name
  127. enabled,
  128. optionName,
  129. optionValue,
  130. html5AttrName,
  131. html5Attrs;
  132. this.$form
  133. // Disable client side validation in HTML 5
  134. .attr('novalidate', 'novalidate')
  135. .addClass(this.options.elementClass)
  136. // Disable the default submission first
  137. .on('submit.bv', function(e) {
  138. e.preventDefault();
  139. that.validate();
  140. })
  141. .on('click', this.options.submitButtons, function() {
  142. that.$submitButton = $(this);
  143. // The user just click the submit button
  144. that._submitIfValid = true;
  145. })
  146. // Find all fields which have either "name" or "data-bv-field" attribute
  147. .find('[name], [data-bv-field]').each(function() {
  148. var $field = $(this);
  149. // Don't initialize hidden input
  150. if ('hidden' == $field.attr('type')) {
  151. return;
  152. }
  153. var field = $field.attr('name') || $field.attr('data-bv-field');
  154. $field.attr('data-bv-field', field);
  155. options.fields[field] = $.extend({}, {
  156. trigger: $field.attr('data-bv-trigger'),
  157. message: $field.attr('data-bv-message'),
  158. container: $field.attr('data-bv-container'),
  159. selector: $field.attr('data-bv-selector'),
  160. validators: {}
  161. }, options.fields[field]);
  162. for (v in $.fn.bootstrapValidator.validators) {
  163. validator = $.fn.bootstrapValidator.validators[v];
  164. enabled = $field.attr('data-bv-' + v.toLowerCase()) + '';
  165. html5Attrs = ('function' == typeof validator.enableByHtml5) ? validator.enableByHtml5($(this)) : null;
  166. if ((html5Attrs && enabled != 'false')
  167. || (html5Attrs !== true && ('' == enabled || 'true' == enabled)))
  168. {
  169. // Try to parse the options via attributes
  170. validator.html5Attributes = validator.html5Attributes || { message: 'message' };
  171. options.fields[field]['validators'][v] = $.extend({}, html5Attrs == true ? {} : html5Attrs, options.fields[field]['validators'][v]);
  172. for (html5AttrName in validator.html5Attributes) {
  173. optionName = validator.html5Attributes[html5AttrName];
  174. optionValue = $field.attr('data-bv-' + v.toLowerCase() + '-' + html5AttrName);
  175. if (optionValue) {
  176. if ('true' == optionValue) {
  177. optionValue = true;
  178. } else if ('false' == optionValue) {
  179. optionValue = false;
  180. }
  181. options.fields[field]['validators'][v][optionName] = optionValue;
  182. }
  183. }
  184. }
  185. }
  186. });
  187. this.options = $.extend(true, this.options, options);
  188. if ('string' == typeof this.options.excluded) {
  189. this.options.excluded = $.map(this.options.excluded.split(','), function(item) {
  190. // Trim the spaces
  191. return item.trim();
  192. });
  193. }
  194. for (var field in this.options.fields) {
  195. this._initField(field);
  196. }
  197. this.setLiveMode(this.options.live);
  198. },
  199. /**
  200. * Init field
  201. *
  202. * @param {String} field The field name
  203. */
  204. _initField: function(field) {
  205. if (this.options.fields[field] == null || this.options.fields[field].validators == null) {
  206. return;
  207. }
  208. var fields = this.getFieldElements(field);
  209. // We don't need to validate non-existing fields
  210. if (fields == null) {
  211. delete this.options.fields[field];
  212. return;
  213. }
  214. for (var validatorName in this.options.fields[field].validators) {
  215. if (!$.fn.bootstrapValidator.validators[validatorName]) {
  216. delete this.options.fields[field].validators[validatorName];
  217. }
  218. }
  219. var that = this,
  220. type = fields.attr('type'),
  221. event = ('radio' == type || 'checkbox' == type || 'file' == type || 'SELECT' == fields[0].tagName) ? 'change' : that._changeEvent,
  222. total = fields.length,
  223. updateAll = (total == 1) || ('radio' == type) || ('checkbox' == type);
  224. for (var i = 0; i < total; i++) {
  225. var $field = $(fields[i]),
  226. $parent = $field.parents('.form-group'),
  227. // Allow user to indicate where the error messages are shown
  228. $message = this.options.fields[field].container ? $parent.find(this.options.fields[field].container) : this._getMessageContainer($field);
  229. // Set the attribute to indicate the fields which are defined by selector
  230. if (!$field.attr('data-bv-field')) {
  231. $field.attr('data-bv-field', field);
  232. }
  233. // Whenever the user change the field value, mark it as not validated yet
  234. $field.on(event + '.update.bv', function() {
  235. // Reset the flag
  236. that._submitIfValid = false;
  237. updateAll ? that.updateStatus(field, that.STATUS_NOT_VALIDATED, null)
  238. : that.updateElementStatus($(this), that.STATUS_NOT_VALIDATED, null);
  239. });
  240. // Create help block elements for showing the error messages
  241. $field.data('bv.messages', $message);
  242. for (validatorName in this.options.fields[field].validators) {
  243. $field.data('bv.result.' + validatorName, this.STATUS_NOT_VALIDATED);
  244. if (!updateAll || i == total - 1) {
  245. $('<small/>')
  246. .css('display', 'none')
  247. .attr('data-bv-validator', validatorName)
  248. .html(this.options.fields[field].validators[validatorName].message || this.options.fields[field].message || this.options.message)
  249. .addClass('help-block')
  250. .appendTo($message);
  251. }
  252. }
  253. // Prepare the feedback icons
  254. // Available from Bootstrap 3.1 (http://getbootstrap.com/css/#forms-control-validation)
  255. if (this.options.feedbackIcons
  256. && this.options.feedbackIcons.validating && this.options.feedbackIcons.invalid && this.options.feedbackIcons.valid
  257. && (!updateAll || i == total - 1))
  258. {
  259. $parent.addClass('has-feedback');
  260. var $icon = $('<i/>').css('display', 'none').addClass('form-control-feedback').attr('data-bv-field', field).insertAfter($field);
  261. // The feedback icon does not render correctly if there is no label
  262. // https://github.com/twbs/bootstrap/issues/12873
  263. if ($parent.find('label').length == 0) {
  264. $icon.css('top', 0);
  265. }
  266. }
  267. }
  268. if (this.options.fields[field]['enabled'] == null) {
  269. this.options.fields[field]['enabled'] = true;
  270. }
  271. },
  272. /**
  273. * Get the element to place the error messages
  274. *
  275. * @param {jQuery} $field The field element
  276. * @returns {jQuery}
  277. */
  278. _getMessageContainer: function($field) {
  279. var $parent = $field.parent();
  280. if ($parent.hasClass('form-group')) {
  281. return $parent;
  282. }
  283. var cssClasses = $parent.attr('class');
  284. if (!cssClasses) {
  285. return this._getMessageContainer($parent);
  286. }
  287. cssClasses = cssClasses.split(' ');
  288. var n = cssClasses.length;
  289. for (var i = 0; i < n; i++) {
  290. if (/^col-(xs|sm|md|lg)-\d+$/.test(cssClasses[i]) || /^col-(xs|sm|md|lg)-offset-\d+$/.test(cssClasses[i])) {
  291. return $parent;
  292. }
  293. }
  294. return this._getMessageContainer($parent);
  295. },
  296. /**
  297. * Called when all validations are completed
  298. */
  299. _submit: function() {
  300. if (!this.isValid()) {
  301. if ('submitted' == this.options.live) {
  302. this.setLiveMode('enabled');
  303. }
  304. // Focus to the first invalid field
  305. if (this.$invalidField) {
  306. this.$invalidField.focus();
  307. }
  308. return;
  309. }
  310. // Call the custom submission if enabled
  311. if (this.options.submitHandler && 'function' == typeof this.options.submitHandler) {
  312. // If you want to submit the form inside your submit handler, please call defaultSubmit() method
  313. this.options.submitHandler.call(this, this, this.$form, this.$submitButton);
  314. } else {
  315. this.disableSubmitButtons(true).defaultSubmit();
  316. }
  317. },
  318. /**
  319. * Check if the field is excluded.
  320. * Returning true means that the field will not be validated
  321. *
  322. * @param {jQuery} $field The field element
  323. * @return {Boolean}
  324. */
  325. _isExcluded: function($field) {
  326. if (this.options.excluded) {
  327. for (var i in this.options.excluded) {
  328. if (('string' == typeof this.options.excluded[i] && $field.is(this.options.excluded[i]))
  329. || ('function' == typeof this.options.excluded[i] && this.options.excluded[i].call(this, $field, this) == true))
  330. {
  331. return true;
  332. }
  333. }
  334. }
  335. return false;
  336. },
  337. // --- Public methods ---
  338. /**
  339. * Retrieve the field elements by given name
  340. *
  341. * @param {String} field The field name
  342. * @returns {null|jQuery[]}
  343. */
  344. getFieldElements: function(field) {
  345. var fields = this.options.fields[field].selector ? $(this.options.fields[field].selector) : this.$form.find('[name="' + field + '"]');
  346. return (fields.length == 0) ? null : fields;
  347. },
  348. /**
  349. * Set live validating mode
  350. *
  351. * @param {String} mode Live validating mode. Can be 'enabled', 'disabled', 'submitted'
  352. * @returns {BootstrapValidator}
  353. */
  354. setLiveMode: function(mode) {
  355. this.options.live = mode;
  356. if ('submitted' == mode) {
  357. return this;
  358. }
  359. var that = this;
  360. for (var field in this.options.fields) {
  361. (function(f) {
  362. var fields = that.getFieldElements(f);
  363. if (fields) {
  364. var type = fields.attr('type'),
  365. total = fields.length,
  366. updateAll = (total == 1) || ('radio' == type) || ('checkbox' == type),
  367. trigger = that.options.fields[field].trigger
  368. || that.options.trigger
  369. || (('radio' == type || 'checkbox' == type || 'file' == type || 'SELECT' == fields[0].tagName) ? 'change' : that._changeEvent),
  370. events = $.map(trigger.split(' '), function(item) {
  371. return item + '.live.bv';
  372. }).join(' ');
  373. for (var i = 0; i < total; i++) {
  374. ('enabled' == mode)
  375. ? $(fields[i]).on(events, function() {
  376. updateAll ? that.validateField(f) : that.validateFieldElement($(this), false);
  377. })
  378. : $(fields[i]).off(events);
  379. }
  380. }
  381. })(field);
  382. }
  383. return this;
  384. },
  385. /**
  386. * Disable/enable submit buttons
  387. *
  388. * @param {Boolean} disabled Can be true or false
  389. * @returns {BootstrapValidator}
  390. */
  391. disableSubmitButtons: function(disabled) {
  392. if (!disabled) {
  393. this.$form.find(this.options.submitButtons).removeAttr('disabled');
  394. } else if (this.options.live != 'disabled') {
  395. // Don't disable if the live validating mode is disabled
  396. this.$form.find(this.options.submitButtons).attr('disabled', 'disabled');
  397. }
  398. return this;
  399. },
  400. /**
  401. * Validate the form
  402. *
  403. * @return {BootstrapValidator}
  404. */
  405. validate: function() {
  406. if (!this.options.fields) {
  407. return this;
  408. }
  409. this.disableSubmitButtons(true);
  410. for (var field in this.options.fields) {
  411. this.validateField(field);
  412. }
  413. // Check if whether the submit button is clicked
  414. if (this.$submitButton) {
  415. this._submit();
  416. }
  417. return this;
  418. },
  419. /**
  420. * Validate given field
  421. *
  422. * @param {String} field The field name
  423. * @returns {BootstrapValidator}
  424. */
  425. validateField: function(field) {
  426. var fields = this.getFieldElements(field),
  427. type = fields.attr('type'),
  428. n = (('radio' == type) || ('checkbox' == type)) ? 1 : fields.length;
  429. for (var i = 0; i < n; i++) {
  430. this.validateFieldElement($(fields[i]), (n == 1));
  431. }
  432. return this;
  433. },
  434. /**
  435. * Validate field element
  436. *
  437. * @param {jQuery} $field The field element
  438. * @param {Boolean} updateAll If true, update status of all elements which have the same name
  439. * @returns {BootstrapValidator}
  440. */
  441. validateFieldElement: function($field, updateAll) {
  442. var that = this,
  443. field = $field.attr('data-bv-field'),
  444. validators = this.options.fields[field].validators,
  445. validatorName,
  446. validateResult;
  447. if (!this.options.fields[field]['enabled'] || this._isExcluded($field)) {
  448. return this;
  449. }
  450. for (validatorName in validators) {
  451. if ($field.data('bv.dfs.' + validatorName)) {
  452. $field.data('bv.dfs.' + validatorName).reject();
  453. }
  454. // Don't validate field if it is already done
  455. var result = $field.data('bv.result.' + validatorName);
  456. if (result == this.STATUS_VALID || result == this.STATUS_INVALID) {
  457. continue;
  458. }
  459. $field.data('bv.result.' + validatorName, this.STATUS_VALIDATING);
  460. validateResult = $.fn.bootstrapValidator.validators[validatorName].validate(this, $field, validators[validatorName]);
  461. if ('object' == typeof validateResult) {
  462. updateAll ? this.updateStatus(field, this.STATUS_VALIDATING, validatorName)
  463. : this.updateElementStatus($field, this.STATUS_VALIDATING, validatorName);
  464. $field.data('bv.dfs.' + validatorName, validateResult);
  465. validateResult.done(function($f, v, isValid) {
  466. // v is validator name
  467. $f.removeData('bv.dfs.' + v);
  468. updateAll ? that.updateStatus($f.attr('data-bv-field'), isValid ? that.STATUS_VALID : that.STATUS_INVALID, v)
  469. : that.updateElementStatus($f, isValid ? that.STATUS_VALID : that.STATUS_INVALID, v);
  470. if (isValid && that._submitIfValid == true) {
  471. // If a remote validator returns true and the form is ready to submit, then do it
  472. that._submit();
  473. }
  474. });
  475. } else if ('boolean' == typeof validateResult) {
  476. updateAll ? this.updateStatus(field, validateResult ? this.STATUS_VALID : this.STATUS_INVALID, validatorName)
  477. : this.updateElementStatus($field, validateResult ? this.STATUS_VALID : this.STATUS_INVALID, validatorName);
  478. }
  479. }
  480. return this;
  481. },
  482. /**
  483. * Update all validating results of elements which have the same field name
  484. *
  485. * @param {String} field The field name
  486. * @param {String} status The status. Can be 'NOT_VALIDATED', 'VALIDATING', 'INVALID' or 'VALID'
  487. * @param {String} [validatorName] The validator name. If null, the method updates validity result for all validators
  488. * @return {BootstrapValidator}
  489. */
  490. updateStatus: function(field, status, validatorName) {
  491. var fields = this.getFieldElements(field),
  492. type = fields.attr('type'),
  493. n = (('radio' == type) || ('checkbox' == type)) ? 1 : fields.length;
  494. for (var i = 0; i < n; i++) {
  495. this.updateElementStatus($(fields[i]), status, validatorName);
  496. }
  497. return this;
  498. },
  499. /**
  500. * Update validating result of given element
  501. *
  502. * @param {jQuery} $field The field element
  503. * @param {String} status The status. Can be 'NOT_VALIDATED', 'VALIDATING', 'INVALID' or 'VALID'
  504. * @param {String} [validatorName] The validator name. If null, the method updates validity result for all validators
  505. * @return {BootstrapValidator}
  506. */
  507. updateElementStatus: function($field, status, validatorName) {
  508. var that = this,
  509. field = $field.attr('data-bv-field'),
  510. $parent = $field.parents('.form-group'),
  511. $message = $field.data('bv.messages'),
  512. $rowErrors = $parent.find('.help-block[data-bv-validator]'),
  513. $errors = $message.find('.help-block[data-bv-validator]'),
  514. $icon = $parent.find('.form-control-feedback[data-bv-field="' + field + '"]');
  515. // Update status
  516. if (validatorName) {
  517. $field.data('bv.result.' + validatorName, status);
  518. } else {
  519. for (var v in this.options.fields[field].validators) {
  520. $field.data('bv.result.' + v, status);
  521. }
  522. }
  523. // Show/hide error elements and feedback icons
  524. switch (status) {
  525. case this.STATUS_VALIDATING:
  526. this.disableSubmitButtons(true);
  527. $parent.removeClass('has-success').removeClass('has-error');
  528. // TODO: Show validating message
  529. validatorName ? $errors.filter('.help-block[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide();
  530. if ($icon) {
  531. $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).addClass(this.options.feedbackIcons.validating).show();
  532. }
  533. break;
  534. case this.STATUS_INVALID:
  535. this.disableSubmitButtons(true);
  536. $parent.removeClass('has-success').addClass('has-error');
  537. validatorName ? $errors.filter('[data-bv-validator="' + validatorName + '"]').show() : $errors.show();
  538. if ($icon) {
  539. $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.invalid).show();
  540. }
  541. break;
  542. case this.STATUS_VALID:
  543. validatorName ? $errors.filter('[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide();
  544. // If the field is valid (passes all validators)
  545. var validField = ($errors.filter(function() {
  546. var display = $(this).css('display'), v = $(this).attr('data-bv-validator');
  547. return ('block' == display) || ($field.data('bv.result.' + v) != that.STATUS_VALID);
  548. }).length == 0);
  549. this.disableSubmitButtons(validField ? false : true);
  550. if ($icon) {
  551. $icon
  552. .removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).removeClass(this.options.feedbackIcons.valid)
  553. .addClass(validField ? this.options.feedbackIcons.valid : this.options.feedbackIcons.invalid)
  554. .show();
  555. }
  556. // Check if all fields in the same row are valid
  557. var validRow = ($rowErrors.filter(function() {
  558. var display = $(this).css('display'), v = $(this).attr('data-bv-validator');
  559. return ('block' == display) || ($field.data('bv.result.' + v) != that.STATUS_VALID);
  560. }).length == 0);
  561. $parent.removeClass('has-error has-success').addClass(validRow ? 'has-success' : 'has-error');
  562. break;
  563. case this.STATUS_NOT_VALIDATED:
  564. default:
  565. this.disableSubmitButtons(false);
  566. $parent.removeClass('has-success').removeClass('has-error');
  567. validatorName ? $errors.filter('.help-block[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide();
  568. if ($icon) {
  569. $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).hide();
  570. }
  571. break;
  572. }
  573. return this;
  574. },
  575. /**
  576. * Check the form validity
  577. *
  578. * @returns {Boolean}
  579. */
  580. isValid: function() {
  581. var fields, field, $field,
  582. type, status, validatorName,
  583. n, i;
  584. for (field in this.options.fields) {
  585. if (this.options.fields[field] == null || !this.options.fields[field]['enabled']) {
  586. continue;
  587. }
  588. fields = this.getFieldElements(field);
  589. type = fields.attr('type');
  590. n = (('radio' == type) || ('checkbox' == type)) ? 1 : fields.length;
  591. for (i = 0; i < n; i++) {
  592. $field = $(fields[i]);
  593. if (this._isExcluded($field)) {
  594. continue;
  595. }
  596. for (validatorName in this.options.fields[field].validators) {
  597. status = $field.data('bv.result.' + validatorName);
  598. if (status == this.STATUS_NOT_VALIDATED || status == this.STATUS_VALIDATING) {
  599. return false;
  600. }
  601. if (status == this.STATUS_INVALID) {
  602. this.$invalidField = $field;
  603. return false;
  604. }
  605. }
  606. }
  607. }
  608. return true;
  609. },
  610. /**
  611. * Submit the form using default submission.
  612. * It also does not perform any validations when submitting the form
  613. *
  614. * It might be used when you want to submit the form right inside the submitHandler()
  615. */
  616. defaultSubmit: function() {
  617. this.$form.off('submit.bv').submit();
  618. },
  619. // Useful APIs which aren't used internally
  620. /**
  621. * Reset the form
  622. *
  623. * @param {Boolean} resetFormData Reset current form data
  624. * @return {BootstrapValidator}
  625. */
  626. resetForm: function(resetFormData) {
  627. var field, fields, total, type, validator;
  628. for (field in this.options.fields) {
  629. fields = this.getFieldElements(field);
  630. total = fields.length;
  631. for (var i = 0; i < total; i++) {
  632. for (validator in this.options.fields[field].validators) {
  633. $(fields[i]).removeData('bv.dfs.' + validator);
  634. }
  635. }
  636. // Mark field as not validated yet
  637. this.updateStatus(field, this.STATUS_NOT_VALIDATED, null);
  638. if (resetFormData) {
  639. type = fields.attr('type');
  640. ('radio' == type || 'checkbox' == type) ? fields.removeAttr('checked').removeAttr('selected') : fields.val('');
  641. }
  642. }
  643. this.$invalidField = null;
  644. this.$submitButton = null;
  645. // Enable submit buttons
  646. this.disableSubmitButtons(false);
  647. return this;
  648. },
  649. /**
  650. * Enable/Disable all validators to given field
  651. *
  652. * @param {String} field The field name
  653. * @param {Boolean} enabled Enable/Disable field validators
  654. * @return {BootstrapValidator}
  655. */
  656. enableFieldValidators: function(field, enabled) {
  657. this.options.fields[field]['enabled'] = enabled;
  658. this.updateStatus(field, this.STATUS_NOT_VALIDATED, null);
  659. return this;
  660. }
  661. };
  662. // Plugin definition
  663. $.fn.bootstrapValidator = function(options) {
  664. return this.each(function() {
  665. var $this = $(this), data = $this.data('bootstrapValidator');
  666. if (!data) {
  667. $this.data('bootstrapValidator', (data = new BootstrapValidator(this, options)));
  668. }
  669. if ('string' == typeof options) {
  670. data[options]();
  671. }
  672. });
  673. };
  674. // Available validators
  675. $.fn.bootstrapValidator.validators = {};
  676. $.fn.bootstrapValidator.Constructor = BootstrapValidator;
  677. }(window.jQuery));
  678. ;(function($) {
  679. $.fn.bootstrapValidator.validators.base64 = {
  680. /**
  681. * Return true if the input value is a base 64 encoded string.
  682. *
  683. * @param {BootstrapValidator} validator The validator plugin instance
  684. * @param {jQuery} $field Field element
  685. * @param {Object} options Can consist of the following keys:
  686. * - message: The invalid message
  687. * @returns {Boolean}
  688. */
  689. validate: function(validator, $field, options) {
  690. var value = $field.val();
  691. if (value == '') {
  692. return true;
  693. }
  694. return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/.test(value);
  695. }
  696. };
  697. }(window.jQuery));
  698. ;(function($) {
  699. $.fn.bootstrapValidator.validators.between = {
  700. html5Attributes: {
  701. message: 'message',
  702. min: 'min',
  703. max: 'max',
  704. inclusive: 'inclusive'
  705. },
  706. enableByHtml5: function($field) {
  707. if ('range' == $field.attr('type')) {
  708. return {
  709. min: $field.attr('min'),
  710. max: $field.attr('max')
  711. };
  712. }
  713. return false;
  714. },
  715. /**
  716. * Return true if the input value is between (strictly or not) two given numbers
  717. *
  718. * @param {BootstrapValidator} validator The validator plugin instance
  719. * @param {jQuery} $field Field element
  720. * @param {Object} options Can consist of the following keys:
  721. * - min
  722. * - max
  723. * - inclusive [optional]: Can be true or false. Default is true
  724. * - message: The invalid message
  725. * @returns {Boolean}
  726. */
  727. validate: function(validator, $field, options) {
  728. var value = $field.val();
  729. if (value == '') {
  730. return true;
  731. }
  732. value = parseFloat(value);
  733. return (options.inclusive === true)
  734. ? (value > options.min && value < options.max)
  735. : (value >= options.min && value <= options.max);
  736. }
  737. };
  738. }(window.jQuery));
  739. ;(function($) {
  740. $.fn.bootstrapValidator.validators.callback = {
  741. /**
  742. * Return result from the callback method
  743. *
  744. * @param {BootstrapValidator} validator The validator plugin instance
  745. * @param {jQuery} $field Field element
  746. * @param {Object} options Can consist of the following keys:
  747. * - callback: The callback method that passes 2 parameters:
  748. * callback: function(fieldValue, validator) {
  749. * // fieldValue is the value of field
  750. * // validator is instance of BootstrapValidator
  751. * }
  752. * - message: The invalid message
  753. * @returns {Boolean|Deferred}
  754. */
  755. validate: function(validator, $field, options) {
  756. var value = $field.val();
  757. if (options.callback && 'function' == typeof options.callback) {
  758. var dfd = new $.Deferred();
  759. dfd.resolve($field, 'callback', options.callback.call(this, value, validator));
  760. return dfd;
  761. }
  762. return true;
  763. }
  764. };
  765. }(window.jQuery));
  766. ;(function($) {
  767. $.fn.bootstrapValidator.validators.choice = {
  768. html5Attributes: {
  769. message: 'message',
  770. min: 'min',
  771. max: 'max'
  772. },
  773. /**
  774. * Check if the number of checked boxes are less or more than a given number
  775. *
  776. * @param {BootstrapValidator} validator The validator plugin instance
  777. * @param {jQuery} $field Field element
  778. * @param {Object} options Consists of following keys:
  779. * - min
  780. * - max
  781. * At least one of two keys is required
  782. * - message: The invalid message
  783. * @returns {Boolean}
  784. */
  785. validate: function(validator, $field, options) {
  786. var numChoices = validator
  787. .getFieldElements($field.attr('data-bv-field'))
  788. .filter(':checked')
  789. .length;
  790. if ((options.min && numChoices < options.min) || (options.max && numChoices > options.max)) {
  791. return false;
  792. }
  793. return true;
  794. }
  795. };
  796. }(window.jQuery));
  797. ;(function($) {
  798. $.fn.bootstrapValidator.validators.creditCard = {
  799. /**
  800. * Return true if the input value is valid credit card number
  801. * Based on https://gist.github.com/DiegoSalazar/4075533
  802. *
  803. * @param {BootstrapValidator} validator The validator plugin instance
  804. * @param {jQuery} $field Field element
  805. * @param {Object} options Can consist of the following key:
  806. * - message: The invalid message
  807. * @returns {Boolean}
  808. */
  809. validate: function(validator, $field, options) {
  810. var value = $field.val();
  811. if (value == '') {
  812. return true;
  813. }
  814. // Accept only digits, dashes or spaces
  815. if (/[^0-9-\s]+/.test(value)) {
  816. return false;
  817. }
  818. value = value.replace(/\D/g, '');
  819. // Validate the check sum
  820. // The Luhn Algorithm
  821. // http://en.wikipedia.org/wiki/Luhn
  822. var check = 0, digit = 0, even = false, length = value.length;
  823. for (var n = length - 1; n >= 0; n--) {
  824. digit = parseInt(value.charAt(n), 10);
  825. if (even) {
  826. if ((digit *= 2) > 9) {
  827. digit -= 9;
  828. }
  829. }
  830. check += digit;
  831. even = !even;
  832. }
  833. if ((check % 10) != 0) {
  834. return false;
  835. }
  836. // Validate the card number based on prefix (IIN ranges) and length
  837. var cards = {
  838. AMERICAN_EXPRESS: {
  839. length: [15],
  840. prefix: ['34', '37']
  841. },
  842. DINERS_CLUB: {
  843. length: [14],
  844. prefix: ['300', '301', '302', '303', '304', '305', '36']
  845. },
  846. DINERS_CLUB_US: {
  847. length: [16],
  848. prefix: ['54', '55']
  849. },
  850. DISCOVER: {
  851. length: [16],
  852. prefix: ['6011', '622126', '622127', '622128', '622129', '62213',
  853. '62214', '62215', '62216', '62217', '62218', '62219',
  854. '6222', '6223', '6224', '6225', '6226', '6227', '6228',
  855. '62290', '62291', '622920', '622921', '622922', '622923',
  856. '622924', '622925', '644', '645', '646', '647', '648',
  857. '649', '65']
  858. },
  859. JCB: {
  860. length: [16],
  861. prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358']
  862. },
  863. LASER: {
  864. length: [16, 17, 18, 19],
  865. prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358']
  866. },
  867. MAESTRO: {
  868. length: [12, 13, 14, 15, 16, 17, 18, 19],
  869. prefix: ['5018', '5020', '5038', '6304', '6759', '6761', '6762', '6763', '6764', '6765', '6766']
  870. },
  871. MASTERCARD: {
  872. length: [16],
  873. prefix: ['51', '52', '53', '54', '55']
  874. },
  875. SOLO: {
  876. length: [16, 18, 19],
  877. prefix: ['6334', '6767']
  878. },
  879. UNIONPAY: {
  880. length: [16, 17, 18, 19],
  881. prefix: ['622126', '622127', '622128', '622129', '62213', '62214',
  882. '62215', '62216', '62217', '62218', '62219', '6222', '6223',
  883. '6224', '6225', '6226', '6227', '6228', '62290', '62291',
  884. '622920', '622921', '622922', '622923', '622924', '622925']
  885. },
  886. VISA: {
  887. length: [16],
  888. prefix: ['4']
  889. }
  890. };
  891. var type, i;
  892. for (type in cards) {
  893. for (i in cards[type]['prefix']) {
  894. if (value.substr(0, cards[type]['prefix'][i].length) == cards[type]['prefix'][i] // Check the prefix
  895. && cards[type]['length'].indexOf(value.length) != -1) // and length
  896. {
  897. return true;
  898. }
  899. }
  900. }
  901. return false;
  902. }
  903. };
  904. }(window.jQuery));
  905. ;(function($) {
  906. $.fn.bootstrapValidator.validators.cvv = {
  907. html5Attributes: {
  908. message: 'message',
  909. ccfield: 'creditCardField'
  910. },
  911. /**
  912. * Return true if the input value is a valid CVV number.
  913. *
  914. * @param {BootstrapValidator} validator The validator plugin instance
  915. * @param {jQuery} $field Field element
  916. * @param {Object} options Can consist of the following keys:
  917. * - creditCardField: The credit card number field. It can be null
  918. * - message: The invalid message
  919. * @returns {Boolean}
  920. */
  921. validate: function(validator, $field, options) {
  922. var value = $field.val();
  923. if (value == '') {
  924. return true;
  925. }
  926. if (!/^[0-9]{3,4}$/.test(value)) {
  927. return false;
  928. }
  929. if (!options.creditCardField) {
  930. return true;
  931. }
  932. // Get the credit card number
  933. var creditCard = validator.getFieldElements(options.creditCardField).val();
  934. if (creditCard == '') {
  935. return true;
  936. }
  937. // Supported credit card types
  938. var cards = {
  939. AMERICAN_EXPRESS: {
  940. length: [15],
  941. prefix: ['34', '37']
  942. },
  943. DINERS_CLUB: {
  944. length: [14],
  945. prefix: ['300', '301', '302', '303', '304', '305', '36']
  946. },
  947. DINERS_CLUB_US: {
  948. length: [16],
  949. prefix: ['54', '55']
  950. },
  951. DISCOVER: {
  952. length: [16],
  953. prefix: ['6011', '622126', '622127', '622128', '622129', '62213',
  954. '62214', '62215', '62216', '62217', '62218', '62219',
  955. '6222', '6223', '6224', '6225', '6226', '6227', '6228',
  956. '62290', '62291', '622920', '622921', '622922', '622923',
  957. '622924', '622925', '644', '645', '646', '647', '648',
  958. '649', '65']
  959. },
  960. JCB: {
  961. length: [16],
  962. prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358']
  963. },
  964. LASER: {
  965. length: [16, 17, 18, 19],
  966. prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358']
  967. },
  968. MAESTRO: {
  969. length: [12, 13, 14, 15, 16, 17, 18, 19],
  970. prefix: ['5018', '5020', '5038', '6304', '6759', '6761', '6762', '6763', '6764', '6765', '6766']
  971. },
  972. MASTERCARD: {
  973. length: [16],
  974. prefix: ['51', '52', '53', '54', '55']
  975. },
  976. SOLO: {
  977. length: [16, 18, 19],
  978. prefix: ['6334', '6767']
  979. },
  980. UNIONPAY: {
  981. length: [16, 17, 18, 19],
  982. prefix: ['622126', '622127', '622128', '622129', '62213', '62214',
  983. '62215', '62216', '62217', '62218', '62219', '6222', '6223',
  984. '6224', '6225', '6226', '6227', '6228', '62290', '62291',
  985. '622920', '622921', '622922', '622923', '622924', '622925']
  986. },
  987. VISA: {
  988. length: [16],
  989. prefix: ['4']
  990. }
  991. };
  992. var type, i, creditCardType = null;
  993. for (type in cards) {
  994. for (i in cards[type]['prefix']) {
  995. if (creditCard.substr(0, cards[type]['prefix'][i].length) == cards[type]['prefix'][i] // Check the prefix
  996. && cards[type]['length'].indexOf(creditCard.length) != -1) // and length
  997. {
  998. creditCardType = type;
  999. break;
  1000. }
  1001. }
  1002. }
  1003. return (creditCardType == null)
  1004. ? false
  1005. : (('AMERICAN_EXPRESS' == creditCardType) ? (value.length == 4) : (value.length == 3));
  1006. }
  1007. };
  1008. }(window.jQuery));
  1009. ;(function($) {
  1010. $.fn.bootstrapValidator.validators.date = {
  1011. html5Attributes: {
  1012. message: 'message',
  1013. format: 'format'
  1014. },
  1015. /**
  1016. * Return true if the input value is valid date
  1017. *
  1018. * @param {BootstrapValidator} validator The validator plugin instance
  1019. * @param {jQuery} $field Field element
  1020. * @param {Object} options Can consist of the following keys:
  1021. * - format: The date format. Default is MM/DD/YYYY
  1022. * Support the following formats:
  1023. * YYYY/DD/MM
  1024. * YYYY/DD/MM h:m A
  1025. * YYYY/MM/DD
  1026. * YYYY/MM/DD h:m A
  1027. *
  1028. * YYYY-DD-MM
  1029. * YYYY-DD-MM h:m A
  1030. * YYYY-MM-DD
  1031. * YYYY-MM-DD h:m A
  1032. *
  1033. * MM/DD/YYYY
  1034. * MM/DD/YYYY h:m A
  1035. * DD/MM/YYYY
  1036. * DD/MM/YYYY h:m A
  1037. *
  1038. * MM-DD-YYYY
  1039. * MM-DD-YYYY h:m A
  1040. * DD-MM-YYYY
  1041. * DD-MM-YYYY h:m A
  1042. * - message: The invalid message
  1043. * @returns {Boolean}
  1044. */
  1045. validate: function(validator, $field, options) {
  1046. var value = $field.val();
  1047. if (value == '') {
  1048. return true;
  1049. }
  1050. // Determine the separator
  1051. options.format = options.format || 'MM/DD/YYYY';
  1052. var separator = (options.format.indexOf('/') != -1)
  1053. ? '/'
  1054. : ((options.format.indexOf('-') != -1) ? '-' : null);
  1055. if (separator == null) {
  1056. return false;
  1057. }
  1058. var month, day, year, minutes = null, hours = null, matches;
  1059. switch (true) {
  1060. case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i)) && options.format == 'YYYY/DD/MM'):
  1061. case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i)) && options.format == 'YYYY-DD-MM'):
  1062. year = matches[1]; day = matches[2]; month = matches[3];
  1063. break;
  1064. case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i)) && options.format == 'DD/MM/YYYY'):
  1065. case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i)) && options.format == 'DD-MM-YYYY'):
  1066. day = matches[1]; month = matches[2]; year = matches[3];
  1067. break;
  1068. case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i)) && options.format == 'YYYY/MM/DD'):
  1069. case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i)) && options.format == 'YYYY-MM-DD'):
  1070. year = matches[1]; month = matches[2]; day = matches[3];
  1071. break;
  1072. case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i)) && options.format == 'MM/DD/YYYY'):
  1073. case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i)) && options.format == 'MM-DD-YYYY'):
  1074. month = matches[1]; day = matches[2]; year = matches[3];
  1075. break;
  1076. case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY/DD/MM h:m A'):
  1077. case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY-DD-MM h:m A'):
  1078. year = matches[1]; day = matches[2]; month = matches[3]; hours = matches[4]; minutes = matches[5];
  1079. break;
  1080. case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'DD/MM/YYYY h:m A'):
  1081. case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'DD-MM-YYYY h:m A'):
  1082. day = matches[1]; month = matches[2]; year = matches[3]; hours = matches[4]; minutes = matches[5];
  1083. break;
  1084. case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY/MM/DD h:m A'):
  1085. case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY-MM-DD h:m A'):
  1086. year = matches[1]; month = matches[2]; day = matches[3]; hours = matches[4]; minutes = matches[5];
  1087. break;
  1088. case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'MM/DD/YYYY h:m A'):
  1089. case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'MM-DD-YYYY h:m A'):
  1090. month = matches[1]; day = matches[2]; year = matches[3]; hours = matches[4]; minutes = matches[5];
  1091. break;
  1092. default:
  1093. return false;
  1094. }
  1095. // Validate hours and minutes
  1096. if (hours && minutes) {
  1097. hours = parseInt(hours, 10);
  1098. minutes = parseInt(minutes, 10);
  1099. if (hours < 1 || hours > 12 || minutes < 0 || minutes > 59) {
  1100. return false;
  1101. }
  1102. }
  1103. // Validate day, month, and year
  1104. day = parseInt(day, 10);
  1105. month = parseInt(month, 10);
  1106. year = parseInt(year, 10);
  1107. if (year < 1000 || year > 9999 || month == 0 || month > 12) {
  1108. return false;
  1109. }
  1110. var numDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
  1111. // Update the number of days in Feb of leap year
  1112. if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
  1113. numDays[1] = 29;
  1114. }
  1115. // Check the day
  1116. return (day > 0 && day <= numDays[month - 1]);
  1117. }
  1118. };
  1119. }(window.jQuery));
  1120. ;(function($) {
  1121. $.fn.bootstrapValidator.validators.different = {
  1122. html5Attributes: {
  1123. message: 'message',
  1124. field: 'field'
  1125. },
  1126. /**
  1127. * Return true if the input value is different with given field's value
  1128. *
  1129. * @param {BootstrapValidator} validator The validator plugin instance
  1130. * @param {jQuery} $field Field element
  1131. * @param {Object} options Consists of the following key:
  1132. * - field: The name of field that will be used to compare with current one
  1133. * - message: The invalid message
  1134. * @returns {Boolean}
  1135. */
  1136. validate: function(validator, $field, options) {
  1137. var value = $field.val();
  1138. if (value == '') {
  1139. return true;
  1140. }
  1141. var compareWith = validator.getFieldElements(options.field);
  1142. if (compareWith == null) {
  1143. return true;
  1144. }
  1145. if (value != compareWith.val()) {
  1146. validator.updateStatus(options.field, validator.STATUS_VALID, 'different');
  1147. return true;
  1148. } else {
  1149. return false;
  1150. }
  1151. }
  1152. };
  1153. }(window.jQuery));
  1154. ;(function($) {
  1155. $.fn.bootstrapValidator.validators.digits = {
  1156. /**
  1157. * Return true if the input value contains digits only
  1158. *
  1159. * @param {BootstrapValidator} validator Validate plugin instance
  1160. * @param {jQuery} $field Field element
  1161. * @param {Object} options
  1162. * @returns {Boolean}
  1163. */
  1164. validate: function(validator, $field, options) {
  1165. var value = $field.val();
  1166. if (value == '') {
  1167. return true;
  1168. }
  1169. return /^\d+$/.test(value);
  1170. }
  1171. }
  1172. }(window.jQuery));
  1173. ;(function($) {
  1174. $.fn.bootstrapValidator.validators.emailAddress = {
  1175. enableByHtml5: function($field) {
  1176. return ('email' == $field.attr('type'));
  1177. },
  1178. /**
  1179. * Return true if and only if the input value is a valid email address
  1180. *
  1181. * @param {BootstrapValidator} validator Validate plugin instance
  1182. * @param {jQuery} $field Field element
  1183. * @param {Object} options
  1184. * @returns {Boolean}
  1185. */
  1186. validate: function(validator, $field, options) {
  1187. var value = $field.val();
  1188. if (value == '') {
  1189. return true;
  1190. }
  1191. // Email address regular expression
  1192. // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript
  1193. var emailRegExp = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
  1194. return emailRegExp.test(value);
  1195. }
  1196. }
  1197. }(window.jQuery));
  1198. ;(function($) {
  1199. $.fn.bootstrapValidator.validators.greaterThan = {
  1200. html5Attributes: {
  1201. message: 'message',
  1202. value: 'value',
  1203. inclusive: 'inclusive'
  1204. },
  1205. enableByHtml5: function($field) {
  1206. var min = $field.attr('min');
  1207. if (min) {
  1208. return {
  1209. value: min
  1210. };
  1211. }
  1212. return false;
  1213. },
  1214. /**
  1215. * Return true if the input value is greater than or equals to given number
  1216. *
  1217. * @param {BootstrapValidator} validator Validate plugin instance
  1218. * @param {jQuery} $field Field element
  1219. * @param {Object} options Can consist of the following keys:
  1220. * - value: The number used to compare to
  1221. * - inclusive [optional]: Can be true or false. Default is true
  1222. * - message: The invalid message
  1223. * @returns {Boolean}
  1224. */
  1225. validate: function(validator, $field, options) {
  1226. var value = $field.val();
  1227. if (value == '') {
  1228. return true;
  1229. }
  1230. value = parseFloat(value);
  1231. return (options.inclusive === true) ? (value > options.value) : (value >= options.value);
  1232. }
  1233. }
  1234. }(window.jQuery));
  1235. ;(function($) {
  1236. $.fn.bootstrapValidator.validators.hex = {
  1237. /**
  1238. * Return true if and only if the input value is a valid hexadecimal number
  1239. *
  1240. * @param {BootstrapValidator} validator The validator plugin instance
  1241. * @param {jQuery} $field Field element
  1242. * @param {Object} options Consist of key:
  1243. * - message: The invalid message
  1244. * @returns {Boolean}
  1245. */
  1246. validate: function(validator, $field, options) {
  1247. var value = $field.val();
  1248. if (value == '') {
  1249. return true;
  1250. }
  1251. return /^[0-9a-fA-F]+$/.test(value);
  1252. }
  1253. };
  1254. }(window.jQuery));
  1255. ;(function($) {
  1256. $.fn.bootstrapValidator.validators.hexColor = {
  1257. enableByHtml5: function($field) {
  1258. return ('color' == $field.attr('type'));
  1259. },
  1260. /**
  1261. * Return true if the input value is a valid hex color
  1262. *
  1263. * @param {BootstrapValidator} validator The validator plugin instance
  1264. * @param {jQuery} $field Field element
  1265. * @param {Object} options Can consist of the following keys:
  1266. * - message: The invalid message
  1267. * @returns {Boolean}
  1268. */
  1269. validate: function(validator, $field, options) {
  1270. var value = $field.val();
  1271. if (value == '') {
  1272. return true;
  1273. }
  1274. return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(value);
  1275. }
  1276. };
  1277. }(window.jQuery));
  1278. ;(function($) {
  1279. $.fn.bootstrapValidator.validators.iban = {
  1280. html5Attributes: {
  1281. message: 'message',
  1282. country: 'country'
  1283. },
  1284. /**
  1285. * Validate an International Bank Account Number (IBAN)
  1286. * To test it, take the sample IBAN from
  1287. * http://www.nordea.com/Our+services/International+products+and+services/Cash+Management/IBAN+countries/908462.html
  1288. *
  1289. * @param {BootstrapValidator} validator The validator plugin instance
  1290. * @param {jQuery} $field Field element
  1291. * @param {Object} options Can consist of the following keys:
  1292. * - message: The invalid message
  1293. * - country: The ISO 3166-1 country code
  1294. * @returns {Boolean}
  1295. */
  1296. validate: function(validator, $field, options) {
  1297. var value = $field.val();
  1298. if (value == '') {
  1299. return true;
  1300. }
  1301. // See
  1302. // http://www.swift.com/dsp/resources/documents/IBAN_Registry.pdf
  1303. // http://en.wikipedia.org/wiki/International_Bank_Account_Number#IBAN_formats_by_country
  1304. var ibanRegex = {
  1305. 'AD': 'AD[0-9]{2}[0-9]{4}[0-9]{4}[A-Z0-9]{12}', // Andorra
  1306. 'AE': 'AE[0-9]{2}[0-9]{3}[0-9]{16}', // United Arab Emirates
  1307. 'AL': 'AL[0-9]{2}[0-9]{8}[A-Z0-9]{16}', // Albania
  1308. 'AO': 'AO[0-9]{2}[0-9]{21}', // Angola
  1309. 'AT': 'AT[0-9]{2}[0-9]{5}[0-9]{11}', // Austria
  1310. 'AZ': 'AZ[0-9]{2}[A-Z]{4}[A-Z0-9]{20}', // Azerbaijan
  1311. 'BA': 'BA[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{8}[0-9]{2}', // Bosnia and Herzegovina
  1312. 'BE': 'BE[0-9]{2}[0-9]{3}[0-9]{7}[0-9]{2}', // Belgium
  1313. 'BF': 'BF[0-9]{2}[0-9]{23}', // Burkina Faso
  1314. 'BG': 'BG[0-9]{2}[A-Z]{4}[0-9]{4}[0-9]{2}[A-Z0-9]{8}', // Bulgaria
  1315. 'BH': 'BH[0-9]{2}[A-Z]{4}[A-Z0-9]{14}', // Bahrain
  1316. 'BI': 'BI[0-9]{2}[0-9]{12}', // Burundi
  1317. 'BJ': 'BJ[0-9]{2}[A-Z]{1}[0-9]{23}', // Benin
  1318. 'BR': 'BR[0-9]{2}[0-9]{8}[0-9]{5}[0-9]{10}[A-Z][A-Z0-9]', // Brazil
  1319. 'CH': 'CH[0-9]{2}[0-9]{5}[A-Z0-9]{12}', // Switzerland
  1320. 'CI': 'CI[0-9]{2}[A-Z]{1}[0-9]{23}', // Ivory Coast
  1321. 'CM': 'CM[0-9]{2}[0-9]{23}', // Cameroon
  1322. 'CR': 'CR[0-9]{2}[0-9]{3}[0-9]{14}', // Costa Rica
  1323. 'CV': 'CV[0-9]{2}[0-9]{21}', // Cape Verde
  1324. 'CY': 'CY[0-9]{2}[0-9]{3}[0-9]{5}[A-Z0-9]{16}', // Cyprus
  1325. 'CZ': 'CZ[0-9]{2}[0-9]{20}', // Czech Republic
  1326. 'DE': 'DE[0-9]{2}[0-9]{8}[0-9]{10}', // Germany
  1327. 'DK': 'DK[0-9]{2}[0-9]{14}', // Denmark
  1328. 'DO': 'DO[0-9]{2}[A-Z0-9]{4}[0-9]{20}', // Dominican Republic
  1329. 'DZ': 'DZ[0-9]{2}[0-9]{20}', // Algeria
  1330. 'EE': 'EE[0-9]{2}[0-9]{2}[0-9]{2}[0-9]{11}[0-9]{1}', // Estonia
  1331. 'ES': 'ES[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{1}[0-9]{1}[0-9]{10}', // Spain
  1332. 'FI': 'FI[0-9]{2}[0-9]{6}[0-9]{7}[0-9]{1}', // Finland
  1333. 'FO': 'FO[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}', // Faroe Islands
  1334. 'FR': 'FR[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}', // France
  1335. 'GB': 'GB[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}', // United Kingdom
  1336. 'GE': 'GE[0-9]{2}[A-Z]{2}[0-9]{16}', // Georgia
  1337. 'GI': 'GI[0-9]{2}[A-Z]{4}[A-Z0-9]{15}', // Gibraltar
  1338. 'GL': 'GL[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}', // Greenland[
  1339. 'GR': 'GR[0-9]{2}[0-9]{3}[0-9]{4}[A-Z0-9]{16}', // Greece
  1340. 'GT': 'GT[0-9]{2}[A-Z0-9]{4}[A-Z0-9]{20}', // Guatemala
  1341. 'HR': 'HR[0-9]{2}[0-9]{7}[0-9]{10}', // Croatia
  1342. 'HU': 'HU[0-9]{2}[0-9]{3}[0-9]{4}[0-9]{1}[0-9]{15}[0-9]{1}', // Hungary
  1343. 'IE': 'IE[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}', // Ireland
  1344. 'IL': 'IL[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{13}', // Israel
  1345. 'IR': 'IR[0-9]{2}[0-9]{22}', // Iran
  1346. 'IS': 'IS[0-9]{2}[0-9]{4}[0-9]{2}[0-9]{6}[0-9]{10}', // Iceland
  1347. 'IT': 'IT[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}', // Italy
  1348. 'JO': 'JO[0-9]{2}[A-Z]{4}[0-9]{4}[0]{8}[A-Z0-9]{10}', // Jordan
  1349. 'KW': 'KW[0-9]{2}[A-Z]{4}[0-9]{22}', // Kuwait
  1350. 'KZ': 'KZ[0-9]{2}[0-9]{3}[A-Z0-9]{13}', // Kazakhstan
  1351. 'LB': 'LB[0-9]{2}[0-9]{4}[A-Z0-9]{20}', // Lebanon
  1352. 'LI': 'LI[0-9]{2}[0-9]{5}[A-Z0-9]{12}', // Liechtenstein
  1353. 'LT': 'LT[0-9]{2}[0-9]{5}[0-9]{11}', // Lithuania
  1354. 'LU': 'LU[0-9]{2}[0-9]{3}[A-Z0-9]{13}', // Luxembourg
  1355. 'LV': 'LV[0-9]{2}[A-Z]{4}[A-Z0-9]{13}', // Latvia
  1356. 'MC': 'MC[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}', // Monaco
  1357. 'MD': 'MD[0-9]{2}[A-Z0-9]{20}', // Moldova
  1358. 'ME': 'ME[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}', // Montenegro
  1359. 'MG': 'MG[0-9]{2}[0-9]{23}', // Madagascar
  1360. 'MK': 'MK[0-9]{2}[0-9]{3}[A-Z0-9]{10}[0-9]{2}', // Macedonia
  1361. 'ML': 'ML[0-9]{2}[A-Z]{1}[0-9]{23}', // Mali
  1362. 'MR': 'MR13[0-9]{5}[0-9]{5}[0-9]{11}[0-9]{2}', // Mauritania
  1363. 'MT': 'MT[0-9]{2}[A-Z]{4}[0-9]{5}[A-Z0-9]{18}', // Malta
  1364. 'MU': 'MU[0-9]{2}[A-Z]{4}[0-9]{2}[0-9]{2}[0-9]{12}[0-9]{3}[A-Z]{3}',// Mauritius
  1365. 'MZ': 'MZ[0-9]{2}[0-9]{21}', // Mozambique
  1366. 'NL': 'NL[0-9]{2}[A-Z]{4}[0-9]{10}', // Netherlands
  1367. 'NO': 'NO[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{1}', // Norway
  1368. 'PK': 'PK[0-9]{2}[A-Z]{4}[A-Z0-9]{16}', // Pakistan
  1369. 'PL': 'PL[0-9]{2}[0-9]{8}[0-9]{16}', // Poland
  1370. 'PS': 'PS[0-9]{2}[A-Z]{4}[A-Z0-9]{21}', // Palestinian
  1371. 'PT': 'PT[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{11}[0-9]{2}', // Portugal
  1372. 'QA': 'QA[0-9]{2}[A-Z]{4}[A-Z0-9]{21}', // Qatar
  1373. 'RO': 'RO[0-9]{2}[A-Z]{4}[A-Z0-9]{16}', // Romania
  1374. 'RS': 'RS[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}', // Serbia
  1375. 'SA': 'SA[0-9]{2}[0-9]{2}[A-Z0-9]{18}', // Saudi Arabia
  1376. 'SE': 'SE[0-9]{2}[0-9]{3}[0-9]{16}[0-9]{1}', // Sweden
  1377. 'SI': 'SI[0-9]{2}[0-9]{5}[0-9]{8}[0-9]{2}', // Slovenia
  1378. 'SK': 'SK[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{10}', // Slovakia
  1379. 'SM': 'SM[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}', // San Marino
  1380. 'SN': 'SN[0-9]{2}[A-Z]{1}[0-9]{23}', // Senegal
  1381. 'TN': 'TN59[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}', // Tunisia
  1382. 'TR': 'TR[0-9]{2}[0-9]{5}[A-Z0-9]{1}[A-Z0-9]{16}', // Turkey
  1383. 'VG': 'VG[0-9]{2}[A-Z]{4}[0-9]{16}' // Virgin Islands, British
  1384. };
  1385. value = value.replace(/[^a-zA-Z0-9]/g, '').toUpperCase();
  1386. var country = options.country || value.substr(0, 2);
  1387. if (!ibanRegex[country]) {
  1388. return false;
  1389. }
  1390. if (!(new RegExp('^' + ibanRegex[country] + '$')).test(value)) {
  1391. return false;
  1392. }
  1393. value = value.substr(4) + value.substr(0, 4);
  1394. value = value.split('').map(function(n) {
  1395. var code = n.charCodeAt(0);
  1396. return (code >= 'A'.charCodeAt(0) && code <= 'Z'.charCodeAt(0))
  1397. // Replace A, B, C, ..., Z with 10, 11, ..., 35
  1398. ? (code - 'A'.charCodeAt(0) + 10)
  1399. : n;
  1400. }).join('');
  1401. var temp = parseInt(value.substr(0, 1), 10),
  1402. length = value.length;
  1403. for (var i = 1; i < length; ++i) {
  1404. temp = (temp * 10 + parseInt(value.substr(i, 1), 10)) % 97;
  1405. }
  1406. return (temp == 1);
  1407. }
  1408. };
  1409. }(window.jQuery));
  1410. ;(function($) {
  1411. $.fn.bootstrapValidator.validators.identical = {
  1412. html5Attributes: {
  1413. message: 'message',
  1414. field: 'field'
  1415. },
  1416. /**
  1417. * Check if input value equals to value of particular one
  1418. *
  1419. * @param {BootstrapValidator} validator The validator plugin instance
  1420. * @param {jQuery} $field Field element
  1421. * @param {Object} options Consists of the following key:
  1422. * - field: The name of field that will be used to compare with current one
  1423. * @returns {Boolean}
  1424. */
  1425. validate: function(validator, $field, options) {
  1426. var value = $field.val();
  1427. if (value == '') {
  1428. return true;
  1429. }
  1430. var compareWith = validator.getFieldElements(options.field);
  1431. if (compareWith == null) {
  1432. return true;
  1433. }
  1434. if (value == compareWith.val()) {
  1435. validator.updateStatus(options.field, validator.STATUS_VALID, 'identical');
  1436. return true;
  1437. } else {
  1438. return false;
  1439. }
  1440. }
  1441. };
  1442. }(window.jQuery));
  1443. ;(function($) {
  1444. $.fn.bootstrapValidator.validators.integer = {
  1445. enableByHtml5: function($field) {
  1446. return ('number' == $field.attr('type'));
  1447. },
  1448. /**
  1449. * Return true if the input value is an integer
  1450. *
  1451. * @param {BootstrapValidator} validator The validator plugin instance
  1452. * @param {jQuery} $field Field element
  1453. * @param {Object} options Can consist of the following key:
  1454. * - message: The invalid message
  1455. * @returns {Boolean}
  1456. */
  1457. validate: function(validator, $field, options) {
  1458. var value = $field.val();
  1459. if (value == '') {
  1460. return true;
  1461. }
  1462. return /^(?:-?(?:0|[1-9][0-9]*))$/.test(value);
  1463. }
  1464. };
  1465. }(window.jQuery));
  1466. ;(function($) {
  1467. $.fn.bootstrapValidator.validators.ip = {
  1468. html5Attributes: {
  1469. message: 'message',
  1470. ipv4: 'ipv4',
  1471. ipv6: 'ipv6'
  1472. },
  1473. /**
  1474. * Return true if the input value is a IP address.
  1475. *
  1476. * @param {BootstrapValidator} validator The validator plugin instance
  1477. * @param {jQuery} $field Field element
  1478. * @param {Object} options Can consist of the following keys:
  1479. * - ipv4: Enable IPv4 validator, default to true
  1480. * - ipv6: Enable IPv6 validator, default to true
  1481. * - message: The invalid message
  1482. * @returns {Boolean}
  1483. */
  1484. validate: function(validator, $field, options) {
  1485. var value = $field.val();
  1486. if (value == '') {
  1487. return true;
  1488. }
  1489. options = $.extend({}, { ipv4: true, ipv6: true }, options);
  1490. if (options.ipv4) {
  1491. return /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(value);
  1492. } else if (options.ipv6) {
  1493. return /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/.test(str);
  1494. }
  1495. return false;
  1496. }
  1497. };
  1498. }(window.jQuery));
  1499. ;(function($) {
  1500. $.fn.bootstrapValidator.validators.isbn = {
  1501. /**
  1502. * Return true if the input value is a valid ISBN 10 or ISBN 13 number
  1503. *
  1504. * @param {BootstrapValidator} validator The validator plugin instance
  1505. * @param {jQuery} $field Field element
  1506. * @param {Object} options Can consist of the following keys:
  1507. * - message: The invalid message
  1508. * @returns {Boolean}
  1509. */
  1510. validate: function(validator, $field, options) {
  1511. var value = $field.val();
  1512. if (value == '') {
  1513. return true;
  1514. }
  1515. // Replace all special characters except digits and X
  1516. value = value.replace(/[^\dX]/gi, '');
  1517. var chars = value.split(''),
  1518. sum = 0,
  1519. checksum;
  1520. // See http://en.wikipedia.org/wiki/International_Standard_Book_Number
  1521. switch (chars.length) {
  1522. // ISBN 10
  1523. case 10:
  1524. sum = 0;
  1525. for (var i = 0; i < 9; i++) {
  1526. sum += ((10 - i) * parseInt(chars[i]));
  1527. }
  1528. checksum = 11 - (sum % 11);
  1529. if (checksum == 11) {
  1530. checksum = 0;
  1531. } else if (checksum == 10) {
  1532. checksum = 'X';
  1533. }
  1534. return (checksum == chars[9]);
  1535. // ISBN 13
  1536. case 13:
  1537. sum = 0;
  1538. for (var i = 0; i < 12; i++) {
  1539. sum += ((i % 2 == 0) ? parseInt(chars[i]) : (parseInt(chars[i]) * 3));
  1540. }
  1541. checksum = 10 - (sum % 10);
  1542. if (checksum == 10) {
  1543. checksum = '0';
  1544. }
  1545. return (checksum == chars[12]);
  1546. default:
  1547. return false;
  1548. }
  1549. }
  1550. };
  1551. }(window.jQuery));
  1552. ;(function($) {
  1553. $.fn.bootstrapValidator.validators.lessThan = {
  1554. html5Attributes: {
  1555. message: 'message',
  1556. value: 'value',
  1557. inclusive: 'inclusive'
  1558. },
  1559. enableByHtml5: function($field) {
  1560. var max = $field.attr('max');
  1561. if (max) {
  1562. return {
  1563. value: max
  1564. };
  1565. }
  1566. return false;
  1567. },
  1568. /**
  1569. * Return true if the input value is less than or equal to given number
  1570. *
  1571. * @param {BootstrapValidator} validator The validator plugin instance
  1572. * @param {jQuery} $field Field element
  1573. * @param {Object} options Can consist of the following keys:
  1574. * - value: The number used to compare to
  1575. * - inclusive [optional]: Can be true or false. Default is true
  1576. * - message: The invalid message
  1577. * @returns {Boolean}
  1578. */
  1579. validate: function(validator, $field, options) {
  1580. var value = $field.val();
  1581. if (value == '') {
  1582. return true;
  1583. }
  1584. value = parseFloat(value);
  1585. return (options.inclusive === false) ? (value <= options.value) : (value < options.value);
  1586. }
  1587. };
  1588. }(window.jQuery));
  1589. ;(function($) {
  1590. $.fn.bootstrapValidator.validators.mac = {
  1591. /**
  1592. * Return true if the input value is a MAC address.
  1593. *
  1594. * @param {BootstrapValidator} validator The validator plugin instance
  1595. * @param {jQuery} $field Field element
  1596. * @param {Object} options Can consist of the following keys:
  1597. * - message: The invalid message
  1598. * @returns {Boolean}
  1599. */
  1600. validate: function(validator, $field, options) {
  1601. var value = $field.val();
  1602. if (value == '') {
  1603. return true;
  1604. }
  1605. return /^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$/.test(value);
  1606. }
  1607. };
  1608. }(window.jQuery));
  1609. ;(function($) {
  1610. $.fn.bootstrapValidator.validators.notEmpty = {
  1611. enableByHtml5: function($field) {
  1612. var required = $field.attr('required') + '';
  1613. return ('required' == required || 'true' == required);
  1614. },
  1615. /**
  1616. * Check if input value is empty or not
  1617. *
  1618. * @param {BootstrapValidator} validator The validator plugin instance
  1619. * @param {jQuery} $field Field element
  1620. * @param {Object} options
  1621. * @returns {Boolean}
  1622. */
  1623. validate: function(validator, $field, options) {
  1624. var type = $field.attr('type');
  1625. if ('radio' == type || 'checkbox' == type) {
  1626. return validator
  1627. .getFieldElements($field.attr('data-bv-field'))
  1628. .filter(':checked')
  1629. .length > 0;
  1630. }
  1631. return $.trim($field.val()) != '';
  1632. }
  1633. };
  1634. }(window.jQuery));
  1635. ;(function($) {
  1636. $.fn.bootstrapValidator.validators.numeric = {
  1637. /**
  1638. * Validate decimal number
  1639. *
  1640. * @param {BootstrapValidator} validator The validator plugin instance
  1641. * @param {jQuery} $field Field element
  1642. * @param {Object} options Consist of key:
  1643. * - message: The invalid message
  1644. * @returns {Boolean}
  1645. */
  1646. validate: function(validator, $field, options) {
  1647. var value = $field.val();
  1648. if (value == '') {
  1649. return true;
  1650. }
  1651. return !isNaN(parseFloat(value)) && isFinite(value);
  1652. }
  1653. };
  1654. }(window.jQuery));
  1655. ;(function($) {
  1656. $.fn.bootstrapValidator.validators.phone = {
  1657. html5Attributes: {
  1658. message: 'message',
  1659. country: 'country'
  1660. },
  1661. /**
  1662. * Return true if the input value contains a valid US phone number only
  1663. *
  1664. * @param {BootstrapValidator} validator Validate plugin instance
  1665. * @param {jQuery} $field Field element
  1666. * @param {Object} options Consist of key:
  1667. * - message: The invalid message
  1668. * - country: The ISO 3166 country code
  1669. * Currently it only supports United State (US) country
  1670. * @returns {Boolean}
  1671. */
  1672. validate: function(validator, $field, options) {
  1673. var value = $field.val();
  1674. if (value == '') {
  1675. return true;
  1676. }
  1677. var country = (options.country || 'US').toUpperCase();
  1678. switch (country) {
  1679. case 'US':
  1680. default:
  1681. // Make sure US phone numbers have 10 digits
  1682. // May start with 1, +1, or 1-; should discard
  1683. // Area code may be delimited with (), & sections may be delimited with . or -
  1684. // Test: http://regexr.com/38mqi
  1685. value = value.replace(/\D/g, '');
  1686. return (/^(?:(1\-?)|(\+1 ?))?\(?(\d{3})[\)\-\.]?(\d{3})[\-\.]?(\d{4})$/).test(value) && (value.length == 10);
  1687. }
  1688. }
  1689. }
  1690. }(window.jQuery));
  1691. ;(function($) {
  1692. $.fn.bootstrapValidator.validators.regexp = {
  1693. html5Attributes: {
  1694. message: 'message',
  1695. regexp: 'regexp'
  1696. },
  1697. enableByHtml5: function($field) {
  1698. var pattern = $field.attr('pattern');
  1699. if (pattern) {
  1700. return {
  1701. regexp: pattern
  1702. };
  1703. }
  1704. return false;
  1705. },
  1706. /**
  1707. * Check if the element value matches given regular expression
  1708. *
  1709. * @param {BootstrapValidator} validator The validator plugin instance
  1710. * @param {jQuery} $field Field element
  1711. * @param {Object} options Consists of the following key:
  1712. * - regexp: The regular expression you need to check
  1713. * @returns {Boolean}
  1714. */
  1715. validate: function(validator, $field, options) {
  1716. var value = $field.val();
  1717. if (value == '') {
  1718. return true;
  1719. }
  1720. var regexp = ('string' == typeof options.regexp) ? new RegExp(options.regexp) : options.regexp;
  1721. return regexp.test(value);
  1722. }
  1723. };
  1724. }(window.jQuery));
  1725. ;(function ($) {
  1726. $.fn.bootstrapValidator.validators.remote = {
  1727. html5Attributes: {
  1728. message: 'message',
  1729. url: 'url',
  1730. name: 'name'
  1731. },
  1732. /**
  1733. * Request a remote server to check the input value
  1734. *
  1735. * @param {BootstrapValidator} validator Plugin instance
  1736. * @param {jQuery} $field Field element
  1737. * @param {Object} options Can consist of the following keys:
  1738. * - url
  1739. * - data [optional]: By default, it will take the value
  1740. * {
  1741. * <fieldName>: <fieldValue>
  1742. * }
  1743. * - name [optional]: Override the field name for the request.
  1744. * - message: The invalid message
  1745. * @returns {Boolean|Deferred}
  1746. */
  1747. validate: function(validator, $field, options) {
  1748. var value = $field.val();
  1749. if (value == '') {
  1750. return true;
  1751. }
  1752. var name = $field.attr('data-bv-field'), data = options.data;
  1753. if (data == null) {
  1754. data = {};
  1755. }
  1756. // Support dynamic data
  1757. if ('function' == typeof data) {
  1758. data = data.call(this, validator);
  1759. }
  1760. data[options.name || name] = value;
  1761. var dfd = new $.Deferred();
  1762. var xhr = $.ajax({
  1763. type: 'POST',
  1764. url: options.url,
  1765. dataType: 'json',
  1766. data: data
  1767. });
  1768. xhr.then(function(response) {
  1769. dfd.resolve($field, 'remote', response.valid === true || response.valid === 'true');
  1770. });
  1771. dfd.fail(function() {
  1772. xhr.abort();
  1773. });
  1774. return dfd;
  1775. }
  1776. };
  1777. }(window.jQuery));
  1778. ;(function($) {
  1779. $.fn.bootstrapValidator.validators.siren = {
  1780. /**
  1781. * Check if a string is a siren number
  1782. *
  1783. * @param {BootstrapValidator} validator The validator plugin instance
  1784. * @param {jQuery} $field Field element
  1785. * @param {Object} options Consist of key:
  1786. * - message: The invalid message
  1787. * @returns {Boolean}
  1788. */
  1789. validate: function(validator, $field, options) {
  1790. var value = $field.val();
  1791. if (value == '') {
  1792. return true;
  1793. }
  1794. var sum = 0,
  1795. length = value.length,
  1796. tmp;
  1797. for (var i = 0; i < length; i++) {
  1798. tmp = parseInt(value.charAt(i));
  1799. if ((i % 2) == 1) {
  1800. tmp = tmp * 2;
  1801. if (tmp > 9) {
  1802. tmp -= 9;
  1803. }
  1804. }
  1805. sum += tmp;
  1806. }
  1807. return ((sum % 10) == 0);
  1808. }
  1809. };
  1810. }(window.jQuery));
  1811. ;(function($) {
  1812. $.fn.bootstrapValidator.validators.siret = {
  1813. /**
  1814. * Check if a string is a siret number
  1815. *
  1816. * @param {BootstrapValidator} validator The validator plugin instance
  1817. * @param {jQuery} $field Field element
  1818. * @param {Object} options Consist of key:
  1819. * - message: The invalid message
  1820. * @returns {Boolean}
  1821. */
  1822. validate: function(validator, $field, options) {
  1823. var value = $field.val();
  1824. if (value == '') {
  1825. return true;
  1826. }
  1827. var sum = 0,
  1828. length = value.length,
  1829. tmp;
  1830. for (var i = 0; i < length; i++) {
  1831. tmp = parseInt(value.charAt(i));
  1832. if ((i % 2) == 0) {
  1833. tmp = tmp * 2;
  1834. if (tmp > 9) {
  1835. tmp -= 9;
  1836. }
  1837. }
  1838. sum += tmp;
  1839. }
  1840. return ((sum % 10) == 0);
  1841. }
  1842. };
  1843. }(window.jQuery));
  1844. ;(function($) {
  1845. $.fn.bootstrapValidator.validators.step = {
  1846. html5Attributes: {
  1847. message: 'message',
  1848. base: 'baseValue',
  1849. step: 'step'
  1850. },
  1851. /**
  1852. * Return true if the input value is valid step one
  1853. *
  1854. * @param {BootstrapValidator} validator The validator plugin instance
  1855. * @param {jQuery} $field Field element
  1856. * @param {Object} options Can consist of the following keys:
  1857. * - baseValue: The base value
  1858. * - step: The step
  1859. * - message: The invalid message
  1860. * @returns {Boolean}
  1861. */
  1862. validate: function(validator, $field, options) {
  1863. var value = $field.val();
  1864. if (value == '') {
  1865. return true;
  1866. }
  1867. options = $.extend({}, { baseValue: 0, step: 1 }, options);
  1868. value = parseFloat(value);
  1869. if (isNaN(value) || !isFinite(value)) {
  1870. return false;
  1871. }
  1872. var round = function(x, precision) {
  1873. var m = Math.pow(10, precision);
  1874. x = x * m;
  1875. var sign = (x > 0) | -(x < 0),
  1876. isHalf = (x % 1 === 0.5 * sign);
  1877. if (isHalf) {
  1878. return (Math.floor(x) + (sign > 0)) / m;
  1879. } else {
  1880. return Math.round(x) / m;
  1881. }
  1882. },
  1883. floatMod = function(x, y) {
  1884. if (y == 0.0) {
  1885. return 1.0;
  1886. }
  1887. var dotX = (x + '').split('.'),
  1888. dotY = (y + '').split('.'),
  1889. precision = ((dotX.length == 1) ? 0 : dotX[1].length) + ((dotY.length == 1) ? 0 : dotY[1].length);
  1890. return round(x - y * Math.floor(x / y), precision);
  1891. };
  1892. var mod = floatMod(value - options.baseValue, options.step);
  1893. return (mod == 0.0 || mod == options.step);
  1894. }
  1895. };
  1896. }(window.jQuery));
  1897. ;(function($) {
  1898. $.fn.bootstrapValidator.validators.stringCase = {
  1899. html5Attributes: {
  1900. message: 'message',
  1901. 'case': 'case'
  1902. },
  1903. /**
  1904. * Check if a string is a lower or upper case one
  1905. *
  1906. * @param {BootstrapValidator} validator The validator plugin instance
  1907. * @param {jQuery} $field Field element
  1908. * @param {Object} options Consist of key:
  1909. * - message: The invalid message
  1910. * - case: Can be 'lower' (default) or 'upper'
  1911. * @returns {Boolean}
  1912. */
  1913. validate: function(validator, $field, options) {
  1914. var value = $field.val();
  1915. if (value == '') {
  1916. return true;
  1917. }
  1918. var stringCase = (options['case'] || 'lower').toLowerCase();
  1919. switch (stringCase) {
  1920. case 'upper':
  1921. return value === value.toUpperCase();
  1922. case 'lower':
  1923. default:
  1924. return value === value.toLowerCase();
  1925. }
  1926. }
  1927. };
  1928. }(window.jQuery));
  1929. ;(function($) {
  1930. $.fn.bootstrapValidator.validators.stringLength = {
  1931. html5Attributes: {
  1932. message: 'message',
  1933. min: 'min',
  1934. max: 'max'
  1935. },
  1936. enableByHtml5: function($field) {
  1937. var maxLength = $field.attr('maxlength');
  1938. if (maxLength) {
  1939. return {
  1940. max: parseInt(maxLength, 10)
  1941. };
  1942. }
  1943. return false;
  1944. },
  1945. /**
  1946. * Check if the length of element value is less or more than given number
  1947. *
  1948. * @param {BootstrapValidator} validator The validator plugin instance
  1949. * @param {jQuery} $field Field element
  1950. * @param {Object} options Consists of following keys:
  1951. * - min
  1952. * - max
  1953. * At least one of two keys is required
  1954. * - message: The invalid message
  1955. * @returns {Boolean}
  1956. */
  1957. validate: function(validator, $field, options) {
  1958. var value = $field.val();
  1959. if (value == '') {
  1960. return true;
  1961. }
  1962. var length = $.trim(value).length;
  1963. if ((options.min && length < options.min) || (options.max && length > options.max)) {
  1964. return false;
  1965. }
  1966. return true;
  1967. }
  1968. };
  1969. }(window.jQuery));
  1970. ;(function($) {
  1971. $.fn.bootstrapValidator.validators.uri = {
  1972. enableByHtml5: function($field) {
  1973. return ('url' == $field.attr('type'));
  1974. },
  1975. /**
  1976. * Return true if the input value is a valid URL
  1977. *
  1978. * @param {BootstrapValidator} validator The validator plugin instance
  1979. * @param {jQuery} $field Field element
  1980. * @param {Object} options
  1981. * @returns {Boolean}
  1982. */
  1983. validate: function(validator, $field, options) {
  1984. var value = $field.val();
  1985. if (value == '') {
  1986. return true;
  1987. }
  1988. // Credit to https://gist.github.com/dperini/729294
  1989. //
  1990. // Regular Expression for URL validation
  1991. //
  1992. // Author: Diego Perini
  1993. // Updated: 2010/12/05
  1994. //
  1995. // the regular expression composed & commented
  1996. // could be easily tweaked for RFC compliance,
  1997. // it was expressly modified to fit & satisfy
  1998. // these test for an URL shortener:
  1999. //
  2000. // http://mathiasbynens.be/demo/url-regex
  2001. //
  2002. // Notes on possible differences from a standard/generic validation:
  2003. //
  2004. // - utf-8 char class take in consideration the full Unicode range
  2005. // - TLDs have been made mandatory so single names like "localhost" fails
  2006. // - protocols have been restricted to ftp, http and https only as requested
  2007. //
  2008. // Changes:
  2009. //
  2010. // - IP address dotted notation validation, range: 1.0.0.0 - 223.255.255.255
  2011. // first and last IP address of each class is considered invalid
  2012. // (since they are broadcast/network addresses)
  2013. //
  2014. // - Added exclusion of private, reserved and/or local networks ranges
  2015. //
  2016. // Compressed one-line versions:
  2017. //
  2018. // Javascript version
  2019. //
  2020. // /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/i
  2021. //
  2022. // PHP version
  2023. //
  2024. // _^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$_iuS
  2025. var urlExp = new RegExp(
  2026. "^" +
  2027. // protocol identifier
  2028. "(?:(?:https?|ftp)://)" +
  2029. // user:pass authentication
  2030. "(?:\\S+(?::\\S*)?@)?" +
  2031. "(?:" +
  2032. // IP address exclusion
  2033. // private & local networks
  2034. "(?!10(?:\\.\\d{1,3}){3})" +
  2035. "(?!127(?:\\.\\d{1,3}){3})" +
  2036. "(?!169\\.254(?:\\.\\d{1,3}){2})" +
  2037. "(?!192\\.168(?:\\.\\d{1,3}){2})" +
  2038. "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" +
  2039. // IP address dotted notation octets
  2040. // excludes loopback network 0.0.0.0
  2041. // excludes reserved space >= 224.0.0.0
  2042. // excludes network & broacast addresses
  2043. // (first & last IP address of each class)
  2044. "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" +
  2045. "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" +
  2046. "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" +
  2047. "|" +
  2048. // host name
  2049. "(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)" +
  2050. // domain name
  2051. "(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*" +
  2052. // TLD identifier
  2053. "(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))" +
  2054. ")" +
  2055. // port number
  2056. "(?::\\d{2,5})?" +
  2057. // resource path
  2058. "(?:/[^\\s]*)?" +
  2059. "$", "i"
  2060. );
  2061. return urlExp.test(value);
  2062. }
  2063. };
  2064. }(window.jQuery));
  2065. ;(function($) {
  2066. $.fn.bootstrapValidator.validators.uuid = {
  2067. html5Attributes: {
  2068. message: 'message',
  2069. version: 'version'
  2070. },
  2071. /**
  2072. * Return true if and only if the input value is a valid UUID string
  2073. *
  2074. * @see http://en.wikipedia.org/wiki/Universally_unique_identifier
  2075. * @param {BootstrapValidator} validator The validator plugin instance
  2076. * @param {jQuery} $field Field element
  2077. * @param {Object} options Consist of key:
  2078. * - message: The invalid message
  2079. * - version: Can be 3, 4, 5, null
  2080. * @returns {Boolean}
  2081. */
  2082. validate: function(validator, $field, options) {
  2083. var value = $field.val();
  2084. if (value == '') {
  2085. return true;
  2086. }
  2087. // See the format at http://en.wikipedia.org/wiki/Universally_unique_identifier#Variants_and_versions
  2088. var patterns = {
  2089. '3': /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i,
  2090. '4': /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,
  2091. '5': /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,
  2092. all: /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i
  2093. },
  2094. version = options.version ? (options.version + '') : 'all';
  2095. return (null == patterns[version]) ? true : patterns[version].test(value);
  2096. }
  2097. };
  2098. }(window.jQuery));
  2099. ;(function($) {
  2100. $.fn.bootstrapValidator.validators.vin = {
  2101. /**
  2102. * Validate an US VIN (Vehicle Identification Number)
  2103. *
  2104. * @param {BootstrapValidator} validator The validator plugin instance
  2105. * @param {jQuery} $field Field element
  2106. * @param {Object} options Consist of key:
  2107. * - message: The invalid message
  2108. * @returns {Boolean}
  2109. */
  2110. validate: function(validator, $field, options) {
  2111. var value = $field.val();
  2112. if (value == '') {
  2113. return true;
  2114. }
  2115. // Don't accept I, O, Q characters
  2116. if (!/^[a-hj-npr-z0-9]{8}[0-9xX][a-hj-npr-z0-9]{8}$/i.test(value)) {
  2117. return false;
  2118. }
  2119. value = value.toUpperCase();
  2120. var chars = {
  2121. A: 1, B: 2, C: 3, D: 4, E: 5, F: 6, G: 7, H: 8,
  2122. J: 1, K: 2, L: 3, M: 4, N: 5, P: 7, R: 9,
  2123. S: 2, T: 3, U: 4, V: 5, W: 6, X: 7, Y: 8, Z: 9,
  2124. '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, '0': 0
  2125. },
  2126. weights = [8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2],
  2127. sum = 0,
  2128. length = value.length;
  2129. for (var i = 0; i < length; i++) {
  2130. sum += chars[value.charAt(i) + ''] * weights[i];
  2131. }
  2132. var reminder = sum % 11;
  2133. if (reminder == 10) {
  2134. reminder = 'X';
  2135. }
  2136. return reminder == value.charAt(8);
  2137. }
  2138. };
  2139. }(window.jQuery));
  2140. ;(function($) {
  2141. $.fn.bootstrapValidator.validators.zipCode = {
  2142. html5Attributes: {
  2143. message: 'message',
  2144. country: 'country'
  2145. },
  2146. /**
  2147. * Return true if and only if the input value is a valid country zip code
  2148. *
  2149. * @param {BootstrapValidator} validator The validator plugin instance
  2150. * @param {jQuery} $field Field element
  2151. * @param {Object} options Consist of key:
  2152. * - message: The invalid message
  2153. * - country: The ISO 3166 country code
  2154. *
  2155. * Currently it supports the following countries:
  2156. * - US (United State)
  2157. * - CA (Canada)
  2158. * - DK (Denmark)
  2159. * - SE (Sweden)
  2160. * @returns {Boolean}
  2161. */
  2162. validate: function(validator, $field, options) {
  2163. var value = $field.val();
  2164. if (value == '' || !options.country) {
  2165. return true;
  2166. }
  2167. var country = (options.country || 'US').toUpperCase();
  2168. switch (country) {
  2169. case 'CA':
  2170. return /(?:A|B|C|E|G|J|K|L|M|N|P|R|S|T|V|X|Y){1}[0-9]{1}(?:A|B|C|E|G|J|K|L|M|N|P|R|S|T|V|X|Y){1}\s?[0-9]{1}(?:A|B|C|E|G|J|K|L|M|N|P|R|S|T|V|X|Y){1}[0-9]{1}/i.test(value);
  2171. case 'DK':
  2172. return /^(DK(-|\s)?)?\d{4}$/i.test(value);
  2173. case 'SE':
  2174. return /^(S-)?\d{3}\s?\d{2}$/i.test(value);
  2175. case 'US':
  2176. default:
  2177. return /^\d{4,5}([\-]\d{4})?$/.test(value);
  2178. }
  2179. }
  2180. };
  2181. }(window.jQuery));