geico-design-kit 7.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of geico-design-kit might be problematic. Click here for more details.

Files changed (107) hide show
  1. package/.babelrc +5 -0
  2. package/LICENSE +0 -0
  3. package/dist/analytics.js +119 -0
  4. package/dist/appState.js +56 -0
  5. package/dist/baseComponent.js +110 -0
  6. package/dist/components/Accordion.js +312 -0
  7. package/dist/components/AddressAutoComplete.js +220 -0
  8. package/dist/components/Alert.js +145 -0
  9. package/dist/components/BackgroundPattern.js +99 -0
  10. package/dist/components/BackgroundPatternPortfolio.js +242 -0
  11. package/dist/components/ButtonSwitch.js +236 -0
  12. package/dist/components/CardSelections.js +230 -0
  13. package/dist/components/CommonQuestionsSquares.js +169 -0
  14. package/dist/components/Confirmation.js +156 -0
  15. package/dist/components/ConsolidatedSummary.js +489 -0
  16. package/dist/components/CoverageGraph.js +201 -0
  17. package/dist/components/CreditCard.js +591 -0
  18. package/dist/components/CurrencyInput.js +302 -0
  19. package/dist/components/DatePicker.js +468 -0
  20. package/dist/components/DockedMessage.js +146 -0
  21. package/dist/components/DotNavigation.js +200 -0
  22. package/dist/components/EditComponent.js +128 -0
  23. package/dist/components/EditableTable.js +113 -0
  24. package/dist/components/InPageNavigation.js +360 -0
  25. package/dist/components/Loader.js +232 -0
  26. package/dist/components/MakePayment.js +361 -0
  27. package/dist/components/Modal.js +254 -0
  28. package/dist/components/MoreInfoButton.js +227 -0
  29. package/dist/components/MultipleSelectBox.js +217 -0
  30. package/dist/components/NavigationalBox.js +161 -0
  31. package/dist/components/Navigator.js +294 -0
  32. package/dist/components/PasswordMeter.js +201 -0
  33. package/dist/components/PayPlans.js +534 -0
  34. package/dist/components/SegmentedControl.js +327 -0
  35. package/dist/components/SortableTable.js +166 -0
  36. package/dist/components/Tabs.js +1 -0
  37. package/dist/components/TextAreaCountdown.js +219 -0
  38. package/dist/components/Timeline.js +498 -0
  39. package/dist/components/TimelineFilter.js +492 -0
  40. package/dist/components/ToTopArrow.js +153 -0
  41. package/dist/components/Tooltip.js +329 -0
  42. package/dist/components/Upsell.js +168 -0
  43. package/dist/components/VIN.js +271 -0
  44. package/dist/components/ValidateForm.js +938 -0
  45. package/dist/components/ViewMoreLess.js +191 -0
  46. package/dist/components/ZipCode.js +191 -0
  47. package/dist/components/portfolio.js +99 -0
  48. package/dist/geico-design-kit.js +141 -0
  49. package/dist/global/components.js +98 -0
  50. package/dist/global/footer.js +26 -0
  51. package/dist/global/nav.js +1257 -0
  52. package/dist/services/CharacterTypeService.js +106 -0
  53. package/dist/services/UserAgentService.js +73 -0
  54. package/dist/utils.js +79 -0
  55. package/package.json +32 -0
  56. package/src/analytics.js +82 -0
  57. package/src/appState.js +56 -0
  58. package/src/baseComponent.js +156 -0
  59. package/src/components/Accordion.js +336 -0
  60. package/src/components/AddressAutoComplete.js +236 -0
  61. package/src/components/Alert.js +135 -0
  62. package/src/components/BackgroundPattern.js +96 -0
  63. package/src/components/BackgroundPatternPortfolio.js +284 -0
  64. package/src/components/ButtonSwitch.js +241 -0
  65. package/src/components/CardSelections.js +240 -0
  66. package/src/components/CommonQuestionsSquares.js +179 -0
  67. package/src/components/Confirmation.js +160 -0
  68. package/src/components/ConsolidatedSummary.js +505 -0
  69. package/src/components/CoverageGraph.js +203 -0
  70. package/src/components/CreditCard.js +595 -0
  71. package/src/components/CurrencyInput.js +321 -0
  72. package/src/components/DatePicker.js +487 -0
  73. package/src/components/DockedMessage.js +142 -0
  74. package/src/components/DotNavigation.js +206 -0
  75. package/src/components/EditComponent.js +130 -0
  76. package/src/components/EditableTable.js +106 -0
  77. package/src/components/InPageNavigation.js +391 -0
  78. package/src/components/Loader.js +272 -0
  79. package/src/components/MakePayment.js +397 -0
  80. package/src/components/Modal.js +279 -0
  81. package/src/components/MoreInfoButton.js +243 -0
  82. package/src/components/MultipleSelectBox.js +211 -0
  83. package/src/components/NavigationalBox.js +163 -0
  84. package/src/components/Navigator.js +338 -0
  85. package/src/components/PasswordMeter.js +209 -0
  86. package/src/components/PayPlans.js +604 -0
  87. package/src/components/SegmentedControl.js +365 -0
  88. package/src/components/SortableTable.js +176 -0
  89. package/src/components/Tabs.js +0 -0
  90. package/src/components/TextAreaCountdown.js +231 -0
  91. package/src/components/Timeline.js +532 -0
  92. package/src/components/TimelineFilter.js +533 -0
  93. package/src/components/ToTopArrow.js +153 -0
  94. package/src/components/Tooltip.js +344 -0
  95. package/src/components/Upsell.js +196 -0
  96. package/src/components/VIN.js +289 -0
  97. package/src/components/ValidateForm.js +1030 -0
  98. package/src/components/ViewMoreLess.js +193 -0
  99. package/src/components/ZipCode.js +193 -0
  100. package/src/components/portfolio.js +106 -0
  101. package/src/geico-design-kit.js +144 -0
  102. package/src/global/components.js +92 -0
  103. package/src/global/footer.js +25 -0
  104. package/src/global/nav.js +1457 -0
  105. package/src/services/CharacterTypeService.js +107 -0
  106. package/src/services/UserAgentService.js +59 -0
  107. package/src/utils.js +82 -0
@@ -0,0 +1,938 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports["default"] = void 0;
7
+ var _baseComponent = _interopRequireDefault(require("../../src/baseComponent"));
8
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
9
+ function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
10
+ function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
11
+ function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
12
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
13
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
14
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
15
+ //Require static assets
16
+
17
+ //
18
+ // PureJS Validation - Our component builds off the validation provided by validate.js
19
+ //
20
+
21
+ /*
22
+ * validate.js 1.4.1
23
+ * Copyright (c) 2011 - 2014 Rick Harrison, http://rickharrison.me
24
+ * validate.js is open sourced under the MIT license.
25
+ * Portions of validate.js are inspired by CodeIgniter.
26
+ * http://rickharrison.github.com/validate.js
27
+ */
28
+
29
+ (function (window, document, undefined) {
30
+ /*
31
+ * If you would like an application-wide config, change these defaults.
32
+ * Otherwise, use the setMessage() function to configure form specific messages.
33
+ */
34
+
35
+ var defaults = {
36
+ messages: {
37
+ required: 'The %s field is required.',
38
+ matches: 'The %s field does not match the %s field.',
39
+ "default": 'The %s field is still set to default, please change.',
40
+ valid_email: 'The %s field must contain a valid email address.',
41
+ valid_emails: 'The %s field must contain all valid email addresses.',
42
+ min_length: 'The %s field must be at least %s characters in length.',
43
+ max_length: 'The %s field must not exceed %s characters in length.',
44
+ exact_length: 'The %s field must be exactly %s characters in length.',
45
+ greater_than: 'The %s field must contain a number greater than %s.',
46
+ less_than: 'The %s field must contain a number less than %s.',
47
+ alpha: 'The %s field must only contain alphabetical characters.',
48
+ alpha_numeric: 'The %s field must only contain alpha-numeric characters.',
49
+ alpha_dash: 'The %s field must only contain alpha-numeric characters, underscores, and dashes.',
50
+ numeric: 'The %s field must contain only numbers.',
51
+ integer: 'The %s field must contain an integer.',
52
+ decimal: 'The %s field must contain a decimal number.',
53
+ is_natural: 'The %s field must contain only positive numbers.',
54
+ is_natural_no_zero: 'The %s field must contain a number greater than zero.',
55
+ valid_ip: 'The %s field must contain a valid IP.',
56
+ valid_base64: 'The %s field must contain a base64 string.',
57
+ valid_credit_card: 'The %s field must contain a valid credit card number.',
58
+ is_file_type: 'The %s field must contain only %s files.',
59
+ valid_url: 'The %s field must contain a valid URL.'
60
+ },
61
+ callback: function callback(errors) {}
62
+ };
63
+
64
+ /*
65
+ * Define the regular expressions that will be used
66
+ */
67
+
68
+ var ruleRegex = /^(.+?)\[(.+)\]$/,
69
+ numericRegex = /^[0-9]+$/,
70
+ integerRegex = /^\-?[0-9]+$/,
71
+ decimalRegex = /^\-?[0-9]*\.?[0-9]+$/,
72
+ emailRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9]){1,})+$/,
73
+ alphaRegex = /^[a-z]+$/i,
74
+ alphaNumericRegex = /^[a-z0-9]+$/i,
75
+ alphaDashRegex = /^[a-z0-9_\-]+$/i,
76
+ naturalRegex = /^[0-9]+$/i,
77
+ naturalNoZeroRegex = /^[1-9][0-9]*$/i,
78
+ ipRegex = /^((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})$/i,
79
+ base64Regex = /[^a-zA-Z0-9\/\+=]/i,
80
+ numericDashRegex = /^[\d\-\s]+$/,
81
+ urlRegex = /^((http|https):\/\/(\w+:{0,1}\w*@)?(\S+)|)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/;
82
+
83
+ /*
84
+ * The exposed public object to validate a form:
85
+ *
86
+ * @param formNameOrNode - String - The name attribute of the form (i.e. <form name="myForm"></form>) or node of the form element
87
+ * @param fields - Array - [{
88
+ * name: The name of the element (i.e. <input name="myField" />)
89
+ * display: 'Field Name'
90
+ * rules: required|matches[password_confirm]
91
+ * }]
92
+ * @param callback - Function - The callback after validation has been performed.
93
+ * @argument errors - An array of validation errors
94
+ * @argument event - The javascript event
95
+ */
96
+
97
+ var FormValidator = function FormValidator(formNameOrNode, fields, callback) {
98
+ this.callback = callback || defaults.callback;
99
+ this.errors = [];
100
+ this.fields = {};
101
+ this.form = this._formByNameOrNode(formNameOrNode) || {};
102
+ this.messages = {};
103
+ this.handlers = {};
104
+ this.conditionals = {};
105
+ for (var i = 0, fieldLength = fields.length; i < fieldLength; i++) {
106
+ var field = fields[i];
107
+
108
+ // If passed in incorrectly, we need to skip the field.
109
+ if (!field.name && !field.names || !field.rules) {
110
+ continue;
111
+ }
112
+
113
+ /*
114
+ * Build the master fields array that has all the information needed to validate
115
+ */
116
+
117
+ if (field.names) {
118
+ for (var j = 0, fieldNamesLength = field.names.length; j < fieldNamesLength; j++) {
119
+ this._addField(field, field.names[j]);
120
+ }
121
+ } else {
122
+ this._addField(field, field.name);
123
+ }
124
+ }
125
+
126
+ /*
127
+ * Attach an event callback for the form submission
128
+ */
129
+
130
+ var _onsubmit = this.form.onsubmit;
131
+ this.form.onsubmit = function (that) {
132
+ return function (evt) {
133
+ try {
134
+ return that._validateForm(evt) && (_onsubmit === undefined || _onsubmit());
135
+ } catch (e) {}
136
+ };
137
+ }(this);
138
+ },
139
+ attributeValue = function attributeValue(element, attributeName) {
140
+ if (element.length > 0 && (element[0].type === 'radio' || element[0].type === 'checkbox')) {
141
+ for (var i = 0; element.length > i; i++) {
142
+ if (element[i].checked) {
143
+ return element[i][attributeName];
144
+ }
145
+ }
146
+ return;
147
+ }
148
+ return element[attributeName];
149
+ };
150
+
151
+ /*
152
+ * @public
153
+ * Sets a custom message for one of the rules
154
+ */
155
+
156
+ FormValidator.prototype.setMessage = function (rule, message) {
157
+ this.messages[rule] = message;
158
+
159
+ // return this for chaining
160
+ return this;
161
+ };
162
+
163
+ /*
164
+ * @public
165
+ * Registers a callback for a custom rule (i.e. callback_username_check)
166
+ */
167
+
168
+ FormValidator.prototype.registerCallback = function (name, handler) {
169
+ if (name && typeof name === 'string' && handler && typeof handler === 'function') {
170
+ this.handlers[name] = handler;
171
+ }
172
+
173
+ // return this for chaining
174
+ return this;
175
+ };
176
+
177
+ /*
178
+ * @public
179
+ * Registers a conditional for a custom 'depends' rule
180
+ */
181
+
182
+ FormValidator.prototype.registerConditional = function (name, conditional) {
183
+ if (name && typeof name === 'string' && conditional && typeof conditional === 'function') {
184
+ this.conditionals[name] = conditional;
185
+ }
186
+
187
+ // return this for chaining
188
+ return this;
189
+ };
190
+
191
+ /*
192
+ * @private
193
+ * Determines if a form dom node was passed in or just a string representing the form name
194
+ */
195
+
196
+ FormValidator.prototype._formByNameOrNode = function (formNameOrNode) {
197
+ return _typeof(formNameOrNode) === 'object' ? formNameOrNode : document.forms[formNameOrNode];
198
+ };
199
+
200
+ /*
201
+ * @private
202
+ * Adds a file to the master fields array
203
+ */
204
+
205
+ FormValidator.prototype._addField = function (field, nameValue) {
206
+ this.fields[nameValue] = {
207
+ name: nameValue,
208
+ display: field.display || nameValue,
209
+ rules: field.rules,
210
+ depends: field.depends,
211
+ id: null,
212
+ element: null,
213
+ type: null,
214
+ value: null,
215
+ checked: null
216
+ };
217
+ };
218
+
219
+ /*
220
+ * @private
221
+ * Runs the validation when the form is submitted.
222
+ */
223
+
224
+ FormValidator.prototype._validateForm = function (evt) {
225
+ this.errors = [];
226
+ for (var key in this.fields) {
227
+ if (this.fields.hasOwnProperty(key)) {
228
+ var field = this.fields[key] || {};
229
+ var element = this.form.querySelectorAll('[name=' + field.name + ']'); //this.form[field.name];
230
+ if (element.length === 1) {
231
+ element = element[0];
232
+ }
233
+ if (element && element !== undefined) {
234
+ field.element = element;
235
+ field.type = element.length > 0 ? element[0].type : element.type;
236
+ field.id = attributeValue(element, 'id');
237
+ field.value = attributeValue(element, 'value');
238
+ field.checked = attributeValue(element, 'checked');
239
+
240
+ /*
241
+ * Run through the rules for each field.
242
+ * If the field has a depends conditional, only validate the field
243
+ * if it passes the custom function
244
+ */
245
+
246
+ if (field.depends && typeof field.depends === "function") {
247
+ if (field.depends.call(this, field)) {
248
+ this._validateField(field);
249
+ }
250
+ } else if (field.depends && typeof field.depends === "string" && this.conditionals[field.depends]) {
251
+ if (this.conditionals[field.depends].call(this, field)) {
252
+ this._validateField(field);
253
+ }
254
+ } else {
255
+ this._validateField(field);
256
+ }
257
+ }
258
+ }
259
+ }
260
+ if (typeof this.callback === 'function') {
261
+ this.callback(this.errors, evt);
262
+ }
263
+ if (this.errors.length > 0) {
264
+ if (evt && evt.preventDefault) {
265
+ evt.preventDefault();
266
+ return false;
267
+ } else if (event) {
268
+ // IE uses the global event variable
269
+ event.returnValue = false;
270
+ }
271
+ }
272
+ return true;
273
+ };
274
+
275
+ /*
276
+ * @private
277
+ * Looks at the fields value and evaluates it against the given rules
278
+ */
279
+
280
+ FormValidator.prototype._validateField = function (field) {
281
+ var rules = field.rules.split('|'),
282
+ indexOfRequired = field.rules.indexOf('required'),
283
+ isEmpty = !field.value || field.value === '' || field.value === undefined;
284
+
285
+ /*
286
+ * Run through the rules and execute the validation methods as needed
287
+ */
288
+
289
+ for (var i = 0, ruleLength = rules.length; i < ruleLength; i++) {
290
+ var method = rules[i],
291
+ param = null,
292
+ failed = false,
293
+ parts = ruleRegex.exec(method);
294
+
295
+ /*
296
+ * If this field is not required and the value is empty, continue on to the next rule unless it's a callback.
297
+ * This ensures that a callback will always be called but other rules will be skipped.
298
+ */
299
+
300
+ if (indexOfRequired === -1 && method.indexOf('!callback_') === -1 && isEmpty) {
301
+ continue;
302
+ }
303
+
304
+ /*
305
+ * If the rule has a parameter (i.e. matches[param]) split it out
306
+ */
307
+
308
+ if (parts) {
309
+ method = parts[1];
310
+ param = parts[2];
311
+ }
312
+ if (method.charAt(0) === '!') {
313
+ method = method.substring(1, method.length);
314
+ }
315
+
316
+ /*
317
+ * If the hook is defined, run it to find any validation errors
318
+ */
319
+
320
+ if (typeof this._hooks[method] === 'function') {
321
+ if (!this._hooks[method].apply(this, [field, param])) {
322
+ failed = true;
323
+ }
324
+ } else if (method.substring(0, 9) === 'callback_') {
325
+ // Custom method. Execute the handler if it was registered
326
+ method = method.substring(9, method.length);
327
+ if (typeof this.handlers[method] === 'function') {
328
+ if (this.handlers[method].apply(this, [field.value, param, field]) === false) {
329
+ failed = true;
330
+ }
331
+ }
332
+ }
333
+
334
+ /*
335
+ * If the hook failed, add a message to the errors array
336
+ */
337
+
338
+ if (failed) {
339
+ // Make sure we have a message for this rule
340
+ var source = this.messages[field.name + '.' + method] || this.messages[method] || defaults.messages[method],
341
+ message = 'An error has occurred with the ' + field.display + ' field.';
342
+ if (source) {
343
+ message = source.replace('%s', field.display);
344
+ if (param) {
345
+ message = message.replace('%s', this.fields[param] ? this.fields[param].display : param);
346
+ }
347
+ }
348
+ this.errors.push({
349
+ id: field.id,
350
+ element: field.element,
351
+ name: field.name,
352
+ message: message,
353
+ rule: method
354
+ });
355
+
356
+ // Break out so as to not spam with validation errors (i.e. required and valid_email)
357
+ break;
358
+ }
359
+ }
360
+ };
361
+
362
+ /*
363
+ * @private
364
+ * Object containing all of the validation hooks
365
+ */
366
+
367
+ FormValidator.prototype._hooks = {
368
+ required: function required(field) {
369
+ var value = field.value;
370
+ if (field.type === 'checkbox' || field.type === 'radio') {
371
+ return field.checked === true;
372
+ }
373
+ return value !== null && value !== '';
374
+ },
375
+ "default": function _default(field, defaultName) {
376
+ return field.value !== defaultName;
377
+ },
378
+ matches: function matches(field, matchName) {
379
+ var el = this.form[matchName];
380
+ if (el) {
381
+ return field.value === el.value;
382
+ }
383
+ return false;
384
+ },
385
+ valid_email: function valid_email(field) {
386
+ return emailRegex.test(field.value);
387
+ },
388
+ valid_emails: function valid_emails(field) {
389
+ var result = field.value.split(",");
390
+ for (var i = 0, resultLength = result.length; i < resultLength; i++) {
391
+ if (!emailRegex.test(result[i])) {
392
+ return false;
393
+ }
394
+ }
395
+ return true;
396
+ },
397
+ min_length: function min_length(field, length) {
398
+ if (!numericRegex.test(length)) {
399
+ return false;
400
+ }
401
+ return field.value.length >= parseInt(length, 10);
402
+ },
403
+ max_length: function max_length(field, length) {
404
+ if (!numericRegex.test(length)) {
405
+ return false;
406
+ }
407
+ return field.value.length <= parseInt(length, 10);
408
+ },
409
+ exact_length: function exact_length(field, length) {
410
+ if (!numericRegex.test(length)) {
411
+ return false;
412
+ }
413
+ return field.value.length === parseInt(length, 10);
414
+ },
415
+ greater_than: function greater_than(field, param) {
416
+ if (!decimalRegex.test(field.value)) {
417
+ return false;
418
+ }
419
+ return parseFloat(field.value) > parseFloat(param);
420
+ },
421
+ less_than: function less_than(field, param) {
422
+ if (!decimalRegex.test(field.value)) {
423
+ return false;
424
+ }
425
+ return parseFloat(field.value) < parseFloat(param);
426
+ },
427
+ alpha: function alpha(field) {
428
+ return alphaRegex.test(field.value);
429
+ },
430
+ alpha_numeric: function alpha_numeric(field) {
431
+ return alphaNumericRegex.test(field.value);
432
+ },
433
+ alpha_dash: function alpha_dash(field) {
434
+ return alphaDashRegex.test(field.value);
435
+ },
436
+ numeric: function numeric(field) {
437
+ return numericRegex.test(field.value);
438
+ },
439
+ integer: function integer(field) {
440
+ return integerRegex.test(field.value);
441
+ },
442
+ decimal: function decimal(field) {
443
+ return decimalRegex.test(field.value);
444
+ },
445
+ is_natural: function is_natural(field) {
446
+ return naturalRegex.test(field.value);
447
+ },
448
+ is_natural_no_zero: function is_natural_no_zero(field) {
449
+ return naturalNoZeroRegex.test(field.value);
450
+ },
451
+ valid_ip: function valid_ip(field) {
452
+ return ipRegex.test(field.value);
453
+ },
454
+ valid_base64: function valid_base64(field) {
455
+ return base64Regex.test(field.value);
456
+ },
457
+ valid_url: function valid_url(field) {
458
+ return urlRegex.test(field.value);
459
+ },
460
+ valid_credit_card: function valid_credit_card(field) {
461
+ // Luhn Check Code from https://gist.github.com/4075533
462
+ // accept only digits, dashes or spaces
463
+ if (!numericDashRegex.test(field.value)) return false;
464
+
465
+ // The Luhn Algorithm. It's so pretty.
466
+ var nCheck = 0,
467
+ nDigit = 0,
468
+ bEven = false;
469
+ var strippedField = field.value.replace(/\D/g, "");
470
+ for (var n = strippedField.length - 1; n >= 0; n--) {
471
+ var cDigit = strippedField.charAt(n);
472
+ nDigit = parseInt(cDigit, 10);
473
+ if (bEven) {
474
+ if ((nDigit *= 2) > 9) nDigit -= 9;
475
+ }
476
+ nCheck += nDigit;
477
+ bEven = !bEven;
478
+ }
479
+ return nCheck % 10 === 0;
480
+ },
481
+ is_file_type: function is_file_type(field, type) {
482
+ if (field.type !== 'file') {
483
+ return true;
484
+ }
485
+ var ext = field.value.substr(field.value.lastIndexOf('.') + 1),
486
+ typeArray = type.split(','),
487
+ inArray = false,
488
+ i = 0,
489
+ len = typeArray.length;
490
+ for (i; i < len; i++) {
491
+ if (ext === typeArray[i]) inArray = true;
492
+ }
493
+ return inArray;
494
+ }
495
+ };
496
+ window.FormValidator = FormValidator;
497
+ })(window, document);
498
+ var validateSettings = [{
499
+ setting: "content",
500
+ isRequired: true,
501
+ validate: "type",
502
+ possibleValues: ["string", "object"],
503
+ errorMessage: ["GDK ValidateForm : Content must be defined and set to a DOM selector or Node"]
504
+ }];
505
+ var ValidateForm = /*#__PURE__*/function () {
506
+ // 1. All input fields need error styling, if there is a server error on fields we are not directly validating
507
+ // 2. Numbers -- needs to be a number and if required
508
+ // 3. Email -- needs to be a email and if required
509
+ // 4. Phone Number -- needs match exact phone number pattern "(804) 341-3525"
510
+ // 5. SSN -- validate the hidden field needs match exact ssn pattern "123-12-4124"
511
+ // 6. Select Box -- if required
512
+ // 7. Checkbox -- if required
513
+ // 8. Radio Buttons -- if required
514
+ // 9. Text area -- if required
515
+
516
+ /**
517
+ * These are settings for the instantiation. Refer to the design kit section of this component for JS setting examples.
518
+ * @param {string|Object} options
519
+ * A reference to the html form container
520
+ */
521
+ function ValidateForm(options) {
522
+ _classCallCheck(this, ValidateForm);
523
+ console.log("Initialized the ValidateForm component");
524
+ this._internalVars = {
525
+ node: null //used for content item
526
+ };
527
+
528
+ //options with defaults set
529
+ this._defaults = {};
530
+
531
+ // Create options by extending defaults with the passed in arguments
532
+ if (options && _typeof(options) === "object") {
533
+ this._options = _baseComponent["default"].extendDefaults(this._defaults, options);
534
+ }
535
+
536
+ // From the passed in CSS selector iterate over each form and build validation rules and events
537
+ this._forms = document.querySelectorAll(options.content);
538
+ this._validators = [];
539
+ this._rules = [];
540
+ for (var n = 0; this._forms.length > n; n++) {
541
+ // Initialize the form
542
+ initializeForm.call(this, n);
543
+ }
544
+
545
+ //if the required options are valid set up the environment
546
+ if (_baseComponent["default"].validateSettings(this._options, validateSettings)) {
547
+ this._internalVars.contentType = _baseComponent["default"].getContentType(this);
548
+ setLocalVars.call(this);
549
+ setEvents.call(this);
550
+ }
551
+ }
552
+
553
+ //Public Methods
554
+
555
+ /**
556
+ * removes the node from the dom and any events attached
557
+ */
558
+ return _createClass(ValidateForm, [{
559
+ key: "destroy",
560
+ value: function destroy() {
561
+ removeEvents.call(this);
562
+ this._internalVars.node.parentNode.removeChild(this._internalVars.node);
563
+
564
+ //a little garbage collection
565
+ for (var variableKey in this) {
566
+ if (this.hasOwnProperty(variableKey)) {
567
+ delete this[variableKey];
568
+ }
569
+ }
570
+ }
571
+ }]);
572
+ }(); // Private Methods
573
+ /**
574
+ * Initialize the form
575
+ */
576
+ function initializeForm(n) {
577
+ return function (that, n) {
578
+ that._rules[n] = buildRules(that._forms[n]);
579
+ that._validators[n] = new FormValidator(that._forms[n],
580
+ // Built dynamically via data attributes
581
+ that._rules[n],
582
+ // Callback on each validation pass blur or submit
583
+ function (errors, evt) {
584
+ // Clear any old errors
585
+ var wrappers = this.form.querySelectorAll('[class=form-field]');
586
+ for (var j = 0; wrappers.length > j; j++) {
587
+ // clear all field errors and reset the error class on wrapper
588
+ clearFieldError(wrappers[j]);
589
+ }
590
+
591
+ // Handle displaying any errors in the form
592
+ if (errors.length > 0) {
593
+ // add error classes to appropriate elements
594
+ for (var i = 0; errors.length > i; i++) {
595
+ var element = this.form.querySelectorAll('[name=' + errors[i].name + ']')[0];
596
+
597
+ // get this field's wrapper
598
+ var field_wrapper = closest(element, "form-field");
599
+
600
+ // Create and append the error message
601
+ addFieldError(field_wrapper, errors[i].message);
602
+ }
603
+ }
604
+ });
605
+
606
+ // Extend validation class
607
+ extendValidator(that._validators[n]);
608
+ }(this, n);
609
+ }
610
+ function addBlur(validator, element) {
611
+ return function (that, element) {
612
+ return function (evt) {
613
+ var field = that.fields[element.getAttribute('name')] || {};
614
+ if (element && element !== undefined) {
615
+ field.element = element;
616
+ field.id = element.getAttribute('id');
617
+ field.name = element.getAttribute('name');
618
+ field.type = element.length > 0 ? element[0].type : element.type;
619
+ field.value = element.value;
620
+ field.checked = element.checked;
621
+
622
+ // clear any errors relating to this field
623
+ if (that.errors.length > 0) {
624
+ for (var i = 0; that.errors.length > i; i++) {
625
+ if (that.errors[i].name === field.name) {
626
+ // splice don't delete
627
+ that.errors.splice(i, 1);
628
+ }
629
+ }
630
+ }
631
+
632
+ // get this field's wrapper
633
+ var field_wrapper = closest(element, "form-field");
634
+
635
+ // clear all field errors and reset the error class on wrapper
636
+ clearFieldError(field_wrapper);
637
+
638
+ // validate this field
639
+ that.errors = [];
640
+ that._validateField(field);
641
+
642
+ // Handle displaying any errors in the form
643
+ if (that.errors.length > 0) {
644
+ // add error classes to appropriate elements
645
+ for (var j = 0; that.errors.length > j; j++) {
646
+ // get this field's wrapper
647
+ field_wrapper = closest(that.errors[j].element, "form-field");
648
+
649
+ // Create and append the error message
650
+ addFieldError(field_wrapper, that.errors[j].message);
651
+ }
652
+ }
653
+ }
654
+ };
655
+ }(validator, element);
656
+ }
657
+
658
+ /**
659
+ * setEvents()
660
+ * Sets all the events needed for the component
661
+ */
662
+ function setEvents() {
663
+ // Go through each form's rulesets
664
+ for (var n = 0; this._rules.length > n; n++) {
665
+ // Go through each ruleset
666
+ for (var e = 0; this._rules[n].length > e; e++) {
667
+ // pull out the element
668
+ var element = this._rules[n][e].element;
669
+ if (element.type === 'checkbox' || element.type === 'radio') {
670
+ // Add an onchange event
671
+ element.onchange = addBlur(this._validators[n], element);
672
+ } else {
673
+ // Add an onblur event
674
+ element.onblur = addBlur(this._validators[n], element);
675
+ }
676
+ }
677
+ }
678
+ }
679
+
680
+ /**
681
+ * removeEvents()
682
+ * removes all events from the component
683
+ */
684
+ function removeEvents() {}
685
+
686
+ /**
687
+ * buildRules()
688
+ * builds an array of validation rules based on the DOM attributes
689
+ */
690
+ function buildRules(form) {
691
+ form = _typeof(form) === 'object' ? form : document.forms[form];
692
+ var elements = form.querySelectorAll('[data-validate]');
693
+ var rules = [];
694
+ var unique_rules = [];
695
+ for (var i = 0; elements.length > i; i++) {
696
+ // set up a rule for this element
697
+ var rule = {
698
+ rules: elements[i].getAttribute("data-validate"),
699
+ element: elements[i],
700
+ name: elements[i].getAttribute("name")
701
+ };
702
+ if (!rule.name) {
703
+ console.log("Warning: Field element missing name attribute.", rule.element);
704
+ }
705
+
706
+ // Add rule to the list
707
+ rules.push(rule);
708
+ }
709
+ return rules;
710
+ }
711
+
712
+ /**
713
+ * Find the closest parent containing a class
714
+ */
715
+ function closest(el, cls) {
716
+ while ((el = el.parentNode) && -1 === el.className.indexOf(cls));
717
+ return el;
718
+ }
719
+
720
+ /**
721
+ * Add an error message to an element
722
+ */
723
+ function addFieldError(wrapper, error) {
724
+ // Make sure the wrapper has the error class
725
+ if (-1 === wrapper.className.indexOf("form-field--error")) {
726
+ wrapper.className = wrapper.className + " form-field--error";
727
+ }
728
+ if (wrapper.querySelector('input')) wrapper.querySelector('input').setAttribute("aria-invalid", "true");
729
+ if (wrapper.querySelector('textarea')) wrapper.querySelector('textarea').setAttribute("aria-invalid", "true");
730
+ if (wrapper.querySelector('select')) wrapper.querySelector('select').setAttribute("aria-invalid", "true");
731
+
732
+ // Get all spans and check ones bearing class "form-message"
733
+ var spans = wrapper.getElementsByTagName('span');
734
+ for (var e = 0; spans.length > e; e++) {
735
+ // Somewhat of a hack to do element content comparison when
736
+ // browsers render inner tags differently
737
+ var comparison_div = document.createElement("div");
738
+ comparison_div.innerHTML = error;
739
+
740
+ // If the discovered span is a message and contains the same text as the error var
741
+ if (-1 !== spans[e].className.indexOf("form-message") && spans[e].innerHTML === comparison_div.innerHTML) {
742
+ // Don't add the same message to a wrapper twice
743
+ return;
744
+ }
745
+ }
746
+
747
+ // Add an error to the element wrapper
748
+ var msg = document.createElement("span");
749
+ msg.id = "form-message-" + wrapper.querySelector('[data-validate]').id;
750
+ msg.innerHTML = error;
751
+ msg.className = "form-message";
752
+ var idString = "";
753
+ wrapper.appendChild(msg);
754
+ if (wrapper.querySelector('.form-descriptive-copy')) {
755
+ idString = wrapper.querySelector('.form-descriptive-copy').id + " " + msg.id;
756
+ } else {
757
+ idString = msg.id;
758
+ }
759
+ wrapper.querySelector('[data-validate]').setAttribute('aria-describedby', idString);
760
+ }
761
+
762
+ /**
763
+ * Remove field errors from an element
764
+ */
765
+ function clearFieldError(wrapper) {
766
+ // remove error class from wrapper
767
+ if (-1 !== wrapper.className.indexOf("form-field--error")) {
768
+ wrapper.className = wrapper.className.replace("form-field--error", "");
769
+ }
770
+ if (wrapper.querySelector('input')) wrapper.querySelector('input').setAttribute("aria-invalid", "false");
771
+ if (wrapper.querySelector('textarea')) wrapper.querySelector('textarea').setAttribute("aria-invalid", "false");
772
+ if (wrapper.querySelector('select')) wrapper.querySelector('select').setAttribute("aria-invalid", "false");
773
+ // Get all spans and remove ones bearing class "form-message"
774
+ var spans = wrapper.getElementsByTagName('span');
775
+ for (var e = 0; spans.length > e; e++) {
776
+ if (-1 !== spans[e].className.indexOf("form-message")) {
777
+ spans[e].parentNode.removeChild(spans[e]);
778
+ }
779
+ }
780
+ wrapper.querySelector('[data-validate]').removeAttribute('aria-describedby');
781
+ }
782
+
783
+ /**
784
+ * Attach additional validator rules to validator objects
785
+ */
786
+ function extendValidator(validator) {
787
+ // custom validators
788
+ validator.registerCallback('ssn', function (value, masked_ssn_id) {
789
+ // get the masked SSN
790
+ var masked_ssn = document.getElementById(masked_ssn_id);
791
+ // Test to see if the masked SSN is valid: '###-##-####'
792
+ // var ssn_regex = /^\d{3}-?\d{2}-?\d{4}$/;
793
+ var ssn_regex = /^(?!219-09-9999|078-05-1120)(?!666|000|9\d{2})\d{3}-(?!00)\d{2}-(?!0{4})\d{4}$/;
794
+ return ssn_regex.test(masked_ssn.value);
795
+ });
796
+ validator.registerCallback('phone', function (value) {
797
+ // Test to see if the Phone is valid: '(###) ###-####'
798
+ var phone_regex = /^([\(]{1}[0-9]{3}[\)]{1}[ ]?[0-9]{3}[\-]{1}[0-9]{4})$/;
799
+ return phone_regex.test(value);
800
+ });
801
+ validator.registerCallback('date', function (value) {
802
+ // Test to see if the Date is valid: '##/##/####'
803
+ var date_regex = /^((0[1-9])|(1[0-2]))[\/]((0[1-9])|([1,2][0-9])|(3[0,1]))[\/]((19|20)[0-9][0-9])$/;
804
+ if (date_regex.test(value)) {
805
+ var date_parts = value.split("/");
806
+ // check to see if the month is still the correct month after
807
+ // casting the date string to a date, This works because if a
808
+ // day is past the last day of the month the JS Date object
809
+ // advances the number of days past the month's end into the
810
+ // next month.
811
+ return new Date(date_parts[2], parseInt(date_parts[0]) - 1, date_parts[1]).getMonth() === parseInt(date_parts[0]) - 1;
812
+ }
813
+ return false;
814
+ });
815
+ validator.registerCallback('date_short', function (value) {
816
+ // Test to see if the Date is valid: '##/####'
817
+ var date_regex = /^((0[1-9])|(1[0-2]))[\/]((19|20)[0-9][0-9])$/;
818
+ return date_regex.test(value);
819
+ });
820
+
821
+ // set variables for regex
822
+ var today = new Date();
823
+ var currentYear = today.getFullYear();
824
+ currentYear = currentYear.toString();
825
+ var twoDigitYear = currentYear.slice(-2);
826
+ var lastYearDigit = twoDigitYear.slice(1);
827
+ var datePatternStart;
828
+ var dateCurrentYear;
829
+ var datePatternEnd;
830
+ if (twoDigitYear < 20) {
831
+ datePatternStart = '^((0[1-9])|(1[0-2]))[\\/](';
832
+ dateCurrentYear = '(1[' + lastYearDigit + '-9])|';
833
+ datePatternEnd = '([2-9][0-9]))$';
834
+ } else {
835
+ datePatternStart = '^((0[1-9])|(1[0-2]))[\\/](';
836
+ dateCurrentYear = '';
837
+ datePatternEnd = '([2-9][0-9]))$';
838
+ }
839
+ validator.registerCallback('date_short_year', function (value) {
840
+ // Test to see if the Date is valid: '##/##'
841
+ var date_regex = new RegExp(datePatternStart + dateCurrentYear + datePatternEnd);
842
+ return date_regex.test(value);
843
+ });
844
+ validator.registerCallback('radio_required', function (value, element_name) {
845
+ // See if there are any checked input elements matching the element name passed in
846
+ var radio = this.form.querySelectorAll('input[name="' + element_name + '"]:checked');
847
+ return radio.length > 0;
848
+ });
849
+ validator.registerCallback('checkbox_required', function (value, element_name) {
850
+ // See if there are any checked input elements matching the element name passed in
851
+ var cb = this.form.querySelectorAll('input[name="' + element_name + '"]:checked');
852
+ return cb.length > 0;
853
+ });
854
+ validator.registerCallback('select_required', function (value, select_id) {
855
+ // See if there are any selected option elements under the provided select
856
+ var select_element = document.getElementById(select_id);
857
+ if (select_element.options[select_element.selectedIndex] !== undefined) {
858
+ // overwrite the "value" passed into this validator
859
+ value = select_element.options[select_element.selectedIndex].value;
860
+ if (value !== undefined && value) {
861
+ return true;
862
+ }
863
+ }
864
+ return false;
865
+ });
866
+ validator.registerCallback('timeInput', function (value, masked_timeInput_id) {
867
+ // get the masked timeInput
868
+ var masked_timeInput = document.getElementById(masked_timeInput_id),
869
+ timeInput_regex = /^(0?[1-9]|1[012]):[0-5][0-9]$/,
870
+ timeInputValue = masked_timeInput.value,
871
+ initialHour,
872
+ minutes;
873
+ if (timeInputValue.length === 5) {
874
+ initialHour = timeInputValue.substring(2, 0);
875
+ minutes = timeInputValue.substring(3);
876
+ if (initialHour > 12 && initialHour < 24) {
877
+ initialHour = initialHour - 12;
878
+ setTime.call(this, masked_timeInput, initialHour, minutes);
879
+ }
880
+ if (initialHour < 1) {
881
+ initialHour = 12;
882
+ setTime.call(this, masked_timeInput, initialHour, minutes);
883
+ }
884
+ }
885
+ return timeInput_regex.test(masked_timeInput.value);
886
+ });
887
+ validator.registerCallback('validateZipCode', function (value) {
888
+ var zipCodePattern = /^\d{5}$/;
889
+ return zipCodePattern.test(value);
890
+ });
891
+ validator.registerCallback('validateZipPlus4', function (value) {
892
+ var zipCodePattern = /^\d{5}-\d{4}$/;
893
+ return value.match('_____-____') || zipCodePattern.test(value);
894
+ });
895
+ function setTime(masked_timeInput, initialHour, minutes) {
896
+ var numHour, newValue, hour;
897
+ numHour = String(initialHour);
898
+ if (numHour.length < 2) {
899
+ hour = '0' + numHour;
900
+ } else {
901
+ hour = numHour;
902
+ }
903
+ Number(hour);
904
+ Number(initialHour);
905
+ newValue = hour + ':' + minutes;
906
+ masked_timeInput.value = newValue;
907
+ }
908
+
909
+ // Custom validation messages
910
+ validator.setMessage('required', 'Invalid entry.<br> Please check your entry and try again.');
911
+ validator.setMessage('numeric', 'Invalid entry.<br> Please check your entry and try again.');
912
+ validator.setMessage('ssn', 'Please enter a valid Social Security Number.');
913
+ validator.setMessage('phone', 'Please enter a valid Phone Number.');
914
+ validator.setMessage('radio_required', 'Please make a selection.');
915
+ validator.setMessage('checkbox_required', 'Please make a selection.');
916
+ validator.setMessage('select_required', 'Please make a selection.');
917
+ validator.setMessage('valid_email', "Invalid email.<br> Please check your entry and try again.");
918
+ validator.setMessage('date', "Invalid date format.<br> Please check your entry and try again.");
919
+ validator.setMessage('date_short', "Invalid date format.<br> Please check your entry and try again.");
920
+ validator.setMessage('timeInput', 'Please enter a valid time of day.');
921
+ validator.setMessage('date_short_year', "Invalid date format.<br> Please check your entry and try again.");
922
+ validator.setMessage('validateZipCode', "Please enter a valid<br/>zip code.");
923
+ validator.setMessage('validateZipPlus4', "Please enter a valid<br/>zip code.");
924
+ }
925
+
926
+ /**
927
+ * setLocalVars()
928
+ * set all the local vars to passed in options
929
+ */
930
+ function setLocalVars() {
931
+ //determine the type of content passed in
932
+ if (this._internalVars.contentType === 'string') {
933
+ this._internalVars.node = document.querySelector(this._options.content);
934
+ } else if (this._internalVars.contentType === 'domNode') {
935
+ this._internalVars.node = this._options.content;
936
+ }
937
+ }
938
+ var _default2 = exports["default"] = ValidateForm;