govuk_publishing_components 34.7.0 → 34.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-event-tracker.js +3 -10
  3. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-form-tracker.js +113 -0
  4. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-link-tracker.js +2 -11
  5. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-schemas.js +15 -1
  6. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-specialist-link-tracker.js +20 -29
  7. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4.js +1 -0
  8. data/app/models/govuk_publishing_components/component_doc.rb +14 -0
  9. data/app/models/govuk_publishing_components/component_wrapper_helper_options.rb +14 -0
  10. data/app/views/govuk_publishing_components/component_guide/show.html.erb +21 -6
  11. data/app/views/govuk_publishing_components/components/_action_link.html.erb +5 -2
  12. data/app/views/govuk_publishing_components/components/_breadcrumbs.html.erb +6 -2
  13. data/app/views/govuk_publishing_components/components/_details.html.erb +3 -1
  14. data/app/views/govuk_publishing_components/components/docs/action_link.yml +1 -0
  15. data/app/views/govuk_publishing_components/components/docs/breadcrumbs.yml +1 -0
  16. data/app/views/govuk_publishing_components/components/docs/details.yml +17 -0
  17. data/lib/govuk_publishing_components/presenters/component_wrapper_helper.rb +78 -0
  18. data/lib/govuk_publishing_components/presenters/related_navigation_helper.rb +0 -7
  19. data/lib/govuk_publishing_components/version.rb +1 -1
  20. data/lib/govuk_publishing_components.rb +1 -0
  21. data/node_modules/govuk-frontend/govuk/all.js +4029 -3792
  22. data/node_modules/govuk-frontend/govuk/all.js.map +1 -0
  23. data/node_modules/govuk-frontend/govuk/common/closest-attribute-value.js +52 -51
  24. data/node_modules/govuk-frontend/govuk/common/closest-attribute-value.js.map +1 -0
  25. data/node_modules/govuk-frontend/govuk/common/index.js +153 -145
  26. data/node_modules/govuk-frontend/govuk/common/index.js.map +1 -0
  27. data/node_modules/govuk-frontend/govuk/common/normalise-dataset.js +324 -321
  28. data/node_modules/govuk-frontend/govuk/common/normalise-dataset.js.map +1 -0
  29. data/node_modules/govuk-frontend/govuk/common.js +154 -146
  30. data/node_modules/govuk-frontend/govuk/common.js.map +1 -0
  31. data/node_modules/govuk-frontend/govuk/components/_all.scss +1 -1
  32. data/node_modules/govuk-frontend/govuk/components/accordion/_index.scss +23 -4
  33. data/node_modules/govuk-frontend/govuk/components/accordion/accordion.js +2059 -1654
  34. data/node_modules/govuk-frontend/govuk/components/accordion/accordion.js.map +1 -0
  35. data/node_modules/govuk-frontend/govuk/components/accordion/fixtures.json +11 -11
  36. data/node_modules/govuk-frontend/govuk/components/accordion/template.njk +1 -1
  37. data/node_modules/govuk-frontend/govuk/components/back-link/_index.scss +19 -19
  38. data/node_modules/govuk-frontend/govuk/components/breadcrumbs/_index.scss +21 -10
  39. data/node_modules/govuk-frontend/govuk/components/button/button.js +927 -917
  40. data/node_modules/govuk-frontend/govuk/components/button/button.js.map +1 -0
  41. data/node_modules/govuk-frontend/govuk/components/character-count/character-count.js +2050 -2040
  42. data/node_modules/govuk-frontend/govuk/components/character-count/character-count.js.map +1 -0
  43. data/node_modules/govuk-frontend/govuk/components/checkboxes/checkboxes.js +1155 -1147
  44. data/node_modules/govuk-frontend/govuk/components/checkboxes/checkboxes.js.map +1 -0
  45. data/node_modules/govuk-frontend/govuk/components/cookie-banner/fixtures.json +23 -23
  46. data/node_modules/govuk-frontend/govuk/components/cookie-banner/template.njk +1 -1
  47. data/node_modules/govuk-frontend/govuk/components/details/details.js +800 -799
  48. data/node_modules/govuk-frontend/govuk/components/details/details.js.map +1 -0
  49. data/node_modules/govuk-frontend/govuk/components/error-summary/error-summary.js +1058 -1045
  50. data/node_modules/govuk-frontend/govuk/components/error-summary/error-summary.js.map +1 -0
  51. data/node_modules/govuk-frontend/govuk/components/header/_index.scss +6 -0
  52. data/node_modules/govuk-frontend/govuk/components/header/header.js +646 -998
  53. data/node_modules/govuk-frontend/govuk/components/header/header.js.map +1 -0
  54. data/node_modules/govuk-frontend/govuk/components/notification-banner/notification-banner.js +760 -752
  55. data/node_modules/govuk-frontend/govuk/components/notification-banner/notification-banner.js.map +1 -0
  56. data/node_modules/govuk-frontend/govuk/components/pagination/fixtures.json +61 -0
  57. data/node_modules/govuk-frontend/govuk/components/pagination/template.njk +1 -1
  58. data/node_modules/govuk-frontend/govuk/components/phase-banner/macro-options.json +1 -1
  59. data/node_modules/govuk-frontend/govuk/components/radios/radios.js +1110 -1107
  60. data/node_modules/govuk-frontend/govuk/components/radios/radios.js.map +1 -0
  61. data/node_modules/govuk-frontend/govuk/components/skip-link/skip-link.js +1017 -1014
  62. data/node_modules/govuk-frontend/govuk/components/skip-link/skip-link.js.map +1 -0
  63. data/node_modules/govuk-frontend/govuk/components/summary-list/_index.scss +107 -0
  64. data/node_modules/govuk-frontend/govuk/components/summary-list/fixtures.json +318 -23
  65. data/node_modules/govuk-frontend/govuk/components/summary-list/macro-options.json +110 -0
  66. data/node_modules/govuk-frontend/govuk/components/summary-list/template.njk +72 -28
  67. data/node_modules/govuk-frontend/govuk/components/tabs/tabs.js +1392 -1264
  68. data/node_modules/govuk-frontend/govuk/components/tabs/tabs.js.map +1 -0
  69. data/node_modules/govuk-frontend/govuk/i18n.js +363 -364
  70. data/node_modules/govuk-frontend/govuk/i18n.js.map +1 -0
  71. data/node_modules/govuk-frontend/govuk/settings/_measurements.scss +5 -5
  72. data/node_modules/govuk-frontend/govuk/vendor/polyfills/DOMTokenList.js +242 -241
  73. data/node_modules/govuk-frontend/govuk/vendor/polyfills/DOMTokenList.js.map +1 -0
  74. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Date/now.js +13 -12
  75. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Date/now.js.map +1 -0
  76. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Document.js +17 -16
  77. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Document.js.map +1 -0
  78. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/classList.js +547 -546
  79. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/classList.js.map +1 -0
  80. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/closest.js +37 -36
  81. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/closest.js.map +1 -0
  82. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/dataset.js +251 -250
  83. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/dataset.js.map +1 -0
  84. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/matches.js +21 -20
  85. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/matches.js.map +1 -0
  86. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/nextElementSibling.js +198 -197
  87. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/nextElementSibling.js.map +1 -0
  88. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/previousElementSibling.js +198 -197
  89. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/previousElementSibling.js.map +1 -0
  90. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element.js +106 -105
  91. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element.js.map +1 -0
  92. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Event.js +400 -399
  93. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Event.js.map +1 -0
  94. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Function/prototype/bind.js +239 -238
  95. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Function/prototype/bind.js.map +1 -0
  96. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Object/defineProperty.js +72 -71
  97. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Object/defineProperty.js.map +1 -0
  98. data/node_modules/govuk-frontend/govuk/vendor/polyfills/String/prototype/trim.js +14 -13
  99. data/node_modules/govuk-frontend/govuk/vendor/polyfills/String/prototype/trim.js.map +1 -0
  100. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Window.js +17 -16
  101. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Window.js.map +1 -0
  102. data/node_modules/govuk-frontend/govuk-esm/all.mjs +2 -2
  103. data/node_modules/govuk-frontend/govuk-esm/common/index.mjs +17 -10
  104. data/node_modules/govuk-frontend/govuk-esm/common/normalise-dataset.mjs +3 -1
  105. data/node_modules/govuk-frontend/govuk-esm/components/accordion/accordion.mjs +135 -52
  106. data/node_modules/govuk-frontend/govuk-esm/components/button/button.mjs +11 -9
  107. data/node_modules/govuk-frontend/govuk-esm/components/character-count/character-count.mjs +10 -7
  108. data/node_modules/govuk-frontend/govuk-esm/components/checkboxes/checkboxes.mjs +24 -18
  109. data/node_modules/govuk-frontend/govuk-esm/components/details/details.mjs +23 -16
  110. data/node_modules/govuk-frontend/govuk-esm/components/error-summary/error-summary.mjs +15 -11
  111. data/node_modules/govuk-frontend/govuk-esm/components/header/header.mjs +3 -2
  112. data/node_modules/govuk-frontend/govuk-esm/components/notification-banner/notification-banner.mjs +3 -4
  113. data/node_modules/govuk-frontend/govuk-esm/components/radios/radios.mjs +10 -9
  114. data/node_modules/govuk-frontend/govuk-esm/components/skip-link/skip-link.mjs +5 -3
  115. data/node_modules/govuk-frontend/govuk-esm/components/tabs/tabs.mjs +165 -38
  116. data/node_modules/govuk-frontend/govuk-esm/i18n.mjs +9 -11
  117. data/node_modules/govuk-frontend/package.json +1 -1
  118. metadata +37 -2
@@ -1,1136 +1,1149 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
3
- typeof define === 'function' && define.amd ? define('GOVUKFrontend.ErrorSummary', factory) :
4
- (global.GOVUKFrontend = global.GOVUKFrontend || {}, global.GOVUKFrontend.ErrorSummary = factory());
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
3
+ typeof define === 'function' && define.amd ? define('GOVUKFrontend.ErrorSummary', factory) :
4
+ (global.GOVUKFrontend = global.GOVUKFrontend || {}, global.GOVUKFrontend.ErrorSummary = factory());
5
5
  }(this, (function () { 'use strict';
6
6
 
7
- (function(undefined) {
8
-
9
- // Detection from https://github.com/Financial-Times/polyfill-service/blob/master/packages/polyfill-library/polyfills/Object/defineProperty/detect.js
10
- var detect = (
11
- // In IE8, defineProperty could only act on DOM elements, so full support
12
- // for the feature requires the ability to set a property on an arbitrary object
13
- 'defineProperty' in Object && (function() {
14
- try {
15
- var a = {};
16
- Object.defineProperty(a, 'test', {value:42});
17
- return true;
18
- } catch(e) {
19
- return false
20
- }
21
- }())
22
- );
23
-
24
- if (detect) return
25
-
26
- // Polyfill from https://cdn.polyfill.io/v2/polyfill.js?features=Object.defineProperty&flags=always
27
- (function (nativeDefineProperty) {
28
-
29
- var supportsAccessors = Object.prototype.hasOwnProperty('__defineGetter__');
30
- var ERR_ACCESSORS_NOT_SUPPORTED = 'Getters & setters cannot be defined on this javascript engine';
31
- var ERR_VALUE_ACCESSORS = 'A property cannot both have accessors and be writable or have a value';
32
-
33
- Object.defineProperty = function defineProperty(object, property, descriptor) {
34
-
35
- // Where native support exists, assume it
36
- if (nativeDefineProperty && (object === window || object === document || object === Element.prototype || object instanceof Element)) {
37
- return nativeDefineProperty(object, property, descriptor);
38
- }
39
-
40
- if (object === null || !(object instanceof Object || typeof object === 'object')) {
41
- throw new TypeError('Object.defineProperty called on non-object');
42
- }
43
-
44
- if (!(descriptor instanceof Object)) {
45
- throw new TypeError('Property description must be an object');
46
- }
47
-
48
- var propertyString = String(property);
49
- var hasValueOrWritable = 'value' in descriptor || 'writable' in descriptor;
50
- var getterType = 'get' in descriptor && typeof descriptor.get;
51
- var setterType = 'set' in descriptor && typeof descriptor.set;
52
-
53
- // handle descriptor.get
54
- if (getterType) {
55
- if (getterType !== 'function') {
56
- throw new TypeError('Getter must be a function');
57
- }
58
- if (!supportsAccessors) {
59
- throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);
60
- }
61
- if (hasValueOrWritable) {
62
- throw new TypeError(ERR_VALUE_ACCESSORS);
63
- }
64
- Object.__defineGetter__.call(object, propertyString, descriptor.get);
65
- } else {
66
- object[propertyString] = descriptor.value;
67
- }
68
-
69
- // handle descriptor.set
70
- if (setterType) {
71
- if (setterType !== 'function') {
72
- throw new TypeError('Setter must be a function');
73
- }
74
- if (!supportsAccessors) {
75
- throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);
76
- }
77
- if (hasValueOrWritable) {
78
- throw new TypeError(ERR_VALUE_ACCESSORS);
79
- }
80
- Object.__defineSetter__.call(object, propertyString, descriptor.set);
81
- }
82
-
83
- // OK to define value unconditionally - if a getter has been specified as well, an error would be thrown above
84
- if ('value' in descriptor) {
85
- object[propertyString] = descriptor.value;
86
- }
87
-
88
- return object;
89
- };
90
- }(Object.defineProperty));
91
- })
92
- .call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
93
-
94
- (function(undefined) {
95
- // Detection from https://github.com/Financial-Times/polyfill-service/blob/master/packages/polyfill-library/polyfills/Function/prototype/bind/detect.js
96
- var detect = 'bind' in Function.prototype;
97
-
98
- if (detect) return
7
+ /**
8
+ * Common helpers which do not require polyfill.
9
+ *
10
+ * IMPORTANT: If a helper require a polyfill, please isolate it in its own module
11
+ * so that the polyfill can be properly tree-shaken and does not burden
12
+ * the components that do not need that helper
13
+ *
14
+ * @module common/index
15
+ */
99
16
 
100
- // Polyfill from https://cdn.polyfill.io/v2/polyfill.js?features=Function.prototype.bind&flags=always
101
- Object.defineProperty(Function.prototype, 'bind', {
102
- value: function bind(that) { // .length is 1
103
- // add necessary es5-shim utilities
104
- var $Array = Array;
105
- var $Object = Object;
106
- var ObjectPrototype = $Object.prototype;
107
- var ArrayPrototype = $Array.prototype;
108
- var Empty = function Empty() {};
109
- var to_string = ObjectPrototype.toString;
110
- var hasToStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag === 'symbol';
111
- var isCallable; /* inlined from https://npmjs.com/is-callable */ var fnToStr = Function.prototype.toString, tryFunctionObject = function tryFunctionObject(value) { try { fnToStr.call(value); return true; } catch (e) { return false; } }, fnClass = '[object Function]', genClass = '[object GeneratorFunction]'; isCallable = function isCallable(value) { if (typeof value !== 'function') { return false; } if (hasToStringTag) { return tryFunctionObject(value); } var strClass = to_string.call(value); return strClass === fnClass || strClass === genClass; };
112
- var array_slice = ArrayPrototype.slice;
113
- var array_concat = ArrayPrototype.concat;
114
- var array_push = ArrayPrototype.push;
115
- var max = Math.max;
116
- // /add necessary es5-shim utilities
117
-
118
- // 1. Let Target be the this value.
119
- var target = this;
120
- // 2. If IsCallable(Target) is false, throw a TypeError exception.
121
- if (!isCallable(target)) {
122
- throw new TypeError('Function.prototype.bind called on incompatible ' + target);
17
+ /**
18
+ * Config flattening function
19
+ *
20
+ * Takes any number of objects, flattens them into namespaced key-value pairs,
21
+ * (e.g. {'i18n.showSection': 'Show section'}) and combines them together, with
22
+ * greatest priority on the LAST item passed in.
23
+ *
24
+ * @returns {Object<string, unknown>} A flattened object of key-value pairs.
25
+ */
26
+ function mergeConfigs (/* configObject1, configObject2, ...configObjects */) {
27
+ /**
28
+ * Function to take nested objects and flatten them to a dot-separated keyed
29
+ * object. Doing this means we don't need to do any deep/recursive merging of
30
+ * each of our objects, nor transform our dataset from a flat list into a
31
+ * nested object.
32
+ *
33
+ * @param {Object<string, unknown>} configObject - Deeply nested object
34
+ * @returns {Object<string, unknown>} Flattened object with dot-separated keys
35
+ */
36
+ var flattenObject = function (configObject) {
37
+ // Prepare an empty return object
38
+ var flattenedObject = {};
39
+
40
+ /**
41
+ * Our flattening function, this is called recursively for each level of
42
+ * depth in the object. At each level we prepend the previous level names to
43
+ * the key using `prefix`.
44
+ *
45
+ * @param {Partial<Object<string, unknown>>} obj - Object to flatten
46
+ * @param {string} [prefix] - Optional dot-separated prefix
47
+ */
48
+ var flattenLoop = function (obj, prefix) {
49
+ // Loop through keys...
50
+ for (var key in obj) {
51
+ // Check to see if this is a prototypical key/value,
52
+ // if it is, skip it.
53
+ if (!Object.prototype.hasOwnProperty.call(obj, key)) {
54
+ continue
123
55
  }
124
- // 3. Let A be a new (possibly empty) internal list of all of the
125
- // argument values provided after thisArg (arg1, arg2 etc), in order.
126
- // XXX slicedArgs will stand in for "A" if used
127
- var args = array_slice.call(arguments, 1); // for normal call
128
- // 4. Let F be a new native ECMAScript object.
129
- // 11. Set the [[Prototype]] internal property of F to the standard
130
- // built-in Function prototype object as specified in 15.3.3.1.
131
- // 12. Set the [[Call]] internal property of F as described in
132
- // 15.3.4.5.1.
133
- // 13. Set the [[Construct]] internal property of F as described in
134
- // 15.3.4.5.2.
135
- // 14. Set the [[HasInstance]] internal property of F as described in
136
- // 15.3.4.5.3.
137
- var bound;
138
- var binder = function () {
139
-
140
- if (this instanceof bound) {
141
- // 15.3.4.5.2 [[Construct]]
142
- // When the [[Construct]] internal method of a function object,
143
- // F that was created using the bind function is called with a
144
- // list of arguments ExtraArgs, the following steps are taken:
145
- // 1. Let target be the value of F's [[TargetFunction]]
146
- // internal property.
147
- // 2. If target has no [[Construct]] internal method, a
148
- // TypeError exception is thrown.
149
- // 3. Let boundArgs be the value of F's [[BoundArgs]] internal
150
- // property.
151
- // 4. Let args be a new list containing the same values as the
152
- // list boundArgs in the same order followed by the same
153
- // values as the list ExtraArgs in the same order.
154
- // 5. Return the result of calling the [[Construct]] internal
155
- // method of target providing args as the arguments.
156
-
157
- var result = target.apply(
158
- this,
159
- array_concat.call(args, array_slice.call(arguments))
160
- );
161
- if ($Object(result) === result) {
162
- return result;
163
- }
164
- return this;
165
-
166
- } else {
167
- // 15.3.4.5.1 [[Call]]
168
- // When the [[Call]] internal method of a function object, F,
169
- // which was created using the bind function is called with a
170
- // this value and a list of arguments ExtraArgs, the following
171
- // steps are taken:
172
- // 1. Let boundArgs be the value of F's [[BoundArgs]] internal
173
- // property.
174
- // 2. Let boundThis be the value of F's [[BoundThis]] internal
175
- // property.
176
- // 3. Let target be the value of F's [[TargetFunction]] internal
177
- // property.
178
- // 4. Let args be a new list containing the same values as the
179
- // list boundArgs in the same order followed by the same
180
- // values as the list ExtraArgs in the same order.
181
- // 5. Return the result of calling the [[Call]] internal method
182
- // of target providing boundThis as the this value and
183
- // providing args as the arguments.
184
-
185
- // equiv: target.call(this, ...boundArgs, ...args)
186
- return target.apply(
187
- that,
188
- array_concat.call(args, array_slice.call(arguments))
189
- );
190
-
191
- }
192
-
193
- };
194
-
195
- // 15. If the [[Class]] internal property of Target is "Function", then
196
- // a. Let L be the length property of Target minus the length of A.
197
- // b. Set the length own property of F to either 0 or L, whichever is
198
- // larger.
199
- // 16. Else set the length own property of F to 0.
200
-
201
- var boundLength = max(0, target.length - args.length);
202
-
203
- // 17. Set the attributes of the length own property of F to the values
204
- // specified in 15.3.5.1.
205
- var boundArgs = [];
206
- for (var i = 0; i < boundLength; i++) {
207
- array_push.call(boundArgs, '$' + i);
56
+ var value = obj[key];
57
+ var prefixedKey = prefix ? prefix + '.' + key : key;
58
+ if (typeof value === 'object') {
59
+ // If the value is a nested object, recurse over that too
60
+ flattenLoop(value, prefixedKey);
61
+ } else {
62
+ // Otherwise, add this value to our return object
63
+ flattenedObject[prefixedKey] = value;
208
64
  }
65
+ }
66
+ };
209
67
 
210
- // XXX Build a dynamic function with desired amount of arguments is the only
211
- // way to set the length property of a function.
212
- // In environments where Content Security Policies enabled (Chrome extensions,
213
- // for ex.) all use of eval or Function costructor throws an exception.
214
- // However in all of these environments Function.prototype.bind exists
215
- // and so this code will never be executed.
216
- bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this, arguments); }')(binder);
217
-
218
- if (target.prototype) {
219
- Empty.prototype = target.prototype;
220
- bound.prototype = new Empty();
221
- // Clean up dangling references.
222
- Empty.prototype = null;
223
- }
68
+ // Kick off the recursive loop
69
+ flattenLoop(configObject);
70
+ return flattenedObject
71
+ };
72
+
73
+ // Start with an empty object as our base
74
+ var formattedConfigObject = {};
224
75
 
225
- // TODO
226
- // 18. Set the [[Extensible]] internal property of F to true.
227
-
228
- // TODO
229
- // 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3).
230
- // 20. Call the [[DefineOwnProperty]] internal method of F with
231
- // arguments "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]:
232
- // thrower, [[Enumerable]]: false, [[Configurable]]: false}, and
233
- // false.
234
- // 21. Call the [[DefineOwnProperty]] internal method of F with
235
- // arguments "arguments", PropertyDescriptor {[[Get]]: thrower,
236
- // [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false},
237
- // and false.
238
-
239
- // TODO
240
- // NOTE Function objects created using Function.prototype.bind do not
241
- // have a prototype property or the [[Code]], [[FormalParameters]], and
242
- // [[Scope]] internal properties.
243
- // XXX can't delete prototype in pure-js.
244
-
245
- // 22. Return F.
246
- return bound;
76
+ // Loop through each of the remaining passed objects and push their keys
77
+ // one-by-one into configObject. Any duplicate keys will override the existing
78
+ // key with the new value.
79
+ for (var i = 0; i < arguments.length; i++) {
80
+ var obj = flattenObject(arguments[i]);
81
+ for (var key in obj) {
82
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
83
+ formattedConfigObject[key] = obj[key];
84
+ }
247
85
  }
248
- });
249
- })
250
- .call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
86
+ }
87
+
88
+ return formattedConfigObject
89
+ }
90
+
91
+ /**
92
+ * @callback nodeListIterator
93
+ * @param {Element} value - The current node being iterated on
94
+ * @param {number} index - The current index in the iteration
95
+ * @param {NodeListOf<Element>} nodes - NodeList from querySelectorAll()
96
+ * @returns {void}
97
+ */
98
+
99
+ (function(undefined) {
251
100
 
252
- (function(undefined) {
101
+ // Detection from https://github.com/Financial-Times/polyfill-service/blob/master/packages/polyfill-library/polyfills/Object/defineProperty/detect.js
102
+ var detect = (
103
+ // In IE8, defineProperty could only act on DOM elements, so full support
104
+ // for the feature requires the ability to set a property on an arbitrary object
105
+ 'defineProperty' in Object && (function() {
106
+ try {
107
+ var a = {};
108
+ Object.defineProperty(a, 'test', {value:42});
109
+ return true;
110
+ } catch(e) {
111
+ return false
112
+ }
113
+ }())
114
+ );
253
115
 
254
- // Detection from https://github.com/Financial-Times/polyfill-service/blob/master/packages/polyfill-library/polyfills/Window/detect.js
255
- var detect = ('Window' in this);
116
+ if (detect) return
256
117
 
257
- if (detect) return
118
+ // Polyfill from https://cdn.polyfill.io/v2/polyfill.js?features=Object.defineProperty&flags=always
119
+ (function (nativeDefineProperty) {
120
+
121
+ var supportsAccessors = Object.prototype.hasOwnProperty('__defineGetter__');
122
+ var ERR_ACCESSORS_NOT_SUPPORTED = 'Getters & setters cannot be defined on this javascript engine';
123
+ var ERR_VALUE_ACCESSORS = 'A property cannot both have accessors and be writable or have a value';
124
+
125
+ Object.defineProperty = function defineProperty(object, property, descriptor) {
126
+
127
+ // Where native support exists, assume it
128
+ if (nativeDefineProperty && (object === window || object === document || object === Element.prototype || object instanceof Element)) {
129
+ return nativeDefineProperty(object, property, descriptor);
130
+ }
131
+
132
+ if (object === null || !(object instanceof Object || typeof object === 'object')) {
133
+ throw new TypeError('Object.defineProperty called on non-object');
134
+ }
135
+
136
+ if (!(descriptor instanceof Object)) {
137
+ throw new TypeError('Property description must be an object');
138
+ }
139
+
140
+ var propertyString = String(property);
141
+ var hasValueOrWritable = 'value' in descriptor || 'writable' in descriptor;
142
+ var getterType = 'get' in descriptor && typeof descriptor.get;
143
+ var setterType = 'set' in descriptor && typeof descriptor.set;
144
+
145
+ // handle descriptor.get
146
+ if (getterType) {
147
+ if (getterType !== 'function') {
148
+ throw new TypeError('Getter must be a function');
149
+ }
150
+ if (!supportsAccessors) {
151
+ throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);
152
+ }
153
+ if (hasValueOrWritable) {
154
+ throw new TypeError(ERR_VALUE_ACCESSORS);
155
+ }
156
+ Object.__defineGetter__.call(object, propertyString, descriptor.get);
157
+ } else {
158
+ object[propertyString] = descriptor.value;
159
+ }
160
+
161
+ // handle descriptor.set
162
+ if (setterType) {
163
+ if (setterType !== 'function') {
164
+ throw new TypeError('Setter must be a function');
165
+ }
166
+ if (!supportsAccessors) {
167
+ throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);
168
+ }
169
+ if (hasValueOrWritable) {
170
+ throw new TypeError(ERR_VALUE_ACCESSORS);
171
+ }
172
+ Object.__defineSetter__.call(object, propertyString, descriptor.set);
173
+ }
174
+
175
+ // OK to define value unconditionally - if a getter has been specified as well, an error would be thrown above
176
+ if ('value' in descriptor) {
177
+ object[propertyString] = descriptor.value;
178
+ }
179
+
180
+ return object;
181
+ };
182
+ }(Object.defineProperty));
183
+ })
184
+ .call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
185
+
186
+ (function(undefined) {
187
+
188
+ // Detection from https://github.com/Financial-Times/polyfill-service/blob/master/packages/polyfill-library/polyfills/Document/detect.js
189
+ var detect = ("Document" in this);
258
190
 
259
- // Polyfill from https://cdn.polyfill.io/v2/polyfill.js?features=Window&flags=always
260
- if ((typeof WorkerGlobalScope === "undefined") && (typeof importScripts !== "function")) {
261
- (function (global) {
262
- if (global.constructor) {
263
- global.Window = global.constructor;
264
- } else {
265
- (global.Window = global.constructor = new Function('return function Window() {}')()).prototype = this;
266
- }
267
- }(this));
268
- }
191
+ if (detect) return
269
192
 
270
- })
271
- .call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
193
+ // Polyfill from https://cdn.polyfill.io/v2/polyfill.js?features=Document&flags=always
194
+ if ((typeof WorkerGlobalScope === "undefined") && (typeof importScripts !== "function")) {
272
195
 
273
- (function(undefined) {
196
+ if (this.HTMLDocument) { // IE8
274
197
 
275
- // Detection from https://github.com/Financial-Times/polyfill-service/blob/master/packages/polyfill-library/polyfills/Document/detect.js
276
- var detect = ("Document" in this);
198
+ // HTMLDocument is an extension of Document. If the browser has HTMLDocument but not Document, the former will suffice as an alias for the latter.
199
+ this.Document = this.HTMLDocument;
277
200
 
278
- if (detect) return
201
+ } else {
202
+
203
+ // Create an empty function to act as the missing constructor for the document object, attach the document object as its prototype. The function needs to be anonymous else it is hoisted and causes the feature detect to prematurely pass, preventing the assignments below being made.
204
+ this.Document = this.HTMLDocument = document.constructor = (new Function('return function Document() {}')());
205
+ this.Document.prototype = document;
206
+ }
207
+ }
279
208
 
280
- // Polyfill from https://cdn.polyfill.io/v2/polyfill.js?features=Document&flags=always
281
- if ((typeof WorkerGlobalScope === "undefined") && (typeof importScripts !== "function")) {
282
209
 
283
- if (this.HTMLDocument) { // IE8
210
+ })
211
+ .call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
284
212
 
285
- // HTMLDocument is an extension of Document. If the browser has HTMLDocument but not Document, the former will suffice as an alias for the latter.
286
- this.Document = this.HTMLDocument;
213
+ (function(undefined) {
214
+
215
+ // Detection from https://github.com/Financial-Times/polyfill-service/blob/master/packages/polyfill-library/polyfills/Element/detect.js
216
+ var detect = ('Element' in this && 'HTMLElement' in this);
217
+
218
+ if (detect) return
219
+
220
+ // Polyfill from https://cdn.polyfill.io/v2/polyfill.js?features=Element&flags=always
221
+ (function () {
222
+
223
+ // IE8
224
+ if (window.Element && !window.HTMLElement) {
225
+ window.HTMLElement = window.Element;
226
+ return;
227
+ }
287
228
 
288
- } else {
229
+ // create Element constructor
230
+ window.Element = window.HTMLElement = new Function('return function Element() {}')();
231
+
232
+ // generate sandboxed iframe
233
+ var vbody = document.appendChild(document.createElement('body'));
234
+ var frame = vbody.appendChild(document.createElement('iframe'));
235
+
236
+ // use sandboxed iframe to replicate Element functionality
237
+ var frameDocument = frame.contentWindow.document;
238
+ var prototype = Element.prototype = frameDocument.appendChild(frameDocument.createElement('*'));
239
+ var cache = {};
240
+
241
+ // polyfill Element.prototype on an element
242
+ var shiv = function (element, deep) {
243
+ var
244
+ childNodes = element.childNodes || [],
245
+ index = -1,
246
+ key, value, childNode;
247
+
248
+ if (element.nodeType === 1 && element.constructor !== Element) {
249
+ element.constructor = Element;
250
+
251
+ for (key in cache) {
252
+ value = cache[key];
253
+ element[key] = value;
254
+ }
255
+ }
256
+
257
+ while (childNode = deep && childNodes[++index]) {
258
+ shiv(childNode, deep);
259
+ }
260
+
261
+ return element;
262
+ };
263
+
264
+ var elements = document.getElementsByTagName('*');
265
+ var nativeCreateElement = document.createElement;
266
+ var interval;
267
+ var loopLimit = 100;
268
+
269
+ prototype.attachEvent('onpropertychange', function (event) {
270
+ var
271
+ propertyName = event.propertyName,
272
+ nonValue = !cache.hasOwnProperty(propertyName),
273
+ newValue = prototype[propertyName],
274
+ oldValue = cache[propertyName],
275
+ index = -1,
276
+ element;
277
+
278
+ while (element = elements[++index]) {
279
+ if (element.nodeType === 1) {
280
+ if (nonValue || element[propertyName] === oldValue) {
281
+ element[propertyName] = newValue;
282
+ }
283
+ }
284
+ }
285
+
286
+ cache[propertyName] = newValue;
287
+ });
288
+
289
+ prototype.constructor = Element;
290
+
291
+ if (!prototype.hasAttribute) {
292
+ // <Element>.hasAttribute
293
+ prototype.hasAttribute = function hasAttribute(name) {
294
+ return this.getAttribute(name) !== null;
295
+ };
296
+ }
289
297
 
290
- // Create an empty function to act as the missing constructor for the document object, attach the document object as its prototype. The function needs to be anonymous else it is hoisted and causes the feature detect to prematurely pass, preventing the assignments below being made.
291
- this.Document = this.HTMLDocument = document.constructor = (new Function('return function Document() {}')());
292
- this.Document.prototype = document;
293
- }
294
- }
295
-
296
-
297
- })
298
- .call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
299
-
300
- (function(undefined) {
301
-
302
- // Detection from https://github.com/Financial-Times/polyfill-service/blob/master/packages/polyfill-library/polyfills/Element/detect.js
303
- var detect = ('Element' in this && 'HTMLElement' in this);
304
-
305
- if (detect) return
306
-
307
- // Polyfill from https://cdn.polyfill.io/v2/polyfill.js?features=Element&flags=always
308
- (function () {
309
-
310
- // IE8
311
- if (window.Element && !window.HTMLElement) {
312
- window.HTMLElement = window.Element;
313
- return;
314
- }
315
-
316
- // create Element constructor
317
- window.Element = window.HTMLElement = new Function('return function Element() {}')();
318
-
319
- // generate sandboxed iframe
320
- var vbody = document.appendChild(document.createElement('body'));
321
- var frame = vbody.appendChild(document.createElement('iframe'));
322
-
323
- // use sandboxed iframe to replicate Element functionality
324
- var frameDocument = frame.contentWindow.document;
325
- var prototype = Element.prototype = frameDocument.appendChild(frameDocument.createElement('*'));
326
- var cache = {};
327
-
328
- // polyfill Element.prototype on an element
329
- var shiv = function (element, deep) {
330
- var
331
- childNodes = element.childNodes || [],
332
- index = -1,
333
- key, value, childNode;
334
-
335
- if (element.nodeType === 1 && element.constructor !== Element) {
336
- element.constructor = Element;
337
-
338
- for (key in cache) {
339
- value = cache[key];
340
- element[key] = value;
341
- }
342
- }
343
-
344
- while (childNode = deep && childNodes[++index]) {
345
- shiv(childNode, deep);
346
- }
347
-
348
- return element;
349
- };
350
-
351
- var elements = document.getElementsByTagName('*');
352
- var nativeCreateElement = document.createElement;
353
- var interval;
354
- var loopLimit = 100;
355
-
356
- prototype.attachEvent('onpropertychange', function (event) {
357
- var
358
- propertyName = event.propertyName,
359
- nonValue = !cache.hasOwnProperty(propertyName),
360
- newValue = prototype[propertyName],
361
- oldValue = cache[propertyName],
362
- index = -1,
363
- element;
364
-
365
- while (element = elements[++index]) {
366
- if (element.nodeType === 1) {
367
- if (nonValue || element[propertyName] === oldValue) {
368
- element[propertyName] = newValue;
369
- }
370
- }
371
- }
372
-
373
- cache[propertyName] = newValue;
374
- });
375
-
376
- prototype.constructor = Element;
377
-
378
- if (!prototype.hasAttribute) {
379
- // <Element>.hasAttribute
380
- prototype.hasAttribute = function hasAttribute(name) {
381
- return this.getAttribute(name) !== null;
382
- };
383
- }
384
-
385
- // Apply Element prototype to the pre-existing DOM as soon as the body element appears.
386
- function bodyCheck() {
387
- if (!(loopLimit--)) clearTimeout(interval);
388
- if (document.body && !document.body.prototype && /(complete|interactive)/.test(document.readyState)) {
389
- shiv(document, true);
390
- if (interval && document.body.prototype) clearTimeout(interval);
391
- return (!!document.body.prototype);
392
- }
393
- return false;
394
- }
395
- if (!bodyCheck()) {
396
- document.onreadystatechange = bodyCheck;
397
- interval = setInterval(bodyCheck, 25);
398
- }
399
-
400
- // Apply to any new elements created after load
401
- document.createElement = function createElement(nodeName) {
402
- var element = nativeCreateElement(String(nodeName).toLowerCase());
403
- return shiv(element);
404
- };
405
-
406
- // remove sandboxed iframe
407
- document.removeChild(vbody);
408
- }());
409
-
410
- })
411
- .call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
412
-
413
- (function(undefined) {
414
-
415
- // Detection from https://github.com/Financial-Times/polyfill-service/blob/master/packages/polyfill-library/polyfills/Event/detect.js
416
- var detect = (
417
- (function(global) {
418
-
419
- if (!('Event' in global)) return false;
420
- if (typeof global.Event === 'function') return true;
421
-
422
- try {
423
-
424
- // In IE 9-11, the Event object exists but cannot be instantiated
425
- new Event('click');
426
- return true;
427
- } catch(e) {
298
+ // Apply Element prototype to the pre-existing DOM as soon as the body element appears.
299
+ function bodyCheck() {
300
+ if (!(loopLimit--)) clearTimeout(interval);
301
+ if (document.body && !document.body.prototype && /(complete|interactive)/.test(document.readyState)) {
302
+ shiv(document, true);
303
+ if (interval && document.body.prototype) clearTimeout(interval);
304
+ return (!!document.body.prototype);
305
+ }
428
306
  return false;
429
307
  }
430
- }(this))
431
- );
432
-
433
- if (detect) return
434
-
435
- // Polyfill from https://cdn.polyfill.io/v2/polyfill.js?features=Event&flags=always
436
- (function () {
437
- var unlistenableWindowEvents = {
438
- click: 1,
439
- dblclick: 1,
440
- keyup: 1,
441
- keypress: 1,
442
- keydown: 1,
443
- mousedown: 1,
444
- mouseup: 1,
445
- mousemove: 1,
446
- mouseover: 1,
447
- mouseenter: 1,
448
- mouseleave: 1,
449
- mouseout: 1,
450
- storage: 1,
451
- storagecommit: 1,
452
- textinput: 1
453
- };
454
-
455
- // This polyfill depends on availability of `document` so will not run in a worker
456
- // However, we asssume there are no browsers with worker support that lack proper
457
- // support for `Event` within the worker
458
- if (typeof document === 'undefined' || typeof window === 'undefined') return;
459
-
460
- function indexOf(array, element) {
461
- var
462
- index = -1,
463
- length = array.length;
464
-
465
- while (++index < length) {
466
- if (index in array && array[index] === element) {
467
- return index;
468
- }
469
- }
470
-
471
- return -1;
472
- }
473
-
474
- var existingProto = (window.Event && window.Event.prototype) || null;
475
- window.Event = Window.prototype.Event = function Event(type, eventInitDict) {
476
- if (!type) {
477
- throw new Error('Not enough arguments');
478
- }
479
-
480
- var event;
481
- // Shortcut if browser supports createEvent
482
- if ('createEvent' in document) {
483
- event = document.createEvent('Event');
484
- var bubbles = eventInitDict && eventInitDict.bubbles !== undefined ? eventInitDict.bubbles : false;
485
- var cancelable = eventInitDict && eventInitDict.cancelable !== undefined ? eventInitDict.cancelable : false;
486
-
487
- event.initEvent(type, bubbles, cancelable);
488
-
489
- return event;
490
- }
491
-
492
- event = document.createEventObject();
493
-
494
- event.type = type;
495
- event.bubbles = eventInitDict && eventInitDict.bubbles !== undefined ? eventInitDict.bubbles : false;
496
- event.cancelable = eventInitDict && eventInitDict.cancelable !== undefined ? eventInitDict.cancelable : false;
497
-
498
- return event;
499
- };
500
- if (existingProto) {
501
- Object.defineProperty(window.Event, 'prototype', {
502
- configurable: false,
503
- enumerable: false,
504
- writable: true,
505
- value: existingProto
506
- });
507
- }
508
-
509
- if (!('createEvent' in document)) {
510
- window.addEventListener = Window.prototype.addEventListener = Document.prototype.addEventListener = Element.prototype.addEventListener = function addEventListener() {
511
- var
512
- element = this,
513
- type = arguments[0],
514
- listener = arguments[1];
515
-
516
- if (element === window && type in unlistenableWindowEvents) {
517
- throw new Error('In IE8 the event: ' + type + ' is not available on the window object. Please see https://github.com/Financial-Times/polyfill-service/issues/317 for more information.');
518
- }
519
-
520
- if (!element._events) {
521
- element._events = {};
522
- }
523
-
524
- if (!element._events[type]) {
525
- element._events[type] = function (event) {
526
- var
527
- list = element._events[event.type].list,
528
- events = list.slice(),
529
- index = -1,
530
- length = events.length,
531
- eventElement;
532
-
533
- event.preventDefault = function preventDefault() {
534
- if (event.cancelable !== false) {
535
- event.returnValue = false;
536
- }
537
- };
538
-
539
- event.stopPropagation = function stopPropagation() {
540
- event.cancelBubble = true;
541
- };
542
-
543
- event.stopImmediatePropagation = function stopImmediatePropagation() {
544
- event.cancelBubble = true;
545
- event.cancelImmediate = true;
546
- };
547
-
548
- event.currentTarget = element;
549
- event.relatedTarget = event.fromElement || null;
550
- event.target = event.target || event.srcElement || element;
551
- event.timeStamp = new Date().getTime();
552
-
553
- if (event.clientX) {
554
- event.pageX = event.clientX + document.documentElement.scrollLeft;
555
- event.pageY = event.clientY + document.documentElement.scrollTop;
556
- }
557
-
558
- while (++index < length && !event.cancelImmediate) {
559
- if (index in events) {
560
- eventElement = events[index];
561
-
562
- if (indexOf(list, eventElement) !== -1 && typeof eventElement === 'function') {
563
- eventElement.call(element, event);
564
- }
565
- }
566
- }
567
- };
568
-
569
- element._events[type].list = [];
570
-
571
- if (element.attachEvent) {
572
- element.attachEvent('on' + type, element._events[type]);
573
- }
574
- }
575
-
576
- element._events[type].list.push(listener);
577
- };
578
-
579
- window.removeEventListener = Window.prototype.removeEventListener = Document.prototype.removeEventListener = Element.prototype.removeEventListener = function removeEventListener() {
580
- var
581
- element = this,
582
- type = arguments[0],
583
- listener = arguments[1],
584
- index;
585
-
586
- if (element._events && element._events[type] && element._events[type].list) {
587
- index = indexOf(element._events[type].list, listener);
588
-
589
- if (index !== -1) {
590
- element._events[type].list.splice(index, 1);
591
-
592
- if (!element._events[type].list.length) {
593
- if (element.detachEvent) {
594
- element.detachEvent('on' + type, element._events[type]);
595
- }
596
- delete element._events[type];
597
- }
598
- }
599
- }
600
- };
601
-
602
- window.dispatchEvent = Window.prototype.dispatchEvent = Document.prototype.dispatchEvent = Element.prototype.dispatchEvent = function dispatchEvent(event) {
603
- if (!arguments.length) {
604
- throw new Error('Not enough arguments');
605
- }
606
-
607
- if (!event || typeof event.type !== 'string') {
608
- throw new Error('DOM Events Exception 0');
609
- }
610
-
611
- var element = this, type = event.type;
612
-
613
- try {
614
- if (!event.bubbles) {
615
- event.cancelBubble = true;
616
-
617
- var cancelBubbleEvent = function (event) {
618
- event.cancelBubble = true;
619
-
620
- (element || window).detachEvent('on' + type, cancelBubbleEvent);
621
- };
622
-
623
- this.attachEvent('on' + type, cancelBubbleEvent);
624
- }
625
-
626
- this.fireEvent('on' + type, event);
627
- } catch (error) {
628
- event.target = element;
629
-
630
- do {
631
- event.currentTarget = element;
632
-
633
- if ('_events' in element && typeof element._events[type] === 'function') {
634
- element._events[type].call(element, event);
635
- }
636
-
637
- if (typeof element['on' + type] === 'function') {
638
- element['on' + type].call(element, event);
639
- }
640
-
641
- element = element.nodeType === 9 ? element.parentWindow : element.parentNode;
642
- } while (element && !event.cancelBubble);
643
- }
644
-
645
- return true;
646
- };
647
-
648
- // Add the DOMContentLoaded Event
649
- document.attachEvent('onreadystatechange', function() {
650
- if (document.readyState === 'complete') {
651
- document.dispatchEvent(new Event('DOMContentLoaded', {
652
- bubbles: true
653
- }));
654
- }
655
- });
656
- }
657
- }());
658
-
659
- })
660
- .call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
661
-
662
- (function(undefined) {
663
-
664
- // Detection from https://raw.githubusercontent.com/Financial-Times/polyfill-service/1f3c09b402f65bf6e393f933a15ba63f1b86ef1f/packages/polyfill-library/polyfills/Element/prototype/matches/detect.js
665
- var detect = (
666
- 'document' in this && "matches" in document.documentElement
667
- );
308
+ if (!bodyCheck()) {
309
+ document.onreadystatechange = bodyCheck;
310
+ interval = setInterval(bodyCheck, 25);
311
+ }
668
312
 
669
- if (detect) return
313
+ // Apply to any new elements created after load
314
+ document.createElement = function createElement(nodeName) {
315
+ var element = nativeCreateElement(String(nodeName).toLowerCase());
316
+ return shiv(element);
317
+ };
670
318
 
671
- // Polyfill from https://raw.githubusercontent.com/Financial-Times/polyfill-service/1f3c09b402f65bf6e393f933a15ba63f1b86ef1f/packages/polyfill-library/polyfills/Element/prototype/matches/polyfill.js
672
- Element.prototype.matches = Element.prototype.webkitMatchesSelector || Element.prototype.oMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.mozMatchesSelector || function matches(selector) {
673
- var element = this;
674
- var elements = (element.document || element.ownerDocument).querySelectorAll(selector);
675
- var index = 0;
319
+ // remove sandboxed iframe
320
+ document.removeChild(vbody);
321
+ }());
676
322
 
677
- while (elements[index] && elements[index] !== element) {
678
- ++index;
679
- }
323
+ })
324
+ .call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
680
325
 
681
- return !!elements[index];
682
- };
326
+ (function(undefined) {
683
327
 
684
- }).call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
328
+ // Detection from https://raw.githubusercontent.com/Financial-Times/polyfill-library/13cf7c340974d128d557580b5e2dafcd1b1192d1/polyfills/Element/prototype/dataset/detect.js
329
+ var detect = (function(){
330
+ if (!document.documentElement.dataset) {
331
+ return false;
332
+ }
333
+ var el = document.createElement('div');
334
+ el.setAttribute("data-a-b", "c");
335
+ return el.dataset && el.dataset.aB == "c";
336
+ }());
685
337
 
686
- (function(undefined) {
338
+ if (detect) return
687
339
 
688
- // Detection from https://raw.githubusercontent.com/Financial-Times/polyfill-service/1f3c09b402f65bf6e393f933a15ba63f1b86ef1f/packages/polyfill-library/polyfills/Element/prototype/closest/detect.js
689
- var detect = (
690
- 'document' in this && "closest" in document.documentElement
691
- );
340
+ // Polyfill derived from https://raw.githubusercontent.com/Financial-Times/polyfill-library/13cf7c340974d128d557580b5e2dafcd1b1192d1/polyfills/Element/prototype/dataset/polyfill.js
341
+ Object.defineProperty(Element.prototype, 'dataset', {
342
+ get: function() {
343
+ var element = this;
344
+ var attributes = this.attributes;
345
+ var map = {};
346
+
347
+ for (var i = 0; i < attributes.length; i++) {
348
+ var attribute = attributes[i];
349
+
350
+ // This regex has been edited from the original polyfill, to add
351
+ // support for period (.) separators in data-* attribute names. These
352
+ // are allowed in the HTML spec, but were not covered by the original
353
+ // polyfill's regex. We use periods in our i18n implementation.
354
+ if (attribute && attribute.name && (/^data-\w[.\w-]*$/).test(attribute.name)) {
355
+ var name = attribute.name;
356
+ var value = attribute.value;
357
+
358
+ var propName = name.substr(5).replace(/-./g, function (prop) {
359
+ return prop.charAt(1).toUpperCase();
360
+ });
361
+
362
+ // If this browser supports __defineGetter__ and __defineSetter__,
363
+ // continue using defineProperty. If not (like IE 8 and below), we use
364
+ // a hacky fallback which at least gives an object in the right format
365
+ if ('__defineGetter__' in Object.prototype && '__defineSetter__' in Object.prototype) {
366
+ Object.defineProperty(map, propName, {
367
+ enumerable: true,
368
+ get: function() {
369
+ return this.value;
370
+ }.bind({value: value || ''}),
371
+ set: function setter(name, value) {
372
+ if (typeof value !== 'undefined') {
373
+ this.setAttribute(name, value);
374
+ } else {
375
+ this.removeAttribute(name);
376
+ }
377
+ }.bind(element, name)
378
+ });
379
+ } else {
380
+ map[propName] = value;
381
+ }
692
382
 
693
- if (detect) return
383
+ }
384
+ }
385
+
386
+ return map;
387
+ }
388
+ });
389
+
390
+ }).call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
391
+
392
+ (function(undefined) {
393
+
394
+ // Detection from https://github.com/mdn/content/blob/cf607d68522cd35ee7670782d3ee3a361eaef2e4/files/en-us/web/javascript/reference/global_objects/string/trim/index.md#polyfill
395
+ var detect = ('trim' in String.prototype);
396
+
397
+ if (detect) return
398
+
399
+ // Polyfill from https://github.com/mdn/content/blob/cf607d68522cd35ee7670782d3ee3a361eaef2e4/files/en-us/web/javascript/reference/global_objects/string/trim/index.md#polyfill
400
+ String.prototype.trim = function () {
401
+ return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
402
+ };
694
403
 
695
- // Polyfill from https://raw.githubusercontent.com/Financial-Times/polyfill-service/1f3c09b402f65bf6e393f933a15ba63f1b86ef1f/packages/polyfill-library/polyfills/Element/prototype/closest/polyfill.js
696
- Element.prototype.closest = function closest(selector) {
697
- var node = this;
404
+ }).call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
698
405
 
699
- while (node) {
700
- if (node.matches(selector)) return node;
701
- else node = 'SVGElement' in window && node instanceof SVGElement ? node.parentNode : node.parentElement;
406
+ /* eslint-disable es-x/no-string-prototype-trim -- Polyfill imported */
407
+
408
+ /**
409
+ * Normalise string
410
+ *
411
+ * 'If it looks like a duck, and it quacks like a duck…' 🦆
412
+ *
413
+ * If the passed value looks like a boolean or a number, convert it to a boolean
414
+ * or number.
415
+ *
416
+ * Designed to be used to convert config passed via data attributes (which are
417
+ * always strings) into something sensible.
418
+ *
419
+ * @param {string} value - The value to normalise
420
+ * @returns {string | boolean | number | undefined} Normalised data
421
+ */
422
+ function normaliseString (value) {
423
+ if (typeof value !== 'string') {
424
+ return value
702
425
  }
703
426
 
704
- return null;
705
- };
427
+ var trimmedValue = value.trim();
428
+
429
+ if (trimmedValue === 'true') {
430
+ return true
431
+ }
432
+
433
+ if (trimmedValue === 'false') {
434
+ return false
435
+ }
436
+
437
+ // Empty / whitespace-only strings are considered finite so we need to check
438
+ // the length of the trimmed string as well
439
+ if (trimmedValue.length > 0 && isFinite(trimmedValue)) {
440
+ return Number(trimmedValue)
441
+ }
442
+
443
+ return value
444
+ }
706
445
 
707
- }).call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
708
-
709
- /**
710
- * Common helpers which do not require polyfill.
711
- *
712
- * IMPORTANT: If a helper require a polyfill, please isolate it in its own module
713
- * so that the polyfill can be properly tree-shaken and does not burden
714
- * the components that do not need that helper
715
- *
716
- * @module common/index
717
- */
718
-
719
- /**
720
- * Config flattening function
721
- *
722
- * Takes any number of objects, flattens them into namespaced key-value pairs,
723
- * (e.g. {'i18n.showSection': 'Show section'}) and combines them together, with
724
- * greatest priority on the LAST item passed in.
725
- *
726
- * @returns {object} A flattened object of key-value pairs.
727
- */
728
- function mergeConfigs (/* configObject1, configObject2, ...configObjects */) {
729
446
  /**
730
- * Function to take nested objects and flatten them to a dot-separated keyed
731
- * object. Doing this means we don't need to do any deep/recursive merging of
732
- * each of our objects, nor transform our dataset from a flat list into a
733
- * nested object.
447
+ * Normalise dataset
734
448
  *
735
- * @param {object} configObject - Deeply nested object
736
- * @returns {object} Flattened object with dot-separated keys
449
+ * Loop over an object and normalise each value using normaliseData function
450
+ *
451
+ * @param {DOMStringMap} dataset - HTML element dataset
452
+ * @returns {Object<string, unknown>} Normalised dataset
737
453
  */
738
- var flattenObject = function (configObject) {
739
- // Prepare an empty return object
740
- var flattenedObject = {};
741
-
742
- // Our flattening function, this is called recursively for each level of
743
- // depth in the object. At each level we prepend the previous level names to
744
- // the key using `prefix`.
745
- var flattenLoop = function (obj, prefix) {
746
- // Loop through keys...
747
- for (var key in obj) {
748
- // Check to see if this is a prototypical key/value,
749
- // if it is, skip it.
750
- if (!Object.prototype.hasOwnProperty.call(obj, key)) {
751
- continue
752
- }
753
- var value = obj[key];
754
- var prefixedKey = prefix ? prefix + '.' + key : key;
755
- if (typeof value === 'object') {
756
- // If the value is a nested object, recurse over that too
757
- flattenLoop(value, prefixedKey);
758
- } else {
759
- // Otherwise, add this value to our return object
760
- flattenedObject[prefixedKey] = value;
761
- }
454
+ function normaliseDataset (dataset) {
455
+ var out = {};
456
+
457
+ for (var key in dataset) {
458
+ out[key] = normaliseString(dataset[key]);
459
+ }
460
+
461
+ return out
462
+ }
463
+
464
+ (function(undefined) {
465
+
466
+ // Detection from https://raw.githubusercontent.com/Financial-Times/polyfill-service/1f3c09b402f65bf6e393f933a15ba63f1b86ef1f/packages/polyfill-library/polyfills/Element/prototype/matches/detect.js
467
+ var detect = (
468
+ 'document' in this && "matches" in document.documentElement
469
+ );
470
+
471
+ if (detect) return
472
+
473
+ // Polyfill from https://raw.githubusercontent.com/Financial-Times/polyfill-service/1f3c09b402f65bf6e393f933a15ba63f1b86ef1f/packages/polyfill-library/polyfills/Element/prototype/matches/polyfill.js
474
+ Element.prototype.matches = Element.prototype.webkitMatchesSelector || Element.prototype.oMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.mozMatchesSelector || function matches(selector) {
475
+ var element = this;
476
+ var elements = (element.document || element.ownerDocument).querySelectorAll(selector);
477
+ var index = 0;
478
+
479
+ while (elements[index] && elements[index] !== element) {
480
+ ++index;
762
481
  }
482
+
483
+ return !!elements[index];
763
484
  };
764
485
 
765
- // Kick off the recursive loop
766
- flattenLoop(configObject);
767
- return flattenedObject
768
- };
486
+ }).call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
487
+
488
+ (function(undefined) {
489
+
490
+ // Detection from https://raw.githubusercontent.com/Financial-Times/polyfill-service/1f3c09b402f65bf6e393f933a15ba63f1b86ef1f/packages/polyfill-library/polyfills/Element/prototype/closest/detect.js
491
+ var detect = (
492
+ 'document' in this && "closest" in document.documentElement
493
+ );
494
+
495
+ if (detect) return
769
496
 
770
- // Start with an empty object as our base
771
- var formattedConfigObject = {};
772
-
773
- // Loop through each of the remaining passed objects and push their keys
774
- // one-by-one into configObject. Any duplicate keys will override the existing
775
- // key with the new value.
776
- for (var i = 0; i < arguments.length; i++) {
777
- var obj = flattenObject(arguments[i]);
778
- for (var key in obj) {
779
- if (Object.prototype.hasOwnProperty.call(obj, key)) {
780
- formattedConfigObject[key] = obj[key];
497
+ // Polyfill from https://raw.githubusercontent.com/Financial-Times/polyfill-service/1f3c09b402f65bf6e393f933a15ba63f1b86ef1f/packages/polyfill-library/polyfills/Element/prototype/closest/polyfill.js
498
+ Element.prototype.closest = function closest(selector) {
499
+ var node = this;
500
+
501
+ while (node) {
502
+ if (node.matches(selector)) return node;
503
+ else node = 'SVGElement' in window && node instanceof SVGElement ? node.parentNode : node.parentElement;
781
504
  }
782
- }
505
+
506
+ return null;
507
+ };
508
+
509
+ }).call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
510
+
511
+ (function(undefined) {
512
+
513
+ // Detection from https://github.com/Financial-Times/polyfill-service/blob/master/packages/polyfill-library/polyfills/Window/detect.js
514
+ var detect = ('Window' in this);
515
+
516
+ if (detect) return
517
+
518
+ // Polyfill from https://cdn.polyfill.io/v2/polyfill.js?features=Window&flags=always
519
+ if ((typeof WorkerGlobalScope === "undefined") && (typeof importScripts !== "function")) {
520
+ (function (global) {
521
+ if (global.constructor) {
522
+ global.Window = global.constructor;
523
+ } else {
524
+ (global.Window = global.constructor = new Function('return function Window() {}')()).prototype = this;
525
+ }
526
+ }(this));
783
527
  }
784
528
 
785
- return formattedConfigObject
786
- }
529
+ })
530
+ .call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
787
531
 
788
- /**
789
- * @callback nodeListIterator
790
- * @param {Element} value - The current node being iterated on
791
- * @param {number} index - The current index in the iteration
792
- * @param {NodeListOf<Element>} nodes - NodeList from querySelectorAll()
793
- * @returns {undefined}
794
- */
532
+ (function(undefined) {
795
533
 
796
- (function(undefined) {
534
+ // Detection from https://github.com/Financial-Times/polyfill-service/blob/master/packages/polyfill-library/polyfills/Event/detect.js
535
+ var detect = (
536
+ (function(global) {
797
537
 
798
- // Detection from https://raw.githubusercontent.com/Financial-Times/polyfill-library/13cf7c340974d128d557580b5e2dafcd1b1192d1/polyfills/Element/prototype/dataset/detect.js
799
- var detect = (function(){
800
- if (!document.documentElement.dataset) {
801
- return false;
802
- }
803
- var el = document.createElement('div');
804
- el.setAttribute("data-a-b", "c");
805
- return el.dataset && el.dataset.aB == "c";
806
- }());
538
+ if (!('Event' in global)) return false;
539
+ if (typeof global.Event === 'function') return true;
540
+
541
+ try {
542
+
543
+ // In IE 9-11, the Event object exists but cannot be instantiated
544
+ new Event('click');
545
+ return true;
546
+ } catch(e) {
547
+ return false;
548
+ }
549
+ }(this))
550
+ );
807
551
 
808
552
  if (detect) return
809
553
 
810
- // Polyfill derived from https://raw.githubusercontent.com/Financial-Times/polyfill-library/13cf7c340974d128d557580b5e2dafcd1b1192d1/polyfills/Element/prototype/dataset/polyfill.js
811
- Object.defineProperty(Element.prototype, 'dataset', {
812
- get: function() {
813
- var element = this;
814
- var attributes = this.attributes;
815
- var map = {};
816
-
817
- for (var i = 0; i < attributes.length; i++) {
818
- var attribute = attributes[i];
819
-
820
- // This regex has been edited from the original polyfill, to add
821
- // support for period (.) separators in data-* attribute names. These
822
- // are allowed in the HTML spec, but were not covered by the original
823
- // polyfill's regex. We use periods in our i18n implementation.
824
- if (attribute && attribute.name && (/^data-\w[.\w-]*$/).test(attribute.name)) {
825
- var name = attribute.name;
826
- var value = attribute.value;
827
-
828
- var propName = name.substr(5).replace(/-./g, function (prop) {
829
- return prop.charAt(1).toUpperCase();
830
- });
831
-
832
- // If this browser supports __defineGetter__ and __defineSetter__,
833
- // continue using defineProperty. If not (like IE 8 and below), we use
834
- // a hacky fallback which at least gives an object in the right format
835
- if ('__defineGetter__' in Object.prototype && '__defineSetter__' in Object.prototype) {
836
- Object.defineProperty(map, propName, {
837
- enumerable: true,
838
- get: function() {
839
- return this.value;
840
- }.bind({value: value || ''}),
841
- set: function setter(name, value) {
842
- if (typeof value !== 'undefined') {
843
- this.setAttribute(name, value);
554
+ // Polyfill from https://cdn.polyfill.io/v2/polyfill.js?features=Event&flags=always
555
+ (function () {
556
+ var unlistenableWindowEvents = {
557
+ click: 1,
558
+ dblclick: 1,
559
+ keyup: 1,
560
+ keypress: 1,
561
+ keydown: 1,
562
+ mousedown: 1,
563
+ mouseup: 1,
564
+ mousemove: 1,
565
+ mouseover: 1,
566
+ mouseenter: 1,
567
+ mouseleave: 1,
568
+ mouseout: 1,
569
+ storage: 1,
570
+ storagecommit: 1,
571
+ textinput: 1
572
+ };
573
+
574
+ // This polyfill depends on availability of `document` so will not run in a worker
575
+ // However, we asssume there are no browsers with worker support that lack proper
576
+ // support for `Event` within the worker
577
+ if (typeof document === 'undefined' || typeof window === 'undefined') return;
578
+
579
+ function indexOf(array, element) {
580
+ var
581
+ index = -1,
582
+ length = array.length;
583
+
584
+ while (++index < length) {
585
+ if (index in array && array[index] === element) {
586
+ return index;
587
+ }
588
+ }
589
+
590
+ return -1;
591
+ }
592
+
593
+ var existingProto = (window.Event && window.Event.prototype) || null;
594
+ window.Event = Window.prototype.Event = function Event(type, eventInitDict) {
595
+ if (!type) {
596
+ throw new Error('Not enough arguments');
597
+ }
598
+
599
+ var event;
600
+ // Shortcut if browser supports createEvent
601
+ if ('createEvent' in document) {
602
+ event = document.createEvent('Event');
603
+ var bubbles = eventInitDict && eventInitDict.bubbles !== undefined ? eventInitDict.bubbles : false;
604
+ var cancelable = eventInitDict && eventInitDict.cancelable !== undefined ? eventInitDict.cancelable : false;
605
+
606
+ event.initEvent(type, bubbles, cancelable);
607
+
608
+ return event;
609
+ }
610
+
611
+ event = document.createEventObject();
612
+
613
+ event.type = type;
614
+ event.bubbles = eventInitDict && eventInitDict.bubbles !== undefined ? eventInitDict.bubbles : false;
615
+ event.cancelable = eventInitDict && eventInitDict.cancelable !== undefined ? eventInitDict.cancelable : false;
616
+
617
+ return event;
618
+ };
619
+ if (existingProto) {
620
+ Object.defineProperty(window.Event, 'prototype', {
621
+ configurable: false,
622
+ enumerable: false,
623
+ writable: true,
624
+ value: existingProto
625
+ });
626
+ }
627
+
628
+ if (!('createEvent' in document)) {
629
+ window.addEventListener = Window.prototype.addEventListener = Document.prototype.addEventListener = Element.prototype.addEventListener = function addEventListener() {
630
+ var
631
+ element = this,
632
+ type = arguments[0],
633
+ listener = arguments[1];
634
+
635
+ if (element === window && type in unlistenableWindowEvents) {
636
+ throw new Error('In IE8 the event: ' + type + ' is not available on the window object. Please see https://github.com/Financial-Times/polyfill-service/issues/317 for more information.');
637
+ }
638
+
639
+ if (!element._events) {
640
+ element._events = {};
641
+ }
642
+
643
+ if (!element._events[type]) {
644
+ element._events[type] = function (event) {
645
+ var
646
+ list = element._events[event.type].list,
647
+ events = list.slice(),
648
+ index = -1,
649
+ length = events.length,
650
+ eventElement;
651
+
652
+ event.preventDefault = function preventDefault() {
653
+ if (event.cancelable !== false) {
654
+ event.returnValue = false;
655
+ }
656
+ };
657
+
658
+ event.stopPropagation = function stopPropagation() {
659
+ event.cancelBubble = true;
660
+ };
661
+
662
+ event.stopImmediatePropagation = function stopImmediatePropagation() {
663
+ event.cancelBubble = true;
664
+ event.cancelImmediate = true;
665
+ };
666
+
667
+ event.currentTarget = element;
668
+ event.relatedTarget = event.fromElement || null;
669
+ event.target = event.target || event.srcElement || element;
670
+ event.timeStamp = new Date().getTime();
671
+
672
+ if (event.clientX) {
673
+ event.pageX = event.clientX + document.documentElement.scrollLeft;
674
+ event.pageY = event.clientY + document.documentElement.scrollTop;
675
+ }
676
+
677
+ while (++index < length && !event.cancelImmediate) {
678
+ if (index in events) {
679
+ eventElement = events[index];
680
+
681
+ if (indexOf(list, eventElement) !== -1 && typeof eventElement === 'function') {
682
+ eventElement.call(element, event);
683
+ }
684
+ }
685
+ }
686
+ };
687
+
688
+ element._events[type].list = [];
689
+
690
+ if (element.attachEvent) {
691
+ element.attachEvent('on' + type, element._events[type]);
692
+ }
693
+ }
694
+
695
+ element._events[type].list.push(listener);
696
+ };
697
+
698
+ window.removeEventListener = Window.prototype.removeEventListener = Document.prototype.removeEventListener = Element.prototype.removeEventListener = function removeEventListener() {
699
+ var
700
+ element = this,
701
+ type = arguments[0],
702
+ listener = arguments[1],
703
+ index;
704
+
705
+ if (element._events && element._events[type] && element._events[type].list) {
706
+ index = indexOf(element._events[type].list, listener);
707
+
708
+ if (index !== -1) {
709
+ element._events[type].list.splice(index, 1);
710
+
711
+ if (!element._events[type].list.length) {
712
+ if (element.detachEvent) {
713
+ element.detachEvent('on' + type, element._events[type]);
714
+ }
715
+ delete element._events[type];
716
+ }
717
+ }
718
+ }
719
+ };
720
+
721
+ window.dispatchEvent = Window.prototype.dispatchEvent = Document.prototype.dispatchEvent = Element.prototype.dispatchEvent = function dispatchEvent(event) {
722
+ if (!arguments.length) {
723
+ throw new Error('Not enough arguments');
724
+ }
725
+
726
+ if (!event || typeof event.type !== 'string') {
727
+ throw new Error('DOM Events Exception 0');
728
+ }
729
+
730
+ var element = this, type = event.type;
731
+
732
+ try {
733
+ if (!event.bubbles) {
734
+ event.cancelBubble = true;
735
+
736
+ var cancelBubbleEvent = function (event) {
737
+ event.cancelBubble = true;
738
+
739
+ (element || window).detachEvent('on' + type, cancelBubbleEvent);
740
+ };
741
+
742
+ this.attachEvent('on' + type, cancelBubbleEvent);
743
+ }
744
+
745
+ this.fireEvent('on' + type, event);
746
+ } catch (error) {
747
+ event.target = element;
748
+
749
+ do {
750
+ event.currentTarget = element;
751
+
752
+ if ('_events' in element && typeof element._events[type] === 'function') {
753
+ element._events[type].call(element, event);
754
+ }
755
+
756
+ if (typeof element['on' + type] === 'function') {
757
+ element['on' + type].call(element, event);
758
+ }
759
+
760
+ element = element.nodeType === 9 ? element.parentWindow : element.parentNode;
761
+ } while (element && !event.cancelBubble);
762
+ }
763
+
764
+ return true;
765
+ };
766
+
767
+ // Add the DOMContentLoaded Event
768
+ document.attachEvent('onreadystatechange', function() {
769
+ if (document.readyState === 'complete') {
770
+ document.dispatchEvent(new Event('DOMContentLoaded', {
771
+ bubbles: true
772
+ }));
773
+ }
774
+ });
775
+ }
776
+ }());
777
+
778
+ })
779
+ .call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
780
+
781
+ (function(undefined) {
782
+ // Detection from https://github.com/Financial-Times/polyfill-service/blob/master/packages/polyfill-library/polyfills/Function/prototype/bind/detect.js
783
+ var detect = 'bind' in Function.prototype;
784
+
785
+ if (detect) return
786
+
787
+ // Polyfill from https://cdn.polyfill.io/v2/polyfill.js?features=Function.prototype.bind&flags=always
788
+ Object.defineProperty(Function.prototype, 'bind', {
789
+ value: function bind(that) { // .length is 1
790
+ // add necessary es5-shim utilities
791
+ var $Array = Array;
792
+ var $Object = Object;
793
+ var ObjectPrototype = $Object.prototype;
794
+ var ArrayPrototype = $Array.prototype;
795
+ var Empty = function Empty() {};
796
+ var to_string = ObjectPrototype.toString;
797
+ var hasToStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag === 'symbol';
798
+ var isCallable; /* inlined from https://npmjs.com/is-callable */ var fnToStr = Function.prototype.toString, tryFunctionObject = function tryFunctionObject(value) { try { fnToStr.call(value); return true; } catch (e) { return false; } }, fnClass = '[object Function]', genClass = '[object GeneratorFunction]'; isCallable = function isCallable(value) { if (typeof value !== 'function') { return false; } if (hasToStringTag) { return tryFunctionObject(value); } var strClass = to_string.call(value); return strClass === fnClass || strClass === genClass; };
799
+ var array_slice = ArrayPrototype.slice;
800
+ var array_concat = ArrayPrototype.concat;
801
+ var array_push = ArrayPrototype.push;
802
+ var max = Math.max;
803
+ // /add necessary es5-shim utilities
804
+
805
+ // 1. Let Target be the this value.
806
+ var target = this;
807
+ // 2. If IsCallable(Target) is false, throw a TypeError exception.
808
+ if (!isCallable(target)) {
809
+ throw new TypeError('Function.prototype.bind called on incompatible ' + target);
810
+ }
811
+ // 3. Let A be a new (possibly empty) internal list of all of the
812
+ // argument values provided after thisArg (arg1, arg2 etc), in order.
813
+ // XXX slicedArgs will stand in for "A" if used
814
+ var args = array_slice.call(arguments, 1); // for normal call
815
+ // 4. Let F be a new native ECMAScript object.
816
+ // 11. Set the [[Prototype]] internal property of F to the standard
817
+ // built-in Function prototype object as specified in 15.3.3.1.
818
+ // 12. Set the [[Call]] internal property of F as described in
819
+ // 15.3.4.5.1.
820
+ // 13. Set the [[Construct]] internal property of F as described in
821
+ // 15.3.4.5.2.
822
+ // 14. Set the [[HasInstance]] internal property of F as described in
823
+ // 15.3.4.5.3.
824
+ var bound;
825
+ var binder = function () {
826
+
827
+ if (this instanceof bound) {
828
+ // 15.3.4.5.2 [[Construct]]
829
+ // When the [[Construct]] internal method of a function object,
830
+ // F that was created using the bind function is called with a
831
+ // list of arguments ExtraArgs, the following steps are taken:
832
+ // 1. Let target be the value of F's [[TargetFunction]]
833
+ // internal property.
834
+ // 2. If target has no [[Construct]] internal method, a
835
+ // TypeError exception is thrown.
836
+ // 3. Let boundArgs be the value of F's [[BoundArgs]] internal
837
+ // property.
838
+ // 4. Let args be a new list containing the same values as the
839
+ // list boundArgs in the same order followed by the same
840
+ // values as the list ExtraArgs in the same order.
841
+ // 5. Return the result of calling the [[Construct]] internal
842
+ // method of target providing args as the arguments.
843
+
844
+ var result = target.apply(
845
+ this,
846
+ array_concat.call(args, array_slice.call(arguments))
847
+ );
848
+ if ($Object(result) === result) {
849
+ return result;
850
+ }
851
+ return this;
852
+
844
853
  } else {
845
- this.removeAttribute(name);
854
+ // 15.3.4.5.1 [[Call]]
855
+ // When the [[Call]] internal method of a function object, F,
856
+ // which was created using the bind function is called with a
857
+ // this value and a list of arguments ExtraArgs, the following
858
+ // steps are taken:
859
+ // 1. Let boundArgs be the value of F's [[BoundArgs]] internal
860
+ // property.
861
+ // 2. Let boundThis be the value of F's [[BoundThis]] internal
862
+ // property.
863
+ // 3. Let target be the value of F's [[TargetFunction]] internal
864
+ // property.
865
+ // 4. Let args be a new list containing the same values as the
866
+ // list boundArgs in the same order followed by the same
867
+ // values as the list ExtraArgs in the same order.
868
+ // 5. Return the result of calling the [[Call]] internal method
869
+ // of target providing boundThis as the this value and
870
+ // providing args as the arguments.
871
+
872
+ // equiv: target.call(this, ...boundArgs, ...args)
873
+ return target.apply(
874
+ that,
875
+ array_concat.call(args, array_slice.call(arguments))
876
+ );
877
+
846
878
  }
847
- }.bind(element, name)
848
- });
849
- } else {
850
- map[propName] = value;
851
- }
852
879
 
880
+ };
881
+
882
+ // 15. If the [[Class]] internal property of Target is "Function", then
883
+ // a. Let L be the length property of Target minus the length of A.
884
+ // b. Set the length own property of F to either 0 or L, whichever is
885
+ // larger.
886
+ // 16. Else set the length own property of F to 0.
887
+
888
+ var boundLength = max(0, target.length - args.length);
889
+
890
+ // 17. Set the attributes of the length own property of F to the values
891
+ // specified in 15.3.5.1.
892
+ var boundArgs = [];
893
+ for (var i = 0; i < boundLength; i++) {
894
+ array_push.call(boundArgs, '$' + i);
895
+ }
896
+
897
+ // XXX Build a dynamic function with desired amount of arguments is the only
898
+ // way to set the length property of a function.
899
+ // In environments where Content Security Policies enabled (Chrome extensions,
900
+ // for ex.) all use of eval or Function costructor throws an exception.
901
+ // However in all of these environments Function.prototype.bind exists
902
+ // and so this code will never be executed.
903
+ bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this, arguments); }')(binder);
904
+
905
+ if (target.prototype) {
906
+ Empty.prototype = target.prototype;
907
+ bound.prototype = new Empty();
908
+ // Clean up dangling references.
909
+ Empty.prototype = null;
910
+ }
911
+
912
+ // TODO
913
+ // 18. Set the [[Extensible]] internal property of F to true.
914
+
915
+ // TODO
916
+ // 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3).
917
+ // 20. Call the [[DefineOwnProperty]] internal method of F with
918
+ // arguments "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]:
919
+ // thrower, [[Enumerable]]: false, [[Configurable]]: false}, and
920
+ // false.
921
+ // 21. Call the [[DefineOwnProperty]] internal method of F with
922
+ // arguments "arguments", PropertyDescriptor {[[Get]]: thrower,
923
+ // [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false},
924
+ // and false.
925
+
926
+ // TODO
927
+ // NOTE Function objects created using Function.prototype.bind do not
928
+ // have a prototype property or the [[Code]], [[FormalParameters]], and
929
+ // [[Scope]] internal properties.
930
+ // XXX can't delete prototype in pure-js.
931
+
932
+ // 22. Return F.
933
+ return bound;
853
934
  }
854
- }
855
-
856
- return map;
857
- }
858
- });
935
+ });
936
+ })
937
+ .call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
859
938
 
860
- }).call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
939
+ /* eslint-disable es-x/no-function-prototype-bind -- Polyfill imported */
861
940
 
862
- (function(undefined) {
941
+ /**
942
+ * JavaScript enhancements for the ErrorSummary
943
+ *
944
+ * Takes focus on initialisation for accessible announcement, unless disabled in configuration.
945
+ *
946
+ * @class
947
+ * @param {HTMLElement} $module - HTML element to use for error summary
948
+ * @param {ErrorSummaryConfig} [config] - Error summary config
949
+ */
950
+ function ErrorSummary ($module, config) {
951
+ // Some consuming code may not be passing a module,
952
+ // for example if they initialise the component
953
+ // on their own by directly passing the result
954
+ // of `document.querySelector`.
955
+ // To avoid breaking further JavaScript initialisation
956
+ // we need to safeguard against this so things keep
957
+ // working the same now we read the elements data attributes
958
+ if (!$module) {
959
+ // Little safety in case code gets ported as-is
960
+ // into and ES6 class constructor, where the return value matters
961
+ return this
962
+ }
863
963
 
864
- // Detection from https://github.com/mdn/content/blob/cf607d68522cd35ee7670782d3ee3a361eaef2e4/files/en-us/web/javascript/reference/global_objects/string/trim/index.md#polyfill
865
- var detect = ('trim' in String.prototype);
866
-
867
- if (detect) return
964
+ this.$module = $module;
868
965
 
869
- // Polyfill from https://github.com/mdn/content/blob/cf607d68522cd35ee7670782d3ee3a361eaef2e4/files/en-us/web/javascript/reference/global_objects/string/trim/index.md#polyfill
870
- String.prototype.trim = function () {
871
- return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
966
+ var defaultConfig = {
967
+ disableAutoFocus: false
872
968
  };
873
-
874
- }).call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
875
-
876
- /**
877
- * Normalise string
878
- *
879
- * 'If it looks like a duck, and it quacks like a duck…' 🦆
880
- *
881
- * If the passed value looks like a boolean or a number, convert it to a boolean
882
- * or number.
883
- *
884
- * Designed to be used to convert config passed via data attributes (which are
885
- * always strings) into something sensible.
886
- *
887
- * @param {string} value - The value to normalise
888
- * @returns {string | boolean | number | undefined} Normalised data
889
- */
890
- function normaliseString (value) {
891
- if (typeof value !== 'string') {
892
- return value
969
+ this.config = mergeConfigs(
970
+ defaultConfig,
971
+ config || {},
972
+ normaliseDataset($module.dataset)
973
+ );
893
974
  }
894
975
 
895
- var trimmedValue = value.trim();
976
+ /**
977
+ * Initialise component
978
+ */
979
+ ErrorSummary.prototype.init = function () {
980
+ var $module = this.$module;
981
+ if (!$module) {
982
+ return
983
+ }
896
984
 
897
- if (trimmedValue === 'true') {
898
- return true
899
- }
985
+ this.setFocus();
986
+ $module.addEventListener('click', this.handleClick.bind(this));
987
+ };
900
988
 
901
- if (trimmedValue === 'false') {
902
- return false
903
- }
989
+ /**
990
+ * Focus the error summary
991
+ */
992
+ ErrorSummary.prototype.setFocus = function () {
993
+ var $module = this.$module;
904
994
 
905
- // Empty / whitespace-only strings are considered finite so we need to check
906
- // the length of the trimmed string as well
907
- if (trimmedValue.length > 0 && isFinite(trimmedValue)) {
908
- return Number(trimmedValue)
909
- }
995
+ if (this.config.disableAutoFocus) {
996
+ return
997
+ }
910
998
 
911
- return value
912
- }
913
-
914
- /**
915
- * Normalise dataset
916
- *
917
- * Loop over an object and normalise each value using normaliseData function
918
- *
919
- * @param {DOMStringMap} dataset - HTML element dataset
920
- * @returns {Object<string, string | boolean | number | undefined>} Normalised dataset
921
- */
922
- function normaliseDataset (dataset) {
923
- var out = {};
924
-
925
- for (var key in dataset) {
926
- out[key] = normaliseString(dataset[key]);
927
- }
999
+ // Set tabindex to -1 to make the element programmatically focusable, but
1000
+ // remove it on blur as the error summary doesn't need to be focused again.
1001
+ $module.setAttribute('tabindex', '-1');
928
1002
 
929
- return out
930
- }
931
-
932
- /**
933
- * JavaScript enhancements for the ErrorSummary
934
- *
935
- * Takes focus on initialisation for accessible announcement, unless disabled in configuration.
936
- *
937
- * @class
938
- * @param {HTMLElement} $module - The element this component controls
939
- * @param {ErrorSummaryConfig} config - Error summary config
940
- */
941
- function ErrorSummary ($module, config) {
942
- // Some consuming code may not be passing a module,
943
- // for example if they initialise the component
944
- // on their own by directly passing the result
945
- // of `document.querySelector`.
946
- // To avoid breaking further JavaScript initialisation
947
- // we need to safeguard against this so things keep
948
- // working the same now we read the elements data attributes
949
- if (!$module) {
950
- // Little safety in case code gets ported as-is
951
- // into and ES6 class constructor, where the return value matters
952
- return this
953
- }
1003
+ $module.addEventListener('blur', function () {
1004
+ $module.removeAttribute('tabindex');
1005
+ });
954
1006
 
955
- this.$module = $module;
1007
+ $module.focus();
1008
+ };
956
1009
 
957
- var defaultConfig = {
958
- disableAutoFocus: false
1010
+ /**
1011
+ * Click event handler
1012
+ *
1013
+ * @param {MouseEvent} event - Click event
1014
+ */
1015
+ ErrorSummary.prototype.handleClick = function (event) {
1016
+ var $target = event.target;
1017
+ if (this.focusTarget($target)) {
1018
+ event.preventDefault();
1019
+ }
959
1020
  };
960
- this.config = mergeConfigs(
961
- defaultConfig,
962
- config || {},
963
- normaliseDataset($module.dataset)
964
- );
965
- }
966
1021
 
967
- ErrorSummary.prototype.init = function () {
968
- var $module = this.$module;
969
- if (!$module) {
970
- return
971
- }
1022
+ /**
1023
+ * Focus the target element
1024
+ *
1025
+ * By default, the browser will scroll the target into view. Because our labels
1026
+ * or legends appear above the input, this means the user will be presented with
1027
+ * an input without any context, as the label or legend will be off the top of
1028
+ * the screen.
1029
+ *
1030
+ * Manually handling the click event, scrolling the question into view and then
1031
+ * focussing the element solves this.
1032
+ *
1033
+ * This also results in the label and/or legend being announced correctly in
1034
+ * NVDA (as tested in 2018.3.2) - without this only the field type is announced
1035
+ * (e.g. "Edit, has autocomplete").
1036
+ *
1037
+ * @param {EventTarget} $target - Event target
1038
+ * @returns {boolean} True if the target was able to be focussed
1039
+ */
1040
+ ErrorSummary.prototype.focusTarget = function ($target) {
1041
+ // If the element that was clicked was not a link, return early
1042
+ if ($target.tagName !== 'A' || $target.href === false) {
1043
+ return false
1044
+ }
972
1045
 
973
- this.setFocus();
974
- $module.addEventListener('click', this.handleClick.bind(this));
975
- };
1046
+ var inputId = this.getFragmentFromUrl($target.href);
1047
+ var $input = document.getElementById(inputId);
1048
+ if (!$input) {
1049
+ return false
1050
+ }
976
1051
 
977
- /**
978
- * Focus the error summary
979
- */
980
- ErrorSummary.prototype.setFocus = function () {
981
- var $module = this.$module;
1052
+ var $legendOrLabel = this.getAssociatedLegendOrLabel($input);
1053
+ if (!$legendOrLabel) {
1054
+ return false
1055
+ }
982
1056
 
983
- if (this.config.disableAutoFocus) {
984
- return
985
- }
1057
+ // Scroll the legend or label into view *before* calling focus on the input to
1058
+ // avoid extra scrolling in browsers that don't support `preventScroll` (which
1059
+ // at time of writing is most of them...)
1060
+ $legendOrLabel.scrollIntoView();
1061
+ $input.focus({ preventScroll: true });
986
1062
 
987
- // Set tabindex to -1 to make the element programmatically focusable, but
988
- // remove it on blur as the error summary doesn't need to be focused again.
989
- $module.setAttribute('tabindex', '-1');
990
-
991
- $module.addEventListener('blur', function () {
992
- $module.removeAttribute('tabindex');
993
- });
994
-
995
- $module.focus();
996
- };
997
-
998
- /**
999
- * Click event handler
1000
- *
1001
- * @param {MouseEvent} event - Click event
1002
- */
1003
- ErrorSummary.prototype.handleClick = function (event) {
1004
- var target = event.target;
1005
- if (this.focusTarget(target)) {
1006
- event.preventDefault();
1007
- }
1008
- };
1009
-
1010
- /**
1011
- * Focus the target element
1012
- *
1013
- * By default, the browser will scroll the target into view. Because our labels
1014
- * or legends appear above the input, this means the user will be presented with
1015
- * an input without any context, as the label or legend will be off the top of
1016
- * the screen.
1017
- *
1018
- * Manually handling the click event, scrolling the question into view and then
1019
- * focussing the element solves this.
1020
- *
1021
- * This also results in the label and/or legend being announced correctly in
1022
- * NVDA (as tested in 2018.3.2) - without this only the field type is announced
1023
- * (e.g. "Edit, has autocomplete").
1024
- *
1025
- * @param {HTMLElement} $target - Event target
1026
- * @returns {boolean} True if the target was able to be focussed
1027
- */
1028
- ErrorSummary.prototype.focusTarget = function ($target) {
1029
- // If the element that was clicked was not a link, return early
1030
- if ($target.tagName !== 'A' || $target.href === false) {
1031
- return false
1032
- }
1063
+ return true
1064
+ };
1033
1065
 
1034
- var inputId = this.getFragmentFromUrl($target.href);
1035
- var $input = document.getElementById(inputId);
1036
- if (!$input) {
1037
- return false
1038
- }
1066
+ /**
1067
+ * Get fragment from URL
1068
+ *
1069
+ * Extract the fragment (everything after the hash) from a URL, but not including
1070
+ * the hash.
1071
+ *
1072
+ * @param {string} url - URL
1073
+ * @returns {string} Fragment from URL, without the hash
1074
+ */
1075
+ ErrorSummary.prototype.getFragmentFromUrl = function (url) {
1076
+ if (url.indexOf('#') === -1) {
1077
+ return false
1078
+ }
1039
1079
 
1040
- var $legendOrLabel = this.getAssociatedLegendOrLabel($input);
1041
- if (!$legendOrLabel) {
1042
- return false
1043
- }
1080
+ return url.split('#').pop()
1081
+ };
1044
1082
 
1045
- // Scroll the legend or label into view *before* calling focus on the input to
1046
- // avoid extra scrolling in browsers that don't support `preventScroll` (which
1047
- // at time of writing is most of them...)
1048
- $legendOrLabel.scrollIntoView();
1049
- $input.focus({ preventScroll: true });
1050
-
1051
- return true
1052
- };
1053
-
1054
- /**
1055
- * Get fragment from URL
1056
- *
1057
- * Extract the fragment (everything after the hash) from a URL, but not including
1058
- * the hash.
1059
- *
1060
- * @param {string} url - URL
1061
- * @returns {string} Fragment from URL, without the hash
1062
- */
1063
- ErrorSummary.prototype.getFragmentFromUrl = function (url) {
1064
- if (url.indexOf('#') === -1) {
1065
- return false
1066
- }
1083
+ /**
1084
+ * Get associated legend or label
1085
+ *
1086
+ * Returns the first element that exists from this list:
1087
+ *
1088
+ * - The `<legend>` associated with the closest `<fieldset>` ancestor, as long
1089
+ * as the top of it is no more than half a viewport height away from the
1090
+ * bottom of the input
1091
+ * - The first `<label>` that is associated with the input using for="inputId"
1092
+ * - The closest parent `<label>`
1093
+ *
1094
+ * @param {HTMLElement} $input - The input
1095
+ * @returns {HTMLElement} Associated legend or label, or null if no associated
1096
+ * legend or label can be found
1097
+ */
1098
+ ErrorSummary.prototype.getAssociatedLegendOrLabel = function ($input) {
1099
+ var $fieldset = $input.closest('fieldset');
1067
1100
 
1068
- return url.split('#').pop()
1069
- };
1070
-
1071
- /**
1072
- * Get associated legend or label
1073
- *
1074
- * Returns the first element that exists from this list:
1075
- *
1076
- * - The `<legend>` associated with the closest `<fieldset>` ancestor, as long
1077
- * as the top of it is no more than half a viewport height away from the
1078
- * bottom of the input
1079
- * - The first `<label>` that is associated with the input using for="inputId"
1080
- * - The closest parent `<label>`
1081
- *
1082
- * @param {HTMLElement} $input - The input
1083
- * @returns {HTMLElement} Associated legend or label, or null if no associated
1084
- * legend or label can be found
1085
- */
1086
- ErrorSummary.prototype.getAssociatedLegendOrLabel = function ($input) {
1087
- var $fieldset = $input.closest('fieldset');
1088
-
1089
- if ($fieldset) {
1090
- var legends = $fieldset.getElementsByTagName('legend');
1091
-
1092
- if (legends.length) {
1093
- var $candidateLegend = legends[0];
1094
-
1095
- // If the input type is radio or checkbox, always use the legend if there
1096
- // is one.
1097
- if ($input.type === 'checkbox' || $input.type === 'radio') {
1098
- return $candidateLegend
1099
- }
1101
+ if ($fieldset) {
1102
+ var $legends = $fieldset.getElementsByTagName('legend');
1100
1103
 
1101
- // For other input types, only scroll to the fieldset’s legend (instead of
1102
- // the label associated with the input) if the input would end up in the
1103
- // top half of the screen.
1104
- //
1105
- // This should avoid situations where the input either ends up off the
1106
- // screen, or obscured by a software keyboard.
1107
- var legendTop = $candidateLegend.getBoundingClientRect().top;
1108
- var inputRect = $input.getBoundingClientRect();
1109
-
1110
- // If the browser doesn't support Element.getBoundingClientRect().height
1111
- // or window.innerHeight (like IE8), bail and just link to the label.
1112
- if (inputRect.height && window.innerHeight) {
1113
- var inputBottom = inputRect.top + inputRect.height;
1114
-
1115
- if (inputBottom - legendTop < window.innerHeight / 2) {
1104
+ if ($legends.length) {
1105
+ var $candidateLegend = $legends[0];
1106
+
1107
+ // If the input type is radio or checkbox, always use the legend if there
1108
+ // is one.
1109
+ if ($input.type === 'checkbox' || $input.type === 'radio') {
1116
1110
  return $candidateLegend
1117
1111
  }
1112
+
1113
+ // For other input types, only scroll to the fieldset’s legend (instead of
1114
+ // the label associated with the input) if the input would end up in the
1115
+ // top half of the screen.
1116
+ //
1117
+ // This should avoid situations where the input either ends up off the
1118
+ // screen, or obscured by a software keyboard.
1119
+ var legendTop = $candidateLegend.getBoundingClientRect().top;
1120
+ var inputRect = $input.getBoundingClientRect();
1121
+
1122
+ // If the browser doesn't support Element.getBoundingClientRect().height
1123
+ // or window.innerHeight (like IE8), bail and just link to the label.
1124
+ if (inputRect.height && window.innerHeight) {
1125
+ var inputBottom = inputRect.top + inputRect.height;
1126
+
1127
+ if (inputBottom - legendTop < window.innerHeight / 2) {
1128
+ return $candidateLegend
1129
+ }
1130
+ }
1118
1131
  }
1119
1132
  }
1120
- }
1121
1133
 
1122
- return document.querySelector("label[for='" + $input.getAttribute('id') + "']") ||
1123
- $input.closest('label')
1124
- };
1134
+ return document.querySelector("label[for='" + $input.getAttribute('id') + "']") ||
1135
+ $input.closest('label')
1136
+ };
1125
1137
 
1126
- /**
1127
- * Error summary config
1128
- *
1129
- * @typedef {object} ErrorSummaryConfig
1130
- * @property {boolean} [disableAutoFocus = false] -
1131
- * If set to `true` the error summary will not be focussed when the page loads.
1132
- */
1138
+ /**
1139
+ * Error summary config
1140
+ *
1141
+ * @typedef {object} ErrorSummaryConfig
1142
+ * @property {boolean} [disableAutoFocus = false] -
1143
+ * If set to `true` the error summary will not be focussed when the page loads.
1144
+ */
1133
1145
 
1134
- return ErrorSummary;
1146
+ return ErrorSummary;
1135
1147
 
1136
1148
  })));
1149
+ //# sourceMappingURL=error-summary.js.map