katalyst-govuk-formbuilder 1.2.2 → 1.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/app/assets/builds/katalyst/govuk/formbuilder.css +25 -21
- data/app/assets/{javascripts → builds}/katalyst/govuk/formbuilder.js +606 -203
- data/app/assets/builds/katalyst/govuk/formbuilder.min.js +1 -0
- data/app/assets/config/katalyst-govuk-formbuilder.js +2 -0
- data/app/assets/stylesheets/katalyst/govuk/components/richtextarea/_index.scss +48 -0
- data/app/assets/stylesheets/katalyst/govuk/components/richtextarea/_richtextarea.scss +2 -0
- data/app/assets/stylesheets/katalyst/govuk/formbuilder.scss +26 -0
- data/config/importmap.rb +5 -0
- data/lib/govuk_design_system_formbuilder/elements/check_box_field.rb +5 -5
- data/lib/govuk_design_system_formbuilder/elements/rich_text_area.rb +2 -1
- data/lib/katalyst/govuk/formbuilder/engine.rb +3 -8
- data/lib/katalyst/govuk/formbuilder/frontend.rb +2 -0
- data/lib/katalyst/govuk/formbuilder/version.rb +3 -1
- data/lib/katalyst/govuk/formbuilder.rb +2 -0
- metadata +8 -4
- data/app/assets/javascripts/katalyst/govuk/formbuilder.min.js +0 -1
@@ -7,18 +7,122 @@ function nodeListForEach(nodes, callback) {
|
|
7
7
|
}
|
8
8
|
}
|
9
9
|
|
10
|
+
function mergeConfigs() {
|
11
|
+
var flattenObject = function(configObject) {
|
12
|
+
var flattenedObject = {};
|
13
|
+
var flattenLoop = function(obj, prefix) {
|
14
|
+
for (var key in obj) {
|
15
|
+
if (!Object.prototype.hasOwnProperty.call(obj, key)) {
|
16
|
+
continue;
|
17
|
+
}
|
18
|
+
var value = obj[key];
|
19
|
+
var prefixedKey = prefix ? prefix + "." + key : key;
|
20
|
+
if (typeof value === "object") {
|
21
|
+
flattenLoop(value, prefixedKey);
|
22
|
+
} else {
|
23
|
+
flattenedObject[prefixedKey] = value;
|
24
|
+
}
|
25
|
+
}
|
26
|
+
};
|
27
|
+
flattenLoop(configObject);
|
28
|
+
return flattenedObject;
|
29
|
+
};
|
30
|
+
var formattedConfigObject = {};
|
31
|
+
for (var i = 0; i < arguments.length; i++) {
|
32
|
+
var obj = flattenObject(arguments[i]);
|
33
|
+
for (var key in obj) {
|
34
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
35
|
+
formattedConfigObject[key] = obj[key];
|
36
|
+
}
|
37
|
+
}
|
38
|
+
}
|
39
|
+
return formattedConfigObject;
|
40
|
+
}
|
41
|
+
|
42
|
+
function extractConfigByNamespace(configObject, namespace) {
|
43
|
+
if (!configObject || typeof configObject !== "object") {
|
44
|
+
throw new Error('Provide a `configObject` of type "object".');
|
45
|
+
}
|
46
|
+
if (!namespace || typeof namespace !== "string") {
|
47
|
+
throw new Error('Provide a `namespace` of type "string" to filter the `configObject` by.');
|
48
|
+
}
|
49
|
+
var newObject = {};
|
50
|
+
for (var key in configObject) {
|
51
|
+
var keyParts = key.split(".");
|
52
|
+
if (Object.prototype.hasOwnProperty.call(configObject, key) && keyParts[0] === namespace) {
|
53
|
+
if (keyParts.length > 1) {
|
54
|
+
keyParts.shift();
|
55
|
+
}
|
56
|
+
var newKey = keyParts.join(".");
|
57
|
+
newObject[newKey] = configObject[key];
|
58
|
+
}
|
59
|
+
}
|
60
|
+
return newObject;
|
61
|
+
}
|
62
|
+
|
10
63
|
(function(undefined$1) {
|
11
|
-
var detect = "
|
64
|
+
var detect = "defineProperty" in Object && function() {
|
65
|
+
try {
|
66
|
+
var a = {};
|
67
|
+
Object.defineProperty(a, "test", {
|
68
|
+
value: 42
|
69
|
+
});
|
70
|
+
return true;
|
71
|
+
} catch (e) {
|
72
|
+
return false;
|
73
|
+
}
|
74
|
+
}();
|
12
75
|
if (detect) return;
|
13
|
-
|
14
|
-
(
|
15
|
-
|
16
|
-
|
76
|
+
(function(nativeDefineProperty) {
|
77
|
+
var supportsAccessors = Object.prototype.hasOwnProperty("__defineGetter__");
|
78
|
+
var ERR_ACCESSORS_NOT_SUPPORTED = "Getters & setters cannot be defined on this javascript engine";
|
79
|
+
var ERR_VALUE_ACCESSORS = "A property cannot both have accessors and be writable or have a value";
|
80
|
+
Object.defineProperty = function defineProperty(object, property, descriptor) {
|
81
|
+
if (nativeDefineProperty && (object === window || object === document || object === Element.prototype || object instanceof Element)) {
|
82
|
+
return nativeDefineProperty(object, property, descriptor);
|
83
|
+
}
|
84
|
+
if (object === null || !(object instanceof Object || typeof object === "object")) {
|
85
|
+
throw new TypeError("Object.defineProperty called on non-object");
|
86
|
+
}
|
87
|
+
if (!(descriptor instanceof Object)) {
|
88
|
+
throw new TypeError("Property description must be an object");
|
89
|
+
}
|
90
|
+
var propertyString = String(property);
|
91
|
+
var hasValueOrWritable = "value" in descriptor || "writable" in descriptor;
|
92
|
+
var getterType = "get" in descriptor && typeof descriptor.get;
|
93
|
+
var setterType = "set" in descriptor && typeof descriptor.set;
|
94
|
+
if (getterType) {
|
95
|
+
if (getterType !== "function") {
|
96
|
+
throw new TypeError("Getter must be a function");
|
97
|
+
}
|
98
|
+
if (!supportsAccessors) {
|
99
|
+
throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);
|
100
|
+
}
|
101
|
+
if (hasValueOrWritable) {
|
102
|
+
throw new TypeError(ERR_VALUE_ACCESSORS);
|
103
|
+
}
|
104
|
+
Object.__defineGetter__.call(object, propertyString, descriptor.get);
|
17
105
|
} else {
|
18
|
-
|
106
|
+
object[propertyString] = descriptor.value;
|
19
107
|
}
|
20
|
-
|
21
|
-
|
108
|
+
if (setterType) {
|
109
|
+
if (setterType !== "function") {
|
110
|
+
throw new TypeError("Setter must be a function");
|
111
|
+
}
|
112
|
+
if (!supportsAccessors) {
|
113
|
+
throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);
|
114
|
+
}
|
115
|
+
if (hasValueOrWritable) {
|
116
|
+
throw new TypeError(ERR_VALUE_ACCESSORS);
|
117
|
+
}
|
118
|
+
Object.__defineSetter__.call(object, propertyString, descriptor.set);
|
119
|
+
}
|
120
|
+
if ("value" in descriptor) {
|
121
|
+
object[propertyString] = descriptor.value;
|
122
|
+
}
|
123
|
+
return object;
|
124
|
+
};
|
125
|
+
})(Object.defineProperty);
|
22
126
|
}).call("object" === typeof window && window || "object" === typeof self && self || "object" === typeof global && global || {});
|
23
127
|
|
24
128
|
(function(undefined$1) {
|
@@ -105,68 +209,99 @@ function nodeListForEach(nodes, callback) {
|
|
105
209
|
}).call("object" === typeof window && window || "object" === typeof self && self || "object" === typeof global && global || {});
|
106
210
|
|
107
211
|
(function(undefined$1) {
|
108
|
-
var detect =
|
109
|
-
|
110
|
-
var a = {};
|
111
|
-
Object.defineProperty(a, "test", {
|
112
|
-
value: 42
|
113
|
-
});
|
114
|
-
return true;
|
115
|
-
} catch (e) {
|
212
|
+
var detect = function() {
|
213
|
+
if (!document.documentElement.dataset) {
|
116
214
|
return false;
|
117
215
|
}
|
216
|
+
var el = document.createElement("div");
|
217
|
+
el.setAttribute("data-a-b", "c");
|
218
|
+
return el.dataset && el.dataset.aB == "c";
|
118
219
|
}();
|
119
220
|
if (detect) return;
|
120
|
-
(
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
if (setterType) {
|
153
|
-
if (setterType !== "function") {
|
154
|
-
throw new TypeError("Setter must be a function");
|
155
|
-
}
|
156
|
-
if (!supportsAccessors) {
|
157
|
-
throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);
|
158
|
-
}
|
159
|
-
if (hasValueOrWritable) {
|
160
|
-
throw new TypeError(ERR_VALUE_ACCESSORS);
|
221
|
+
Object.defineProperty(Element.prototype, "dataset", {
|
222
|
+
get: function() {
|
223
|
+
var element = this;
|
224
|
+
var attributes = this.attributes;
|
225
|
+
var map = {};
|
226
|
+
for (var i = 0; i < attributes.length; i++) {
|
227
|
+
var attribute = attributes[i];
|
228
|
+
if (attribute && attribute.name && /^data-\w[.\w-]*$/.test(attribute.name)) {
|
229
|
+
var name = attribute.name;
|
230
|
+
var value = attribute.value;
|
231
|
+
var propName = name.substr(5).replace(/-./g, (function(prop) {
|
232
|
+
return prop.charAt(1).toUpperCase();
|
233
|
+
}));
|
234
|
+
if ("__defineGetter__" in Object.prototype && "__defineSetter__" in Object.prototype) {
|
235
|
+
Object.defineProperty(map, propName, {
|
236
|
+
enumerable: true,
|
237
|
+
get: function() {
|
238
|
+
return this.value;
|
239
|
+
}.bind({
|
240
|
+
value: value || ""
|
241
|
+
}),
|
242
|
+
set: function setter(name, value) {
|
243
|
+
if (typeof value !== "undefined") {
|
244
|
+
this.setAttribute(name, value);
|
245
|
+
} else {
|
246
|
+
this.removeAttribute(name);
|
247
|
+
}
|
248
|
+
}.bind(element, name)
|
249
|
+
});
|
250
|
+
} else {
|
251
|
+
map[propName] = value;
|
252
|
+
}
|
161
253
|
}
|
162
|
-
Object.__defineSetter__.call(object, propertyString, descriptor.set);
|
163
254
|
}
|
164
|
-
|
165
|
-
|
255
|
+
return map;
|
256
|
+
}
|
257
|
+
});
|
258
|
+
}).call("object" === typeof window && window || "object" === typeof self && self || "object" === typeof global && global || {});
|
259
|
+
|
260
|
+
(function(undefined$1) {
|
261
|
+
var detect = "trim" in String.prototype;
|
262
|
+
if (detect) return;
|
263
|
+
String.prototype.trim = function() {
|
264
|
+
return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, "");
|
265
|
+
};
|
266
|
+
}).call("object" === typeof window && window || "object" === typeof self && self || "object" === typeof global && global || {});
|
267
|
+
|
268
|
+
function normaliseString(value) {
|
269
|
+
if (typeof value !== "string") {
|
270
|
+
return value;
|
271
|
+
}
|
272
|
+
var trimmedValue = value.trim();
|
273
|
+
if (trimmedValue === "true") {
|
274
|
+
return true;
|
275
|
+
}
|
276
|
+
if (trimmedValue === "false") {
|
277
|
+
return false;
|
278
|
+
}
|
279
|
+
if (trimmedValue.length > 0 && isFinite(trimmedValue)) {
|
280
|
+
return Number(trimmedValue);
|
281
|
+
}
|
282
|
+
return value;
|
283
|
+
}
|
284
|
+
|
285
|
+
function normaliseDataset(dataset) {
|
286
|
+
var out = {};
|
287
|
+
for (var key in dataset) {
|
288
|
+
out[key] = normaliseString(dataset[key]);
|
289
|
+
}
|
290
|
+
return out;
|
291
|
+
}
|
292
|
+
|
293
|
+
(function(undefined$1) {
|
294
|
+
var detect = "Window" in this;
|
295
|
+
if (detect) return;
|
296
|
+
if (typeof WorkerGlobalScope === "undefined" && typeof importScripts !== "function") {
|
297
|
+
(function(global) {
|
298
|
+
if (global.constructor) {
|
299
|
+
global.Window = global.constructor;
|
300
|
+
} else {
|
301
|
+
(global.Window = global.constructor = new Function("return function Window() {}")()).prototype = this;
|
166
302
|
}
|
167
|
-
|
168
|
-
|
169
|
-
})(Object.defineProperty);
|
303
|
+
})(this);
|
304
|
+
}
|
170
305
|
}).call("object" === typeof window && window || "object" === typeof self && self || "object" === typeof global && global || {});
|
171
306
|
|
172
307
|
(function(undefined$1) {
|
@@ -415,22 +550,36 @@ var KEY_SPACE = 32;
|
|
415
550
|
|
416
551
|
var DEBOUNCE_TIMEOUT_IN_SECONDS = 1;
|
417
552
|
|
418
|
-
function Button($module) {
|
553
|
+
function Button($module, config) {
|
554
|
+
if (!$module) {
|
555
|
+
return this;
|
556
|
+
}
|
419
557
|
this.$module = $module;
|
420
558
|
this.debounceFormSubmitTimer = null;
|
559
|
+
var defaultConfig = {
|
560
|
+
preventDoubleClick: false
|
561
|
+
};
|
562
|
+
this.config = mergeConfigs(defaultConfig, config || {}, normaliseDataset($module.dataset));
|
421
563
|
}
|
422
564
|
|
565
|
+
Button.prototype.init = function() {
|
566
|
+
if (!this.$module) {
|
567
|
+
return;
|
568
|
+
}
|
569
|
+
this.$module.addEventListener("keydown", this.handleKeyDown);
|
570
|
+
this.$module.addEventListener("click", this.debounce.bind(this));
|
571
|
+
};
|
572
|
+
|
423
573
|
Button.prototype.handleKeyDown = function(event) {
|
424
|
-
var target = event.target;
|
425
|
-
if (target.getAttribute("role") === "button" && event.keyCode === KEY_SPACE) {
|
574
|
+
var $target = event.target;
|
575
|
+
if ($target.getAttribute("role") === "button" && event.keyCode === KEY_SPACE) {
|
426
576
|
event.preventDefault();
|
427
|
-
target.click();
|
577
|
+
$target.click();
|
428
578
|
}
|
429
579
|
};
|
430
580
|
|
431
581
|
Button.prototype.debounce = function(event) {
|
432
|
-
|
433
|
-
if (target.getAttribute("data-prevent-double-click") !== "true") {
|
582
|
+
if (!this.config.preventDoubleClick) {
|
434
583
|
return;
|
435
584
|
}
|
436
585
|
if (this.debounceFormSubmitTimer) {
|
@@ -442,11 +591,260 @@ Button.prototype.debounce = function(event) {
|
|
442
591
|
}.bind(this), DEBOUNCE_TIMEOUT_IN_SECONDS * 1e3);
|
443
592
|
};
|
444
593
|
|
445
|
-
|
446
|
-
this
|
447
|
-
|
594
|
+
(function(undefined$1) {
|
595
|
+
var detect = "document" in this && "matches" in document.documentElement;
|
596
|
+
if (detect) return;
|
597
|
+
Element.prototype.matches = Element.prototype.webkitMatchesSelector || Element.prototype.oMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.mozMatchesSelector || function matches(selector) {
|
598
|
+
var element = this;
|
599
|
+
var elements = (element.document || element.ownerDocument).querySelectorAll(selector);
|
600
|
+
var index = 0;
|
601
|
+
while (elements[index] && elements[index] !== element) {
|
602
|
+
++index;
|
603
|
+
}
|
604
|
+
return !!elements[index];
|
605
|
+
};
|
606
|
+
}).call("object" === typeof window && window || "object" === typeof self && self || "object" === typeof global && global || {});
|
607
|
+
|
608
|
+
(function(undefined$1) {
|
609
|
+
var detect = "document" in this && "closest" in document.documentElement;
|
610
|
+
if (detect) return;
|
611
|
+
Element.prototype.closest = function closest(selector) {
|
612
|
+
var node = this;
|
613
|
+
while (node) {
|
614
|
+
if (node.matches(selector)) return node; else node = "SVGElement" in window && node instanceof SVGElement ? node.parentNode : node.parentElement;
|
615
|
+
}
|
616
|
+
return null;
|
617
|
+
};
|
618
|
+
}).call("object" === typeof window && window || "object" === typeof self && self || "object" === typeof global && global || {});
|
619
|
+
|
620
|
+
function closestAttributeValue($element, attributeName) {
|
621
|
+
var closestElementWithAttribute = $element.closest("[" + attributeName + "]");
|
622
|
+
if (closestElementWithAttribute) {
|
623
|
+
return closestElementWithAttribute.getAttribute(attributeName);
|
624
|
+
}
|
625
|
+
}
|
626
|
+
|
627
|
+
function I18n(translations, config) {
|
628
|
+
this.translations = translations || {};
|
629
|
+
this.locale = config && config.locale || document.documentElement.lang || "en";
|
630
|
+
}
|
631
|
+
|
632
|
+
I18n.prototype.t = function(lookupKey, options) {
|
633
|
+
if (!lookupKey) {
|
634
|
+
throw new Error("i18n: lookup key missing");
|
635
|
+
}
|
636
|
+
if (options && typeof options.count !== "undefined") {
|
637
|
+
lookupKey = lookupKey + "." + this.getPluralSuffix(lookupKey, options.count);
|
638
|
+
}
|
639
|
+
if (lookupKey in this.translations) {
|
640
|
+
var translationString = this.translations[lookupKey];
|
641
|
+
if (translationString.match(/%{(.\S+)}/)) {
|
642
|
+
if (!options) {
|
643
|
+
throw new Error("i18n: cannot replace placeholders in string if no option data provided");
|
644
|
+
}
|
645
|
+
return this.replacePlaceholders(translationString, options);
|
646
|
+
} else {
|
647
|
+
return translationString;
|
648
|
+
}
|
649
|
+
} else {
|
650
|
+
return lookupKey;
|
651
|
+
}
|
652
|
+
};
|
653
|
+
|
654
|
+
I18n.prototype.replacePlaceholders = function(translationString, options) {
|
655
|
+
var formatter;
|
656
|
+
if (this.hasIntlNumberFormatSupport()) {
|
657
|
+
formatter = new Intl.NumberFormat(this.locale);
|
658
|
+
}
|
659
|
+
return translationString.replace(/%{(.\S+)}/g, (function(placeholderWithBraces, placeholderKey) {
|
660
|
+
if (Object.prototype.hasOwnProperty.call(options, placeholderKey)) {
|
661
|
+
var placeholderValue = options[placeholderKey];
|
662
|
+
if (placeholderValue === false) {
|
663
|
+
return "";
|
664
|
+
}
|
665
|
+
if (typeof placeholderValue === "number" && formatter) {
|
666
|
+
return formatter.format(placeholderValue);
|
667
|
+
}
|
668
|
+
return placeholderValue;
|
669
|
+
} else {
|
670
|
+
throw new Error("i18n: no data found to replace " + placeholderWithBraces + " placeholder in string");
|
671
|
+
}
|
672
|
+
}));
|
673
|
+
};
|
674
|
+
|
675
|
+
I18n.prototype.hasIntlPluralRulesSupport = function() {
|
676
|
+
return Boolean(window.Intl && ("PluralRules" in window.Intl && Intl.PluralRules.supportedLocalesOf(this.locale).length));
|
677
|
+
};
|
678
|
+
|
679
|
+
I18n.prototype.hasIntlNumberFormatSupport = function() {
|
680
|
+
return Boolean(window.Intl && ("NumberFormat" in window.Intl && Intl.NumberFormat.supportedLocalesOf(this.locale).length));
|
681
|
+
};
|
682
|
+
|
683
|
+
I18n.prototype.getPluralSuffix = function(lookupKey, count) {
|
684
|
+
count = Number(count);
|
685
|
+
if (!isFinite(count)) {
|
686
|
+
return "other";
|
687
|
+
}
|
688
|
+
var preferredForm;
|
689
|
+
if (this.hasIntlPluralRulesSupport()) {
|
690
|
+
preferredForm = new Intl.PluralRules(this.locale).select(count);
|
691
|
+
} else {
|
692
|
+
preferredForm = this.selectPluralFormUsingFallbackRules(count);
|
693
|
+
}
|
694
|
+
if (lookupKey + "." + preferredForm in this.translations) {
|
695
|
+
return preferredForm;
|
696
|
+
} else if (lookupKey + ".other" in this.translations) {
|
697
|
+
if (console && "warn" in console) {
|
698
|
+
console.warn('i18n: Missing plural form ".' + preferredForm + '" for "' + this.locale + '" locale. Falling back to ".other".');
|
699
|
+
}
|
700
|
+
return "other";
|
701
|
+
} else {
|
702
|
+
throw new Error('i18n: Plural form ".other" is required for "' + this.locale + '" locale');
|
703
|
+
}
|
704
|
+
};
|
705
|
+
|
706
|
+
I18n.prototype.selectPluralFormUsingFallbackRules = function(count) {
|
707
|
+
count = Math.abs(Math.floor(count));
|
708
|
+
var ruleset = this.getPluralRulesForLocale();
|
709
|
+
if (ruleset) {
|
710
|
+
return I18n.pluralRules[ruleset](count);
|
711
|
+
}
|
712
|
+
return "other";
|
448
713
|
};
|
449
714
|
|
715
|
+
I18n.prototype.getPluralRulesForLocale = function() {
|
716
|
+
var locale = this.locale;
|
717
|
+
var localeShort = locale.split("-")[0];
|
718
|
+
for (var pluralRule in I18n.pluralRulesMap) {
|
719
|
+
if (Object.prototype.hasOwnProperty.call(I18n.pluralRulesMap, pluralRule)) {
|
720
|
+
var languages = I18n.pluralRulesMap[pluralRule];
|
721
|
+
for (var i = 0; i < languages.length; i++) {
|
722
|
+
if (languages[i] === locale || languages[i] === localeShort) {
|
723
|
+
return pluralRule;
|
724
|
+
}
|
725
|
+
}
|
726
|
+
}
|
727
|
+
}
|
728
|
+
};
|
729
|
+
|
730
|
+
I18n.pluralRulesMap = {
|
731
|
+
arabic: [ "ar" ],
|
732
|
+
chinese: [ "my", "zh", "id", "ja", "jv", "ko", "ms", "th", "vi" ],
|
733
|
+
french: [ "hy", "bn", "fr", "gu", "hi", "fa", "pa", "zu" ],
|
734
|
+
german: [ "af", "sq", "az", "eu", "bg", "ca", "da", "nl", "en", "et", "fi", "ka", "de", "el", "hu", "lb", "no", "so", "sw", "sv", "ta", "te", "tr", "ur" ],
|
735
|
+
irish: [ "ga" ],
|
736
|
+
russian: [ "ru", "uk" ],
|
737
|
+
scottish: [ "gd" ],
|
738
|
+
spanish: [ "pt-PT", "it", "es" ],
|
739
|
+
welsh: [ "cy" ]
|
740
|
+
};
|
741
|
+
|
742
|
+
I18n.pluralRules = {
|
743
|
+
arabic: function(n) {
|
744
|
+
if (n === 0) {
|
745
|
+
return "zero";
|
746
|
+
}
|
747
|
+
if (n === 1) {
|
748
|
+
return "one";
|
749
|
+
}
|
750
|
+
if (n === 2) {
|
751
|
+
return "two";
|
752
|
+
}
|
753
|
+
if (n % 100 >= 3 && n % 100 <= 10) {
|
754
|
+
return "few";
|
755
|
+
}
|
756
|
+
if (n % 100 >= 11 && n % 100 <= 99) {
|
757
|
+
return "many";
|
758
|
+
}
|
759
|
+
return "other";
|
760
|
+
},
|
761
|
+
chinese: function() {
|
762
|
+
return "other";
|
763
|
+
},
|
764
|
+
french: function(n) {
|
765
|
+
return n === 0 || n === 1 ? "one" : "other";
|
766
|
+
},
|
767
|
+
german: function(n) {
|
768
|
+
return n === 1 ? "one" : "other";
|
769
|
+
},
|
770
|
+
irish: function(n) {
|
771
|
+
if (n === 1) {
|
772
|
+
return "one";
|
773
|
+
}
|
774
|
+
if (n === 2) {
|
775
|
+
return "two";
|
776
|
+
}
|
777
|
+
if (n >= 3 && n <= 6) {
|
778
|
+
return "few";
|
779
|
+
}
|
780
|
+
if (n >= 7 && n <= 10) {
|
781
|
+
return "many";
|
782
|
+
}
|
783
|
+
return "other";
|
784
|
+
},
|
785
|
+
russian: function(n) {
|
786
|
+
var lastTwo = n % 100;
|
787
|
+
var last = lastTwo % 10;
|
788
|
+
if (last === 1 && lastTwo !== 11) {
|
789
|
+
return "one";
|
790
|
+
}
|
791
|
+
if (last >= 2 && last <= 4 && !(lastTwo >= 12 && lastTwo <= 14)) {
|
792
|
+
return "few";
|
793
|
+
}
|
794
|
+
if (last === 0 || last >= 5 && last <= 9 || lastTwo >= 11 && lastTwo <= 14) {
|
795
|
+
return "many";
|
796
|
+
}
|
797
|
+
return "other";
|
798
|
+
},
|
799
|
+
scottish: function(n) {
|
800
|
+
if (n === 1 || n === 11) {
|
801
|
+
return "one";
|
802
|
+
}
|
803
|
+
if (n === 2 || n === 12) {
|
804
|
+
return "two";
|
805
|
+
}
|
806
|
+
if (n >= 3 && n <= 10 || n >= 13 && n <= 19) {
|
807
|
+
return "few";
|
808
|
+
}
|
809
|
+
return "other";
|
810
|
+
},
|
811
|
+
spanish: function(n) {
|
812
|
+
if (n === 1) {
|
813
|
+
return "one";
|
814
|
+
}
|
815
|
+
if (n % 1e6 === 0 && n !== 0) {
|
816
|
+
return "many";
|
817
|
+
}
|
818
|
+
return "other";
|
819
|
+
},
|
820
|
+
welsh: function(n) {
|
821
|
+
if (n === 0) {
|
822
|
+
return "zero";
|
823
|
+
}
|
824
|
+
if (n === 1) {
|
825
|
+
return "one";
|
826
|
+
}
|
827
|
+
if (n === 2) {
|
828
|
+
return "two";
|
829
|
+
}
|
830
|
+
if (n === 3) {
|
831
|
+
return "few";
|
832
|
+
}
|
833
|
+
if (n === 6) {
|
834
|
+
return "many";
|
835
|
+
}
|
836
|
+
return "other";
|
837
|
+
}
|
838
|
+
};
|
839
|
+
|
840
|
+
(function(undefined$1) {
|
841
|
+
var detect = "Date" in self && "now" in self.Date && "getTime" in self.Date.prototype;
|
842
|
+
if (detect) return;
|
843
|
+
Date.now = function() {
|
844
|
+
return (new Date).getTime();
|
845
|
+
};
|
846
|
+
}).call("object" === typeof window && window || "object" === typeof self && self || "object" === typeof global && global || {});
|
847
|
+
|
450
848
|
(function(undefined$1) {
|
451
849
|
var detect = "DOMTokenList" in this && function(x) {
|
452
850
|
return "classList" in x ? !x.classList.toggle("x", false) && !x.className : true;
|
@@ -685,7 +1083,57 @@ Button.prototype.init = function() {
|
|
685
1083
|
})(this);
|
686
1084
|
}).call("object" === typeof window && window || "object" === typeof self && self || "object" === typeof global && global || {});
|
687
1085
|
|
688
|
-
|
1086
|
+
var CHARACTER_COUNT_TRANSLATIONS = {
|
1087
|
+
charactersUnderLimit: {
|
1088
|
+
one: "You have %{count} character remaining",
|
1089
|
+
other: "You have %{count} characters remaining"
|
1090
|
+
},
|
1091
|
+
charactersAtLimit: "You have 0 characters remaining",
|
1092
|
+
charactersOverLimit: {
|
1093
|
+
one: "You have %{count} character too many",
|
1094
|
+
other: "You have %{count} characters too many"
|
1095
|
+
},
|
1096
|
+
wordsUnderLimit: {
|
1097
|
+
one: "You have %{count} word remaining",
|
1098
|
+
other: "You have %{count} words remaining"
|
1099
|
+
},
|
1100
|
+
wordsAtLimit: "You have 0 words remaining",
|
1101
|
+
wordsOverLimit: {
|
1102
|
+
one: "You have %{count} word too many",
|
1103
|
+
other: "You have %{count} words too many"
|
1104
|
+
},
|
1105
|
+
textareaDescription: {
|
1106
|
+
other: ""
|
1107
|
+
}
|
1108
|
+
};
|
1109
|
+
|
1110
|
+
function CharacterCount($module, config) {
|
1111
|
+
if (!$module) {
|
1112
|
+
return this;
|
1113
|
+
}
|
1114
|
+
var defaultConfig = {
|
1115
|
+
threshold: 0,
|
1116
|
+
i18n: CHARACTER_COUNT_TRANSLATIONS
|
1117
|
+
};
|
1118
|
+
var datasetConfig = normaliseDataset($module.dataset);
|
1119
|
+
var configOverrides = {};
|
1120
|
+
if ("maxwords" in datasetConfig || "maxlength" in datasetConfig) {
|
1121
|
+
configOverrides = {
|
1122
|
+
maxlength: false,
|
1123
|
+
maxwords: false
|
1124
|
+
};
|
1125
|
+
}
|
1126
|
+
this.config = mergeConfigs(defaultConfig, config || {}, configOverrides, datasetConfig);
|
1127
|
+
this.i18n = new I18n(extractConfigByNamespace(this.config, "i18n"), {
|
1128
|
+
locale: closestAttributeValue($module, "lang")
|
1129
|
+
});
|
1130
|
+
if (this.config.maxwords) {
|
1131
|
+
this.maxLength = this.config.maxwords;
|
1132
|
+
} else if (this.config.maxlength) {
|
1133
|
+
this.maxLength = this.config.maxlength;
|
1134
|
+
} else {
|
1135
|
+
return;
|
1136
|
+
}
|
689
1137
|
this.$module = $module;
|
690
1138
|
this.$textarea = $module.querySelector(".govuk-js-character-count");
|
691
1139
|
this.$visibleCountMessage = null;
|
@@ -693,40 +1141,30 @@ function CharacterCount($module) {
|
|
693
1141
|
this.lastInputTimestamp = null;
|
694
1142
|
}
|
695
1143
|
|
696
|
-
CharacterCount.prototype.defaults = {
|
697
|
-
characterCountAttribute: "data-maxlength",
|
698
|
-
wordCountAttribute: "data-maxwords"
|
699
|
-
};
|
700
|
-
|
701
1144
|
CharacterCount.prototype.init = function() {
|
702
1145
|
if (!this.$textarea) {
|
703
1146
|
return;
|
704
1147
|
}
|
705
|
-
var $module = this.$module;
|
706
1148
|
var $textarea = this.$textarea;
|
707
|
-
var $
|
708
|
-
$
|
1149
|
+
var $textareaDescription = document.getElementById($textarea.id + "-info");
|
1150
|
+
if ($textareaDescription.innerText.match(/^\s*$/)) {
|
1151
|
+
$textareaDescription.innerText = this.i18n.t("textareaDescription", {
|
1152
|
+
count: this.maxLength
|
1153
|
+
});
|
1154
|
+
}
|
1155
|
+
$textarea.insertAdjacentElement("afterend", $textareaDescription);
|
709
1156
|
var $screenReaderCountMessage = document.createElement("div");
|
710
1157
|
$screenReaderCountMessage.className = "govuk-character-count__sr-status govuk-visually-hidden";
|
711
1158
|
$screenReaderCountMessage.setAttribute("aria-live", "polite");
|
712
1159
|
this.$screenReaderCountMessage = $screenReaderCountMessage;
|
713
|
-
$
|
1160
|
+
$textareaDescription.insertAdjacentElement("afterend", $screenReaderCountMessage);
|
714
1161
|
var $visibleCountMessage = document.createElement("div");
|
715
|
-
$visibleCountMessage.className = $
|
1162
|
+
$visibleCountMessage.className = $textareaDescription.className;
|
716
1163
|
$visibleCountMessage.classList.add("govuk-character-count__status");
|
717
1164
|
$visibleCountMessage.setAttribute("aria-hidden", "true");
|
718
1165
|
this.$visibleCountMessage = $visibleCountMessage;
|
719
|
-
$
|
720
|
-
$
|
721
|
-
this.options = this.getDataset($module);
|
722
|
-
var countAttribute = this.defaults.characterCountAttribute;
|
723
|
-
if (this.options.maxwords) {
|
724
|
-
countAttribute = this.defaults.wordCountAttribute;
|
725
|
-
}
|
726
|
-
this.maxLength = $module.getAttribute(countAttribute);
|
727
|
-
if (!this.maxLength) {
|
728
|
-
return;
|
729
|
-
}
|
1166
|
+
$textareaDescription.insertAdjacentElement("afterend", $visibleCountMessage);
|
1167
|
+
$textareaDescription.classList.add("govuk-visually-hidden");
|
730
1168
|
$textarea.removeAttribute("maxlength");
|
731
1169
|
this.bindChangeEvents();
|
732
1170
|
if ("onpageshow" in window) {
|
@@ -737,32 +1175,6 @@ CharacterCount.prototype.init = function() {
|
|
737
1175
|
this.updateCountMessage();
|
738
1176
|
};
|
739
1177
|
|
740
|
-
CharacterCount.prototype.getDataset = function(element) {
|
741
|
-
var dataset = {};
|
742
|
-
var attributes = element.attributes;
|
743
|
-
if (attributes) {
|
744
|
-
for (var i = 0; i < attributes.length; i++) {
|
745
|
-
var attribute = attributes[i];
|
746
|
-
var match = attribute.name.match(/^data-(.+)/);
|
747
|
-
if (match) {
|
748
|
-
dataset[match[1]] = attribute.value;
|
749
|
-
}
|
750
|
-
}
|
751
|
-
}
|
752
|
-
return dataset;
|
753
|
-
};
|
754
|
-
|
755
|
-
CharacterCount.prototype.count = function(text) {
|
756
|
-
var length;
|
757
|
-
if (this.options.maxwords) {
|
758
|
-
var tokens = text.match(/\S+/g) || [];
|
759
|
-
length = tokens.length;
|
760
|
-
} else {
|
761
|
-
length = text.length;
|
762
|
-
}
|
763
|
-
return length;
|
764
|
-
};
|
765
|
-
|
766
1178
|
CharacterCount.prototype.bindChangeEvents = function() {
|
767
1179
|
var $textarea = this.$textarea;
|
768
1180
|
$textarea.addEventListener("keyup", this.handleKeyUp.bind(this));
|
@@ -770,7 +1182,24 @@ CharacterCount.prototype.bindChangeEvents = function() {
|
|
770
1182
|
$textarea.addEventListener("blur", this.handleBlur.bind(this));
|
771
1183
|
};
|
772
1184
|
|
773
|
-
CharacterCount.prototype.
|
1185
|
+
CharacterCount.prototype.handleKeyUp = function() {
|
1186
|
+
this.updateVisibleCountMessage();
|
1187
|
+
this.lastInputTimestamp = Date.now();
|
1188
|
+
};
|
1189
|
+
|
1190
|
+
CharacterCount.prototype.handleFocus = function() {
|
1191
|
+
this.valueChecker = setInterval(function() {
|
1192
|
+
if (!this.lastInputTimestamp || Date.now() - 500 >= this.lastInputTimestamp) {
|
1193
|
+
this.updateIfValueChanged();
|
1194
|
+
}
|
1195
|
+
}.bind(this), 1e3);
|
1196
|
+
};
|
1197
|
+
|
1198
|
+
CharacterCount.prototype.handleBlur = function() {
|
1199
|
+
clearInterval(this.valueChecker);
|
1200
|
+
};
|
1201
|
+
|
1202
|
+
CharacterCount.prototype.updateIfValueChanged = function() {
|
774
1203
|
if (!this.$textarea.oldValue) this.$textarea.oldValue = "";
|
775
1204
|
if (this.$textarea.value !== this.$textarea.oldValue) {
|
776
1205
|
this.$textarea.oldValue = this.$textarea.value;
|
@@ -801,7 +1230,7 @@ CharacterCount.prototype.updateVisibleCountMessage = function() {
|
|
801
1230
|
$visibleCountMessage.classList.remove("govuk-error-message");
|
802
1231
|
$visibleCountMessage.classList.add("govuk-hint");
|
803
1232
|
}
|
804
|
-
$visibleCountMessage.
|
1233
|
+
$visibleCountMessage.innerText = this.getCountMessage();
|
805
1234
|
};
|
806
1235
|
|
807
1236
|
CharacterCount.prototype.updateScreenReaderCountMessage = function() {
|
@@ -811,52 +1240,45 @@ CharacterCount.prototype.updateScreenReaderCountMessage = function() {
|
|
811
1240
|
} else {
|
812
1241
|
$screenReaderCountMessage.setAttribute("aria-hidden", true);
|
813
1242
|
}
|
814
|
-
$screenReaderCountMessage.
|
1243
|
+
$screenReaderCountMessage.innerText = this.getCountMessage();
|
815
1244
|
};
|
816
1245
|
|
817
|
-
CharacterCount.prototype.
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
1246
|
+
CharacterCount.prototype.count = function(text) {
|
1247
|
+
if (this.config.maxwords) {
|
1248
|
+
var tokens = text.match(/\S+/g) || [];
|
1249
|
+
return tokens.length;
|
1250
|
+
} else {
|
1251
|
+
return text.length;
|
1252
|
+
}
|
1253
|
+
};
|
1254
|
+
|
1255
|
+
CharacterCount.prototype.getCountMessage = function() {
|
1256
|
+
var remainingNumber = this.maxLength - this.count(this.$textarea.value);
|
1257
|
+
var countType = this.config.maxwords ? "words" : "characters";
|
1258
|
+
return this.formatCountMessage(remainingNumber, countType);
|
1259
|
+
};
|
1260
|
+
|
1261
|
+
CharacterCount.prototype.formatCountMessage = function(remainingNumber, countType) {
|
1262
|
+
if (remainingNumber === 0) {
|
1263
|
+
return this.i18n.t(countType + "AtLimit");
|
826
1264
|
}
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
1265
|
+
var translationKeySuffix = remainingNumber < 0 ? "OverLimit" : "UnderLimit";
|
1266
|
+
return this.i18n.t(countType + translationKeySuffix, {
|
1267
|
+
count: Math.abs(remainingNumber)
|
1268
|
+
});
|
831
1269
|
};
|
832
1270
|
|
833
1271
|
CharacterCount.prototype.isOverThreshold = function() {
|
1272
|
+
if (!this.config.threshold) {
|
1273
|
+
return true;
|
1274
|
+
}
|
834
1275
|
var $textarea = this.$textarea;
|
835
|
-
var options = this.options;
|
836
1276
|
var currentLength = this.count($textarea.value);
|
837
1277
|
var maxLength = this.maxLength;
|
838
|
-
var
|
839
|
-
var thresholdValue = maxLength * thresholdPercent / 100;
|
1278
|
+
var thresholdValue = maxLength * this.config.threshold / 100;
|
840
1279
|
return thresholdValue <= currentLength;
|
841
1280
|
};
|
842
1281
|
|
843
|
-
CharacterCount.prototype.handleKeyUp = function() {
|
844
|
-
this.updateVisibleCountMessage();
|
845
|
-
this.lastInputTimestamp = Date.now();
|
846
|
-
};
|
847
|
-
|
848
|
-
CharacterCount.prototype.handleFocus = function() {
|
849
|
-
this.valueChecker = setInterval(function() {
|
850
|
-
if (!this.lastInputTimestamp || Date.now() - 500 >= this.lastInputTimestamp) {
|
851
|
-
this.checkIfValueChanged();
|
852
|
-
}
|
853
|
-
}.bind(this), 1e3);
|
854
|
-
};
|
855
|
-
|
856
|
-
CharacterCount.prototype.handleBlur = function() {
|
857
|
-
clearInterval(this.valueChecker);
|
858
|
-
};
|
859
|
-
|
860
1282
|
function Checkboxes($module) {
|
861
1283
|
this.$module = $module;
|
862
1284
|
this.$inputs = $module.querySelectorAll('input[type="checkbox"]');
|
@@ -866,11 +1288,11 @@ Checkboxes.prototype.init = function() {
|
|
866
1288
|
var $module = this.$module;
|
867
1289
|
var $inputs = this.$inputs;
|
868
1290
|
nodeListForEach($inputs, (function($input) {
|
869
|
-
var
|
870
|
-
if (!
|
1291
|
+
var targetId = $input.getAttribute("data-aria-controls");
|
1292
|
+
if (!targetId || !document.getElementById(targetId)) {
|
871
1293
|
return;
|
872
1294
|
}
|
873
|
-
$input.setAttribute("aria-controls",
|
1295
|
+
$input.setAttribute("aria-controls", targetId);
|
874
1296
|
$input.removeAttribute("data-aria-controls");
|
875
1297
|
}));
|
876
1298
|
if ("onpageshow" in window) {
|
@@ -918,53 +1340,34 @@ Checkboxes.prototype.unCheckExclusiveInputs = function($input) {
|
|
918
1340
|
};
|
919
1341
|
|
920
1342
|
Checkboxes.prototype.handleClick = function(event) {
|
921
|
-
var $
|
922
|
-
if ($
|
1343
|
+
var $clickedInput = event.target;
|
1344
|
+
if ($clickedInput.type !== "checkbox") {
|
923
1345
|
return;
|
924
1346
|
}
|
925
|
-
var hasAriaControls = $
|
1347
|
+
var hasAriaControls = $clickedInput.getAttribute("aria-controls");
|
926
1348
|
if (hasAriaControls) {
|
927
|
-
this.syncConditionalRevealWithInputState($
|
1349
|
+
this.syncConditionalRevealWithInputState($clickedInput);
|
928
1350
|
}
|
929
|
-
if (!$
|
1351
|
+
if (!$clickedInput.checked) {
|
930
1352
|
return;
|
931
1353
|
}
|
932
|
-
var hasBehaviourExclusive = $
|
1354
|
+
var hasBehaviourExclusive = $clickedInput.getAttribute("data-behaviour") === "exclusive";
|
933
1355
|
if (hasBehaviourExclusive) {
|
934
|
-
this.unCheckAllInputsExcept($
|
1356
|
+
this.unCheckAllInputsExcept($clickedInput);
|
935
1357
|
} else {
|
936
|
-
this.unCheckExclusiveInputs($
|
1358
|
+
this.unCheckExclusiveInputs($clickedInput);
|
937
1359
|
}
|
938
1360
|
};
|
939
1361
|
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
var element = this;
|
945
|
-
var elements = (element.document || element.ownerDocument).querySelectorAll(selector);
|
946
|
-
var index = 0;
|
947
|
-
while (elements[index] && elements[index] !== element) {
|
948
|
-
++index;
|
949
|
-
}
|
950
|
-
return !!elements[index];
|
951
|
-
};
|
952
|
-
}).call("object" === typeof window && window || "object" === typeof self && self || "object" === typeof global && global || {});
|
953
|
-
|
954
|
-
(function(undefined$1) {
|
955
|
-
var detect = "document" in this && "closest" in document.documentElement;
|
956
|
-
if (detect) return;
|
957
|
-
Element.prototype.closest = function closest(selector) {
|
958
|
-
var node = this;
|
959
|
-
while (node) {
|
960
|
-
if (node.matches(selector)) return node; else node = "SVGElement" in window && node instanceof SVGElement ? node.parentNode : node.parentElement;
|
961
|
-
}
|
962
|
-
return null;
|
963
|
-
};
|
964
|
-
}).call("object" === typeof window && window || "object" === typeof self && self || "object" === typeof global && global || {});
|
965
|
-
|
966
|
-
function ErrorSummary($module) {
|
1362
|
+
function ErrorSummary($module, config) {
|
1363
|
+
if (!$module) {
|
1364
|
+
return this;
|
1365
|
+
}
|
967
1366
|
this.$module = $module;
|
1367
|
+
var defaultConfig = {
|
1368
|
+
disableAutoFocus: false
|
1369
|
+
};
|
1370
|
+
this.config = mergeConfigs(defaultConfig, config || {}, normaliseDataset($module.dataset));
|
968
1371
|
}
|
969
1372
|
|
970
1373
|
ErrorSummary.prototype.init = function() {
|
@@ -978,7 +1381,7 @@ ErrorSummary.prototype.init = function() {
|
|
978
1381
|
|
979
1382
|
ErrorSummary.prototype.setFocus = function() {
|
980
1383
|
var $module = this.$module;
|
981
|
-
if (
|
1384
|
+
if (this.config.disableAutoFocus) {
|
982
1385
|
return;
|
983
1386
|
}
|
984
1387
|
$module.setAttribute("tabindex", "-1");
|
@@ -989,8 +1392,8 @@ ErrorSummary.prototype.setFocus = function() {
|
|
989
1392
|
};
|
990
1393
|
|
991
1394
|
ErrorSummary.prototype.handleClick = function(event) {
|
992
|
-
var target = event.target;
|
993
|
-
if (this.focusTarget(target)) {
|
1395
|
+
var $target = event.target;
|
1396
|
+
if (this.focusTarget($target)) {
|
994
1397
|
event.preventDefault();
|
995
1398
|
}
|
996
1399
|
};
|
@@ -1025,9 +1428,9 @@ ErrorSummary.prototype.getFragmentFromUrl = function(url) {
|
|
1025
1428
|
ErrorSummary.prototype.getAssociatedLegendOrLabel = function($input) {
|
1026
1429
|
var $fieldset = $input.closest("fieldset");
|
1027
1430
|
if ($fieldset) {
|
1028
|
-
var legends = $fieldset.getElementsByTagName("legend");
|
1029
|
-
if (legends.length) {
|
1030
|
-
var $candidateLegend = legends[0];
|
1431
|
+
var $legends = $fieldset.getElementsByTagName("legend");
|
1432
|
+
if ($legends.length) {
|
1433
|
+
var $candidateLegend = $legends[0];
|
1031
1434
|
if ($input.type === "checkbox" || $input.type === "radio") {
|
1032
1435
|
return $candidateLegend;
|
1033
1436
|
}
|
@@ -1053,11 +1456,11 @@ Radios.prototype.init = function() {
|
|
1053
1456
|
var $module = this.$module;
|
1054
1457
|
var $inputs = this.$inputs;
|
1055
1458
|
nodeListForEach($inputs, (function($input) {
|
1056
|
-
var
|
1057
|
-
if (!
|
1459
|
+
var targetId = $input.getAttribute("data-aria-controls");
|
1460
|
+
if (!targetId || !document.getElementById(targetId)) {
|
1058
1461
|
return;
|
1059
1462
|
}
|
1060
|
-
$input.setAttribute("aria-controls",
|
1463
|
+
$input.setAttribute("aria-controls", targetId);
|
1061
1464
|
$input.removeAttribute("data-aria-controls");
|
1062
1465
|
}));
|
1063
1466
|
if ("onpageshow" in window) {
|