govuk_tech_docs 3.2.1 → 3.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/publish.yaml +1 -1
- data/CHANGELOG.md +26 -7
- data/README.md +2 -2
- data/lib/assets/javascripts/_modules/search.js +2 -2
- data/lib/govuk_tech_docs/contribution_banner.rb +1 -1
- data/lib/govuk_tech_docs/version.rb +1 -1
- data/lib/source/layouts/core.erb +1 -1
- data/node_modules/govuk-frontend/govuk/all.js +1548 -311
- data/node_modules/govuk-frontend/govuk/common/closest-attribute-value.js +70 -0
- data/node_modules/govuk-frontend/govuk/common/index.js +172 -0
- data/node_modules/govuk-frontend/govuk/common/normalise-dataset.js +373 -0
- data/node_modules/govuk-frontend/govuk/common.js +138 -3
- data/node_modules/govuk-frontend/govuk/components/_all.scss +1 -0
- data/node_modules/govuk-frontend/govuk/components/accordion/_index.scss +5 -6
- data/node_modules/govuk-frontend/govuk/components/accordion/accordion.js +754 -36
- data/node_modules/govuk-frontend/govuk/components/breadcrumbs/_index.scss +0 -2
- data/node_modules/govuk-frontend/govuk/components/button/_index.scss +29 -21
- data/node_modules/govuk-frontend/govuk/components/button/button.js +365 -107
- data/node_modules/govuk-frontend/govuk/components/character-count/_index.scss +9 -0
- data/node_modules/govuk-frontend/govuk/components/character-count/character-count.js +1092 -109
- data/node_modules/govuk-frontend/govuk/components/checkboxes/_index.scss +3 -2
- data/node_modules/govuk-frontend/govuk/components/checkboxes/checkboxes.js +30 -2
- data/node_modules/govuk-frontend/govuk/components/details/details.js +51 -33
- data/node_modules/govuk-frontend/govuk/components/error-summary/error-summary.js +289 -6
- data/node_modules/govuk-frontend/govuk/components/footer/_index.scss +13 -23
- data/node_modules/govuk-frontend/govuk/components/header/_index.scss +30 -24
- data/node_modules/govuk-frontend/govuk/components/header/header.js +59 -11
- data/node_modules/govuk-frontend/govuk/components/input/_index.scss +13 -23
- data/node_modules/govuk-frontend/govuk/components/notification-banner/notification-banner.js +252 -2
- data/node_modules/govuk-frontend/govuk/components/pagination/_index.scss +247 -0
- data/node_modules/govuk-frontend/govuk/components/pagination/_pagination.scss +2 -0
- data/node_modules/govuk-frontend/govuk/components/panel/_index.scss +1 -1
- data/node_modules/govuk-frontend/govuk/components/radios/_index.scss +5 -12
- data/node_modules/govuk-frontend/govuk/components/radios/radios.js +30 -2
- data/node_modules/govuk-frontend/govuk/components/select/_index.scss +11 -0
- data/node_modules/govuk-frontend/govuk/components/skip-link/_index.scss +1 -3
- data/node_modules/govuk-frontend/govuk/components/skip-link/skip-link.js +10 -4
- data/node_modules/govuk-frontend/govuk/components/summary-list/_index.scss +45 -13
- data/node_modules/govuk-frontend/govuk/components/table/_index.scss +1 -1
- data/node_modules/govuk-frontend/govuk/components/tabs/tabs.js +28 -0
- data/node_modules/govuk-frontend/govuk/core/_section-break.scss +1 -1
- data/node_modules/govuk-frontend/govuk/helpers/_colour.scss +5 -5
- data/node_modules/govuk-frontend/govuk/helpers/_focused.scss +5 -0
- data/node_modules/govuk-frontend/govuk/helpers/_links.scss +13 -11
- data/node_modules/govuk-frontend/govuk/helpers/_media-queries.scss +2 -2
- data/node_modules/govuk-frontend/govuk/helpers/_shape-arrow.scss +1 -1
- data/node_modules/govuk-frontend/govuk/helpers/_spacing.scss +3 -3
- data/node_modules/govuk-frontend/govuk/helpers/_typography.scss +16 -9
- data/node_modules/govuk-frontend/govuk/i18n.js +390 -0
- data/node_modules/govuk-frontend/govuk/objects/_button-group.scss +10 -26
- data/node_modules/govuk-frontend/govuk/objects/_template.scss +1 -1
- data/node_modules/govuk-frontend/govuk/objects/_width-container.scss +0 -4
- data/node_modules/govuk-frontend/govuk/overrides/_spacing.scss +56 -12
- data/node_modules/govuk-frontend/govuk/settings/_all.scss +1 -0
- data/node_modules/govuk-frontend/govuk/settings/_colours-palette.scss +12 -0
- data/node_modules/govuk-frontend/govuk/settings/_compatibility.scss +26 -0
- data/node_modules/govuk-frontend/govuk/settings/_spacing.scss +4 -8
- data/node_modules/govuk-frontend/govuk/settings/_typography-font.scss +23 -0
- data/node_modules/govuk-frontend/govuk/settings/_typography-responsive.scss +12 -0
- data/node_modules/govuk-frontend/govuk/settings/_warnings.scss +53 -0
- data/node_modules/govuk-frontend/govuk/tools/_compatibility.scss +20 -6
- data/node_modules/govuk-frontend/govuk/tools/_exports.scss +1 -1
- data/node_modules/govuk-frontend/govuk/tools/_font-url.scss +1 -1
- data/node_modules/govuk-frontend/govuk/tools/_image-url.scss +1 -1
- data/node_modules/govuk-frontend/govuk/tools/_px-to-em.scss +2 -2
- data/node_modules/govuk-frontend/govuk/tools/_px-to-rem.scss +1 -1
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Date/now.js +21 -0
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/dataset.js +300 -0
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/String/prototype/trim.js +21 -0
- data/node_modules/govuk-frontend/govuk-prototype-kit/init.js +7 -0
- data/node_modules/govuk-frontend/govuk-prototype-kit/init.scss +12 -0
- data/package-lock.json +12 -12
- data/package.json +1 -1
- metadata +14 -2
@@ -58,7 +58,7 @@
|
|
58
58
|
position: relative;
|
59
59
|
top: -1px;
|
60
60
|
margin-right: 1px;
|
61
|
-
fill:
|
61
|
+
fill: currentcolor;
|
62
62
|
vertical-align: top;
|
63
63
|
}
|
64
64
|
|
@@ -91,7 +91,7 @@
|
|
91
91
|
text-decoration: underline;
|
92
92
|
text-decoration-thickness: $govuk-header-link-underline-thickness;
|
93
93
|
|
94
|
-
@if
|
94
|
+
@if $govuk-link-underline-offset {
|
95
95
|
text-underline-offset: $govuk-link-underline-offset;
|
96
96
|
}
|
97
97
|
}
|
@@ -111,6 +111,16 @@
|
|
111
111
|
font-size: 30px; // We don't have a mixin that produces 30px font size
|
112
112
|
line-height: 1;
|
113
113
|
|
114
|
+
@include govuk-media-query($from: tablet) {
|
115
|
+
display: inline;
|
116
|
+
|
117
|
+
&:focus {
|
118
|
+
// Replicate the focus box shadow but without the -2px y-offset of the first yellow shadow
|
119
|
+
// This is to stop the logo getting cut off by the box shadow when focused on above a product name
|
120
|
+
box-shadow: 0 0 $govuk-focus-colour;
|
121
|
+
}
|
122
|
+
}
|
123
|
+
|
114
124
|
&:link,
|
115
125
|
&:visited {
|
116
126
|
text-decoration: none;
|
@@ -132,6 +142,9 @@
|
|
132
142
|
}
|
133
143
|
}
|
134
144
|
|
145
|
+
// The govuk-header__link--service-name class is deprecated - use
|
146
|
+
// govuk-header__service-name instead.
|
147
|
+
.govuk-header__service-name,
|
135
148
|
.govuk-header__link--service-name {
|
136
149
|
display: inline-block;
|
137
150
|
margin-bottom: govuk-spacing(2);
|
@@ -180,7 +193,7 @@
|
|
180
193
|
-webkit-text-decoration: solid underline $govuk-header-link-underline-thickness;
|
181
194
|
text-decoration: solid underline $govuk-header-link-underline-thickness;
|
182
195
|
|
183
|
-
@if
|
196
|
+
@if $govuk-link-underline-offset {
|
184
197
|
text-underline-offset: $govuk-link-underline-offset;
|
185
198
|
}
|
186
199
|
}
|
@@ -195,14 +208,21 @@
|
|
195
208
|
margin-left: govuk-spacing(1);
|
196
209
|
}
|
197
210
|
|
211
|
+
&[aria-expanded="true"]:after {
|
212
|
+
@include govuk-shape-arrow($direction: up, $base: 10px, $display: inline-block);
|
213
|
+
}
|
214
|
+
|
198
215
|
@include govuk-media-query ($from: tablet) {
|
199
216
|
top: govuk-spacing(3);
|
200
217
|
}
|
201
|
-
}
|
202
218
|
|
203
|
-
|
204
|
-
|
205
|
-
|
219
|
+
.js-enabled & {
|
220
|
+
display: block;
|
221
|
+
}
|
222
|
+
|
223
|
+
&[hidden],
|
224
|
+
.js-enabled &[hidden] {
|
225
|
+
display: none;
|
206
226
|
}
|
207
227
|
}
|
208
228
|
|
@@ -217,25 +237,9 @@
|
|
217
237
|
margin: 0;
|
218
238
|
padding: 0;
|
219
239
|
list-style: none;
|
220
|
-
}
|
221
240
|
|
222
|
-
|
223
|
-
.govuk-header__menu-button {
|
224
|
-
display: block;
|
225
|
-
@include govuk-media-query ($from: desktop) {
|
226
|
-
display: none;
|
227
|
-
}
|
228
|
-
}
|
229
|
-
|
230
|
-
.govuk-header__navigation-list {
|
241
|
+
&[hidden] {
|
231
242
|
display: none;
|
232
|
-
@include govuk-media-query ($from: desktop) {
|
233
|
-
display: block;
|
234
|
-
}
|
235
|
-
}
|
236
|
-
|
237
|
-
.govuk-header__navigation-list--open {
|
238
|
-
display: block;
|
239
243
|
}
|
240
244
|
}
|
241
245
|
|
@@ -247,6 +251,8 @@
|
|
247
251
|
}
|
248
252
|
}
|
249
253
|
|
254
|
+
// The govuk-header__navigation--no-service-name class is deprecated and will
|
255
|
+
// be removed in the next major release.
|
250
256
|
.govuk-header__navigation--no-service-name {
|
251
257
|
padding-top: govuk-spacing(7);
|
252
258
|
}
|
@@ -1014,12 +1014,29 @@ if (detect) return
|
|
1014
1014
|
})
|
1015
1015
|
.call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
|
1016
1016
|
|
1017
|
+
/**
|
1018
|
+
* Header component
|
1019
|
+
*
|
1020
|
+
* @class
|
1021
|
+
* @param {HTMLElement} $module - HTML element to use for header
|
1022
|
+
*/
|
1017
1023
|
function Header ($module) {
|
1018
1024
|
this.$module = $module;
|
1019
1025
|
this.$menuButton = $module && $module.querySelector('.govuk-js-header-toggle');
|
1020
1026
|
this.$menu = this.$menuButton && $module.querySelector(
|
1021
1027
|
'#' + this.$menuButton.getAttribute('aria-controls')
|
1022
1028
|
);
|
1029
|
+
|
1030
|
+
// Save the opened/closed state for the nav in memory so that we can
|
1031
|
+
// accurately maintain state when the screen is changed from small to
|
1032
|
+
// big and back to small
|
1033
|
+
this.menuIsOpen = false;
|
1034
|
+
|
1035
|
+
// A global const for storing a matchMedia instance which we'll use to
|
1036
|
+
// detect when a screen size change happens. We set this later during the
|
1037
|
+
// init function and rely on it being null if the feature isn't available
|
1038
|
+
// to initially apply hidden attributes
|
1039
|
+
this.mql = null;
|
1023
1040
|
}
|
1024
1041
|
|
1025
1042
|
/**
|
@@ -1027,27 +1044,58 @@ function Header ($module) {
|
|
1027
1044
|
*
|
1028
1045
|
* Check for the presence of the header, menu and menu button – if any are
|
1029
1046
|
* missing then there's nothing to do so return early.
|
1047
|
+
* Feature sniff for and apply a matchMedia for desktop which will
|
1048
|
+
* trigger a state sync if the browser viewport moves between states. If
|
1049
|
+
* matchMedia isn't available, hide the menu button and present the "no js"
|
1050
|
+
* version of the menu to the user.
|
1030
1051
|
*/
|
1031
1052
|
Header.prototype.init = function () {
|
1032
1053
|
if (!this.$module || !this.$menuButton || !this.$menu) {
|
1033
1054
|
return
|
1034
1055
|
}
|
1035
1056
|
|
1036
|
-
|
1037
|
-
|
1057
|
+
if ('matchMedia' in window) {
|
1058
|
+
// Set the matchMedia to the govuk-frontend desktop breakpoint
|
1059
|
+
this.mql = window.matchMedia('(min-width: 48.0625em)');
|
1060
|
+
|
1061
|
+
if ('addEventListener' in this.mql) {
|
1062
|
+
this.mql.addEventListener('change', this.syncState.bind(this));
|
1063
|
+
} else {
|
1064
|
+
// addListener is a deprecated function, however addEventListener
|
1065
|
+
// isn't supported by IE or Safari. We therefore add this in as
|
1066
|
+
// a fallback for those browsers
|
1067
|
+
this.mql.addListener(this.syncState.bind(this));
|
1068
|
+
}
|
1069
|
+
|
1070
|
+
this.syncState();
|
1071
|
+
this.$menuButton.addEventListener('click', this.handleMenuButtonClick.bind(this));
|
1072
|
+
} else {
|
1073
|
+
this.$menuButton.setAttribute('hidden', '');
|
1074
|
+
}
|
1038
1075
|
};
|
1039
1076
|
|
1040
1077
|
/**
|
1041
1078
|
* Sync menu state
|
1042
1079
|
*
|
1043
|
-
*
|
1044
|
-
*
|
1045
|
-
*
|
1046
|
-
*
|
1080
|
+
* Uses the global variable menuIsOpen to correctly set the accessible and
|
1081
|
+
* visual states of the menu and the menu button.
|
1082
|
+
* Additionally will force the menu to be visible and the menu button to be
|
1083
|
+
* hidden if the matchMedia is triggered to desktop.
|
1047
1084
|
*/
|
1048
|
-
Header.prototype.syncState = function (
|
1049
|
-
this
|
1050
|
-
|
1085
|
+
Header.prototype.syncState = function () {
|
1086
|
+
if (this.mql.matches) {
|
1087
|
+
this.$menu.removeAttribute('hidden');
|
1088
|
+
this.$menuButton.setAttribute('hidden', '');
|
1089
|
+
} else {
|
1090
|
+
this.$menuButton.removeAttribute('hidden');
|
1091
|
+
this.$menuButton.setAttribute('aria-expanded', this.menuIsOpen);
|
1092
|
+
|
1093
|
+
if (this.menuIsOpen) {
|
1094
|
+
this.$menu.removeAttribute('hidden');
|
1095
|
+
} else {
|
1096
|
+
this.$menu.setAttribute('hidden', '');
|
1097
|
+
}
|
1098
|
+
}
|
1051
1099
|
};
|
1052
1100
|
|
1053
1101
|
/**
|
@@ -1057,8 +1105,8 @@ Header.prototype.syncState = function (isVisible) {
|
|
1057
1105
|
* sync the accessibility state and menu button state
|
1058
1106
|
*/
|
1059
1107
|
Header.prototype.handleMenuButtonClick = function () {
|
1060
|
-
|
1061
|
-
this.syncState(
|
1108
|
+
this.menuIsOpen = !this.menuIsOpen;
|
1109
|
+
this.syncState();
|
1062
1110
|
};
|
1063
1111
|
|
1064
1112
|
return Header;
|
@@ -22,7 +22,6 @@
|
|
22
22
|
|
23
23
|
// Disable inner shadow and remove rounded corners
|
24
24
|
-webkit-appearance: none;
|
25
|
-
-moz-appearance: none;
|
26
25
|
appearance: none;
|
27
26
|
|
28
27
|
&:focus {
|
@@ -61,49 +60,44 @@
|
|
61
60
|
}
|
62
61
|
}
|
63
62
|
|
64
|
-
//
|
65
|
-
// Extra space is
|
66
|
-
// Linear regression estimation based on visual tests: y = 1.76 + 1.81x
|
63
|
+
// em measurements are based on the point size of the typeface
|
64
|
+
// Extra space is added on the right hand side to allow for the Safari prefill icon
|
67
65
|
|
68
66
|
.govuk-input--width-30 {
|
69
|
-
max-width:
|
67
|
+
max-width: 29.5em;
|
70
68
|
}
|
71
69
|
|
72
70
|
.govuk-input--width-20 {
|
73
|
-
max-width:
|
71
|
+
max-width: 20.5em;
|
74
72
|
}
|
75
73
|
|
76
74
|
.govuk-input--width-10 {
|
77
|
-
max-width:
|
75
|
+
max-width: 11.5em;
|
78
76
|
}
|
79
77
|
|
80
78
|
.govuk-input--width-5 {
|
81
|
-
max-width:
|
79
|
+
max-width: 5.5em;
|
82
80
|
}
|
83
81
|
|
84
82
|
.govuk-input--width-4 {
|
85
|
-
max-width:
|
83
|
+
max-width: 4.5em;
|
86
84
|
}
|
87
85
|
|
88
86
|
.govuk-input--width-3 {
|
89
|
-
max-width:
|
87
|
+
max-width: 3.75em;
|
90
88
|
}
|
91
89
|
|
92
90
|
.govuk-input--width-2 {
|
93
|
-
max-width:
|
91
|
+
max-width: 2.75em;
|
94
92
|
}
|
95
93
|
|
96
94
|
.govuk-input__wrapper {
|
97
|
-
display: -webkit-box;
|
98
|
-
display: -webkit-flex;
|
99
95
|
display: -ms-flexbox;
|
100
96
|
display: flex;
|
101
97
|
|
102
98
|
.govuk-input {
|
103
|
-
-
|
104
|
-
|
105
|
-
-ms-flex: 0 1 auto;
|
106
|
-
flex: 0 1 auto;
|
99
|
+
-ms-flex: 0 1 auto;
|
100
|
+
flex: 0 1 auto;
|
107
101
|
}
|
108
102
|
|
109
103
|
.govuk-input:focus {
|
@@ -150,13 +144,9 @@
|
|
150
144
|
// Emphasise non-editable status of prefixes and suffixes
|
151
145
|
cursor: default;
|
152
146
|
|
153
|
-
-
|
147
|
+
-ms-flex: 0 0 auto;
|
154
148
|
|
155
|
-
|
156
|
-
|
157
|
-
-ms-flex: 0 0 auto;
|
158
|
-
|
159
|
-
flex: 0 0 auto;
|
149
|
+
flex: 0 0 auto;
|
160
150
|
|
161
151
|
// Split prefix/suffix onto separate lines on narrow screens
|
162
152
|
@include govuk-media-query($until: mobile) {
|
data/node_modules/govuk-frontend/govuk/components/notification-banner/notification-banner.js
CHANGED
@@ -501,8 +501,247 @@ if (detect) return
|
|
501
501
|
})
|
502
502
|
.call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
|
503
503
|
|
504
|
-
|
504
|
+
/**
|
505
|
+
* Common helpers which do not require polyfill.
|
506
|
+
*
|
507
|
+
* IMPORTANT: If a helper require a polyfill, please isolate it in its own module
|
508
|
+
* so that the polyfill can be properly tree-shaken and does not burden
|
509
|
+
* the components that do not need that helper
|
510
|
+
*
|
511
|
+
* @module common/index
|
512
|
+
*/
|
513
|
+
|
514
|
+
/**
|
515
|
+
* Config flattening function
|
516
|
+
*
|
517
|
+
* Takes any number of objects, flattens them into namespaced key-value pairs,
|
518
|
+
* (e.g. {'i18n.showSection': 'Show section'}) and combines them together, with
|
519
|
+
* greatest priority on the LAST item passed in.
|
520
|
+
*
|
521
|
+
* @returns {object} A flattened object of key-value pairs.
|
522
|
+
*/
|
523
|
+
function mergeConfigs (/* configObject1, configObject2, ...configObjects */) {
|
524
|
+
/**
|
525
|
+
* Function to take nested objects and flatten them to a dot-separated keyed
|
526
|
+
* object. Doing this means we don't need to do any deep/recursive merging of
|
527
|
+
* each of our objects, nor transform our dataset from a flat list into a
|
528
|
+
* nested object.
|
529
|
+
*
|
530
|
+
* @param {object} configObject - Deeply nested object
|
531
|
+
* @returns {object} Flattened object with dot-separated keys
|
532
|
+
*/
|
533
|
+
var flattenObject = function (configObject) {
|
534
|
+
// Prepare an empty return object
|
535
|
+
var flattenedObject = {};
|
536
|
+
|
537
|
+
// Our flattening function, this is called recursively for each level of
|
538
|
+
// depth in the object. At each level we prepend the previous level names to
|
539
|
+
// the key using `prefix`.
|
540
|
+
var flattenLoop = function (obj, prefix) {
|
541
|
+
// Loop through keys...
|
542
|
+
for (var key in obj) {
|
543
|
+
// Check to see if this is a prototypical key/value,
|
544
|
+
// if it is, skip it.
|
545
|
+
if (!Object.prototype.hasOwnProperty.call(obj, key)) {
|
546
|
+
continue
|
547
|
+
}
|
548
|
+
var value = obj[key];
|
549
|
+
var prefixedKey = prefix ? prefix + '.' + key : key;
|
550
|
+
if (typeof value === 'object') {
|
551
|
+
// If the value is a nested object, recurse over that too
|
552
|
+
flattenLoop(value, prefixedKey);
|
553
|
+
} else {
|
554
|
+
// Otherwise, add this value to our return object
|
555
|
+
flattenedObject[prefixedKey] = value;
|
556
|
+
}
|
557
|
+
}
|
558
|
+
};
|
559
|
+
|
560
|
+
// Kick off the recursive loop
|
561
|
+
flattenLoop(configObject);
|
562
|
+
return flattenedObject
|
563
|
+
};
|
564
|
+
|
565
|
+
// Start with an empty object as our base
|
566
|
+
var formattedConfigObject = {};
|
567
|
+
|
568
|
+
// Loop through each of the remaining passed objects and push their keys
|
569
|
+
// one-by-one into configObject. Any duplicate keys will override the existing
|
570
|
+
// key with the new value.
|
571
|
+
for (var i = 0; i < arguments.length; i++) {
|
572
|
+
var obj = flattenObject(arguments[i]);
|
573
|
+
for (var key in obj) {
|
574
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
575
|
+
formattedConfigObject[key] = obj[key];
|
576
|
+
}
|
577
|
+
}
|
578
|
+
}
|
579
|
+
|
580
|
+
return formattedConfigObject
|
581
|
+
}
|
582
|
+
|
583
|
+
/**
|
584
|
+
* @callback nodeListIterator
|
585
|
+
* @param {Element} value - The current node being iterated on
|
586
|
+
* @param {number} index - The current index in the iteration
|
587
|
+
* @param {NodeListOf<Element>} nodes - NodeList from querySelectorAll()
|
588
|
+
* @returns {undefined}
|
589
|
+
*/
|
590
|
+
|
591
|
+
(function(undefined) {
|
592
|
+
|
593
|
+
// Detection from https://raw.githubusercontent.com/Financial-Times/polyfill-library/13cf7c340974d128d557580b5e2dafcd1b1192d1/polyfills/Element/prototype/dataset/detect.js
|
594
|
+
var detect = (function(){
|
595
|
+
if (!document.documentElement.dataset) {
|
596
|
+
return false;
|
597
|
+
}
|
598
|
+
var el = document.createElement('div');
|
599
|
+
el.setAttribute("data-a-b", "c");
|
600
|
+
return el.dataset && el.dataset.aB == "c";
|
601
|
+
}());
|
602
|
+
|
603
|
+
if (detect) return
|
604
|
+
|
605
|
+
// Polyfill derived from https://raw.githubusercontent.com/Financial-Times/polyfill-library/13cf7c340974d128d557580b5e2dafcd1b1192d1/polyfills/Element/prototype/dataset/polyfill.js
|
606
|
+
Object.defineProperty(Element.prototype, 'dataset', {
|
607
|
+
get: function() {
|
608
|
+
var element = this;
|
609
|
+
var attributes = this.attributes;
|
610
|
+
var map = {};
|
611
|
+
|
612
|
+
for (var i = 0; i < attributes.length; i++) {
|
613
|
+
var attribute = attributes[i];
|
614
|
+
|
615
|
+
// This regex has been edited from the original polyfill, to add
|
616
|
+
// support for period (.) separators in data-* attribute names. These
|
617
|
+
// are allowed in the HTML spec, but were not covered by the original
|
618
|
+
// polyfill's regex. We use periods in our i18n implementation.
|
619
|
+
if (attribute && attribute.name && (/^data-\w[.\w-]*$/).test(attribute.name)) {
|
620
|
+
var name = attribute.name;
|
621
|
+
var value = attribute.value;
|
622
|
+
|
623
|
+
var propName = name.substr(5).replace(/-./g, function (prop) {
|
624
|
+
return prop.charAt(1).toUpperCase();
|
625
|
+
});
|
626
|
+
|
627
|
+
// If this browser supports __defineGetter__ and __defineSetter__,
|
628
|
+
// continue using defineProperty. If not (like IE 8 and below), we use
|
629
|
+
// a hacky fallback which at least gives an object in the right format
|
630
|
+
if ('__defineGetter__' in Object.prototype && '__defineSetter__' in Object.prototype) {
|
631
|
+
Object.defineProperty(map, propName, {
|
632
|
+
enumerable: true,
|
633
|
+
get: function() {
|
634
|
+
return this.value;
|
635
|
+
}.bind({value: value || ''}),
|
636
|
+
set: function setter(name, value) {
|
637
|
+
if (typeof value !== 'undefined') {
|
638
|
+
this.setAttribute(name, value);
|
639
|
+
} else {
|
640
|
+
this.removeAttribute(name);
|
641
|
+
}
|
642
|
+
}.bind(element, name)
|
643
|
+
});
|
644
|
+
} else {
|
645
|
+
map[propName] = value;
|
646
|
+
}
|
647
|
+
|
648
|
+
}
|
649
|
+
}
|
650
|
+
|
651
|
+
return map;
|
652
|
+
}
|
653
|
+
});
|
654
|
+
|
655
|
+
}).call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
|
656
|
+
|
657
|
+
(function(undefined) {
|
658
|
+
|
659
|
+
// Detection from https://github.com/mdn/content/blob/cf607d68522cd35ee7670782d3ee3a361eaef2e4/files/en-us/web/javascript/reference/global_objects/string/trim/index.md#polyfill
|
660
|
+
var detect = ('trim' in String.prototype);
|
661
|
+
|
662
|
+
if (detect) return
|
663
|
+
|
664
|
+
// Polyfill from https://github.com/mdn/content/blob/cf607d68522cd35ee7670782d3ee3a361eaef2e4/files/en-us/web/javascript/reference/global_objects/string/trim/index.md#polyfill
|
665
|
+
String.prototype.trim = function () {
|
666
|
+
return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
|
667
|
+
};
|
668
|
+
|
669
|
+
}).call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
|
670
|
+
|
671
|
+
/**
|
672
|
+
* Normalise string
|
673
|
+
*
|
674
|
+
* 'If it looks like a duck, and it quacks like a duck…' 🦆
|
675
|
+
*
|
676
|
+
* If the passed value looks like a boolean or a number, convert it to a boolean
|
677
|
+
* or number.
|
678
|
+
*
|
679
|
+
* Designed to be used to convert config passed via data attributes (which are
|
680
|
+
* always strings) into something sensible.
|
681
|
+
*
|
682
|
+
* @param {string} value - The value to normalise
|
683
|
+
* @returns {string | boolean | number | undefined} Normalised data
|
684
|
+
*/
|
685
|
+
function normaliseString (value) {
|
686
|
+
if (typeof value !== 'string') {
|
687
|
+
return value
|
688
|
+
}
|
689
|
+
|
690
|
+
var trimmedValue = value.trim();
|
691
|
+
|
692
|
+
if (trimmedValue === 'true') {
|
693
|
+
return true
|
694
|
+
}
|
695
|
+
|
696
|
+
if (trimmedValue === 'false') {
|
697
|
+
return false
|
698
|
+
}
|
699
|
+
|
700
|
+
// Empty / whitespace-only strings are considered finite so we need to check
|
701
|
+
// the length of the trimmed string as well
|
702
|
+
if (trimmedValue.length > 0 && isFinite(trimmedValue)) {
|
703
|
+
return Number(trimmedValue)
|
704
|
+
}
|
705
|
+
|
706
|
+
return value
|
707
|
+
}
|
708
|
+
|
709
|
+
/**
|
710
|
+
* Normalise dataset
|
711
|
+
*
|
712
|
+
* Loop over an object and normalise each value using normaliseData function
|
713
|
+
*
|
714
|
+
* @param {DOMStringMap} dataset - HTML element dataset
|
715
|
+
* @returns {Object<string, string | boolean | number | undefined>} Normalised dataset
|
716
|
+
*/
|
717
|
+
function normaliseDataset (dataset) {
|
718
|
+
var out = {};
|
719
|
+
|
720
|
+
for (var key in dataset) {
|
721
|
+
out[key] = normaliseString(dataset[key]);
|
722
|
+
}
|
723
|
+
|
724
|
+
return out
|
725
|
+
}
|
726
|
+
|
727
|
+
/**
|
728
|
+
* Notification Banner component
|
729
|
+
*
|
730
|
+
* @class
|
731
|
+
* @param {HTMLElement} $module - HTML element to use for notification banner
|
732
|
+
* @param {NotificationBannerConfig} config - Notification banner config
|
733
|
+
*/
|
734
|
+
function NotificationBanner ($module, config) {
|
505
735
|
this.$module = $module;
|
736
|
+
|
737
|
+
var defaultConfig = {
|
738
|
+
disableAutoFocus: false
|
739
|
+
};
|
740
|
+
this.config = mergeConfigs(
|
741
|
+
defaultConfig,
|
742
|
+
config || {},
|
743
|
+
normaliseDataset($module.dataset)
|
744
|
+
);
|
506
745
|
}
|
507
746
|
|
508
747
|
/**
|
@@ -531,7 +770,7 @@ NotificationBanner.prototype.init = function () {
|
|
531
770
|
NotificationBanner.prototype.setFocus = function () {
|
532
771
|
var $module = this.$module;
|
533
772
|
|
534
|
-
if (
|
773
|
+
if (this.config.disableAutoFocus) {
|
535
774
|
return
|
536
775
|
}
|
537
776
|
|
@@ -553,6 +792,17 @@ NotificationBanner.prototype.setFocus = function () {
|
|
553
792
|
$module.focus();
|
554
793
|
};
|
555
794
|
|
795
|
+
/**
|
796
|
+
* Notification banner config
|
797
|
+
*
|
798
|
+
* @typedef {object} NotificationBannerConfig
|
799
|
+
* @property {boolean} [disableAutoFocus = false] -
|
800
|
+
* If set to `true` the notification banner will not be focussed when the page
|
801
|
+
* loads. This only applies if the component has a `role` of `alert` – in
|
802
|
+
* other cases the component will not be focused on page load, regardless of
|
803
|
+
* this option.
|
804
|
+
*/
|
805
|
+
|
556
806
|
return NotificationBanner;
|
557
807
|
|
558
808
|
})));
|