govuk_tech_docs 3.2.0 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of govuk_tech_docs might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.github/workflows/publish.yaml +1 -1
- data/CHANGELOG.md +26 -7
- data/README.md +2 -2
- data/example/source/code.html.md +3 -26
- data/lib/govuk_tech_docs/contribution_banner.rb +1 -1
- data/lib/govuk_tech_docs/tech_docs_html_renderer.rb +3 -3
- 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 +17 -5
@@ -83,7 +83,7 @@
|
|
83
83
|
left: 0;
|
84
84
|
width: $govuk-checkboxes-size;
|
85
85
|
height: $govuk-checkboxes-size;
|
86
|
-
border: $govuk-border-width-form-element solid
|
86
|
+
border: $govuk-border-width-form-element solid currentcolor;
|
87
87
|
background: transparent;
|
88
88
|
}
|
89
89
|
|
@@ -155,7 +155,8 @@
|
|
155
155
|
cursor: default;
|
156
156
|
}
|
157
157
|
|
158
|
-
.govuk-checkboxes__input:disabled + .govuk-checkboxes__label
|
158
|
+
.govuk-checkboxes__input:disabled + .govuk-checkboxes__label,
|
159
|
+
.govuk-checkboxes__input:disabled ~ .govuk-hint {
|
159
160
|
opacity: .5;
|
160
161
|
}
|
161
162
|
|
@@ -1014,10 +1014,24 @@ if (detect) return
|
|
1014
1014
|
|
1015
1015
|
}).call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
|
1016
1016
|
|
1017
|
+
/**
|
1018
|
+
* Common helpers which do not require polyfill.
|
1019
|
+
*
|
1020
|
+
* IMPORTANT: If a helper require a polyfill, please isolate it in its own module
|
1021
|
+
* so that the polyfill can be properly tree-shaken and does not burden
|
1022
|
+
* the components that do not need that helper
|
1023
|
+
*
|
1024
|
+
* @module common/index
|
1025
|
+
*/
|
1026
|
+
|
1017
1027
|
/**
|
1018
1028
|
* TODO: Ideally this would be a NodeList.prototype.forEach polyfill
|
1019
1029
|
* This seems to fail in IE8, requires more investigation.
|
1020
1030
|
* See: https://github.com/imagitama/nodelist-foreach-polyfill
|
1031
|
+
*
|
1032
|
+
* @param {NodeListOf<Element>} nodes - NodeList from querySelectorAll()
|
1033
|
+
* @param {nodeListIterator} callback - Callback function to run for each node
|
1034
|
+
* @returns {undefined}
|
1021
1035
|
*/
|
1022
1036
|
function nodeListForEach (nodes, callback) {
|
1023
1037
|
if (window.NodeList.prototype.forEach) {
|
@@ -1028,6 +1042,20 @@ function nodeListForEach (nodes, callback) {
|
|
1028
1042
|
}
|
1029
1043
|
}
|
1030
1044
|
|
1045
|
+
/**
|
1046
|
+
* @callback nodeListIterator
|
1047
|
+
* @param {Element} value - The current node being iterated on
|
1048
|
+
* @param {number} index - The current index in the iteration
|
1049
|
+
* @param {NodeListOf<Element>} nodes - NodeList from querySelectorAll()
|
1050
|
+
* @returns {undefined}
|
1051
|
+
*/
|
1052
|
+
|
1053
|
+
/**
|
1054
|
+
* Checkboxes component
|
1055
|
+
*
|
1056
|
+
* @class
|
1057
|
+
* @param {HTMLElement} $module - HTML element to use for checkboxes
|
1058
|
+
*/
|
1031
1059
|
function Checkboxes ($module) {
|
1032
1060
|
this.$module = $module;
|
1033
1061
|
this.$inputs = $module.querySelectorAll('input[type="checkbox"]');
|
@@ -1097,7 +1125,7 @@ Checkboxes.prototype.syncAllConditionalReveals = function () {
|
|
1097
1125
|
* Synchronise the visibility of the conditional reveal, and its accessible
|
1098
1126
|
* state, with the input's checked state.
|
1099
1127
|
*
|
1100
|
-
* @param {HTMLInputElement} $input Checkbox input
|
1128
|
+
* @param {HTMLInputElement} $input - Checkbox input
|
1101
1129
|
*/
|
1102
1130
|
Checkboxes.prototype.syncConditionalRevealWithInputState = function ($input) {
|
1103
1131
|
var $target = document.getElementById($input.getAttribute('aria-controls'));
|
@@ -1155,7 +1183,7 @@ Checkboxes.prototype.unCheckExclusiveInputs = function ($input) {
|
|
1155
1183
|
* Handle a click within the $module – if the click occurred on a checkbox, sync
|
1156
1184
|
* the state of any associated conditional reveal with the checkbox state.
|
1157
1185
|
*
|
1158
|
-
* @param {MouseEvent} event Click event
|
1186
|
+
* @param {MouseEvent} event - Click event
|
1159
1187
|
*/
|
1160
1188
|
Checkboxes.prototype.handleClick = function (event) {
|
1161
1189
|
var $target = event.target;
|
@@ -660,14 +660,22 @@ if (detect) return
|
|
660
660
|
.call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
|
661
661
|
|
662
662
|
/**
|
663
|
-
*
|
664
|
-
*
|
665
|
-
*
|
663
|
+
* Common helpers which do not require polyfill.
|
664
|
+
*
|
665
|
+
* IMPORTANT: If a helper require a polyfill, please isolate it in its own module
|
666
|
+
* so that the polyfill can be properly tree-shaken and does not burden
|
667
|
+
* the components that do not need that helper
|
668
|
+
*
|
669
|
+
* @module common/index
|
666
670
|
*/
|
667
671
|
|
668
|
-
|
669
|
-
|
670
|
-
|
672
|
+
/**
|
673
|
+
* Used to generate a unique string, allows multiple instances of the component
|
674
|
+
* without them conflicting with each other.
|
675
|
+
* https://stackoverflow.com/a/8809472
|
676
|
+
*
|
677
|
+
* @returns {string} Unique ID
|
678
|
+
*/
|
671
679
|
function generateUniqueID () {
|
672
680
|
var d = new Date().getTime();
|
673
681
|
if (typeof window.performance !== 'undefined' && typeof window.performance.now === 'function') {
|
@@ -680,6 +688,14 @@ function generateUniqueID () {
|
|
680
688
|
})
|
681
689
|
}
|
682
690
|
|
691
|
+
/**
|
692
|
+
* @callback nodeListIterator
|
693
|
+
* @param {Element} value - The current node being iterated on
|
694
|
+
* @param {number} index - The current index in the iteration
|
695
|
+
* @param {NodeListOf<Element>} nodes - NodeList from querySelectorAll()
|
696
|
+
* @returns {undefined}
|
697
|
+
*/
|
698
|
+
|
683
699
|
/**
|
684
700
|
* JavaScript 'polyfill' for HTML5's <details> and <summary> elements
|
685
701
|
* and 'shim' to add accessiblity enhancements for all browsers
|
@@ -690,6 +706,12 @@ function generateUniqueID () {
|
|
690
706
|
var KEY_ENTER = 13;
|
691
707
|
var KEY_SPACE = 32;
|
692
708
|
|
709
|
+
/**
|
710
|
+
* Details component
|
711
|
+
*
|
712
|
+
* @class
|
713
|
+
* @param {HTMLElement} $module - HTML element to use for details
|
714
|
+
*/
|
693
715
|
function Details ($module) {
|
694
716
|
this.$module = $module;
|
695
717
|
}
|
@@ -744,13 +766,10 @@ Details.prototype.polyfillDetails = function () {
|
|
744
766
|
$summary.tabIndex = 0;
|
745
767
|
|
746
768
|
// Detect initial open state
|
747
|
-
|
748
|
-
if (openAttr === true) {
|
769
|
+
if (this.$module.hasAttribute('open')) {
|
749
770
|
$summary.setAttribute('aria-expanded', 'true');
|
750
|
-
$content.setAttribute('aria-hidden', 'false');
|
751
771
|
} else {
|
752
772
|
$summary.setAttribute('aria-expanded', 'false');
|
753
|
-
$content.setAttribute('aria-hidden', 'true');
|
754
773
|
$content.style.display = 'none';
|
755
774
|
}
|
756
775
|
|
@@ -759,37 +778,30 @@ Details.prototype.polyfillDetails = function () {
|
|
759
778
|
};
|
760
779
|
|
761
780
|
/**
|
762
|
-
* Define a statechange function that updates aria-expanded and style.display
|
763
|
-
*
|
764
|
-
|
781
|
+
* Define a statechange function that updates aria-expanded and style.display
|
782
|
+
*
|
783
|
+
* @returns {boolean} Returns true
|
784
|
+
*/
|
765
785
|
Details.prototype.polyfillSetAttributes = function () {
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
var expanded = $summary.getAttribute('aria-expanded') === 'true';
|
771
|
-
var hidden = $content.getAttribute('aria-hidden') === 'true';
|
772
|
-
|
773
|
-
$summary.setAttribute('aria-expanded', (expanded ? 'false' : 'true'));
|
774
|
-
$content.setAttribute('aria-hidden', (hidden ? 'false' : 'true'));
|
775
|
-
|
776
|
-
$content.style.display = (expanded ? 'none' : '');
|
777
|
-
|
778
|
-
var hasOpenAttr = $module.getAttribute('open') !== null;
|
779
|
-
if (!hasOpenAttr) {
|
780
|
-
$module.setAttribute('open', 'open');
|
786
|
+
if (this.$module.hasAttribute('open')) {
|
787
|
+
this.$module.removeAttribute('open');
|
788
|
+
this.$summary.setAttribute('aria-expanded', 'false');
|
789
|
+
this.$content.style.display = 'none';
|
781
790
|
} else {
|
782
|
-
|
791
|
+
this.$module.setAttribute('open', 'open');
|
792
|
+
this.$summary.setAttribute('aria-expanded', 'true');
|
793
|
+
this.$content.style.display = '';
|
783
794
|
}
|
784
795
|
|
785
796
|
return true
|
786
797
|
};
|
787
798
|
|
788
799
|
/**
|
789
|
-
* Handle cross-modal click events
|
790
|
-
*
|
791
|
-
* @param {
|
792
|
-
|
800
|
+
* Handle cross-modal click events
|
801
|
+
*
|
802
|
+
* @param {object} node - element
|
803
|
+
* @param {polyfillHandleInputsCallback} callback - function
|
804
|
+
*/
|
793
805
|
Details.prototype.polyfillHandleInputs = function (node, callback) {
|
794
806
|
node.addEventListener('keypress', function (event) {
|
795
807
|
var target = event.target;
|
@@ -823,6 +835,12 @@ Details.prototype.polyfillHandleInputs = function (node, callback) {
|
|
823
835
|
node.addEventListener('click', callback);
|
824
836
|
};
|
825
837
|
|
838
|
+
/**
|
839
|
+
* @callback polyfillHandleInputsCallback
|
840
|
+
* @param {KeyboardEvent} event - Keyboard event
|
841
|
+
* @returns {undefined}
|
842
|
+
*/
|
843
|
+
|
826
844
|
return Details;
|
827
845
|
|
828
846
|
})));
|
@@ -706,8 +706,262 @@ if (detect) return
|
|
706
706
|
|
707
707
|
}).call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
|
708
708
|
|
709
|
-
|
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
|
+
/**
|
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.
|
734
|
+
*
|
735
|
+
* @param {object} configObject - Deeply nested object
|
736
|
+
* @returns {object} Flattened object with dot-separated keys
|
737
|
+
*/
|
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
|
+
}
|
762
|
+
}
|
763
|
+
};
|
764
|
+
|
765
|
+
// Kick off the recursive loop
|
766
|
+
flattenLoop(configObject);
|
767
|
+
return flattenedObject
|
768
|
+
};
|
769
|
+
|
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];
|
781
|
+
}
|
782
|
+
}
|
783
|
+
}
|
784
|
+
|
785
|
+
return formattedConfigObject
|
786
|
+
}
|
787
|
+
|
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
|
+
*/
|
795
|
+
|
796
|
+
(function(undefined) {
|
797
|
+
|
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
|
+
}());
|
807
|
+
|
808
|
+
if (detect) return
|
809
|
+
|
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);
|
844
|
+
} else {
|
845
|
+
this.removeAttribute(name);
|
846
|
+
}
|
847
|
+
}.bind(element, name)
|
848
|
+
});
|
849
|
+
} else {
|
850
|
+
map[propName] = value;
|
851
|
+
}
|
852
|
+
|
853
|
+
}
|
854
|
+
}
|
855
|
+
|
856
|
+
return map;
|
857
|
+
}
|
858
|
+
});
|
859
|
+
|
860
|
+
}).call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
|
861
|
+
|
862
|
+
(function(undefined) {
|
863
|
+
|
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
|
868
|
+
|
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, '');
|
872
|
+
};
|
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
|
893
|
+
}
|
894
|
+
|
895
|
+
var trimmedValue = value.trim();
|
896
|
+
|
897
|
+
if (trimmedValue === 'true') {
|
898
|
+
return true
|
899
|
+
}
|
900
|
+
|
901
|
+
if (trimmedValue === 'false') {
|
902
|
+
return false
|
903
|
+
}
|
904
|
+
|
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
|
+
}
|
910
|
+
|
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
|
+
}
|
928
|
+
|
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
|
+
}
|
954
|
+
|
710
955
|
this.$module = $module;
|
956
|
+
|
957
|
+
var defaultConfig = {
|
958
|
+
disableAutoFocus: false
|
959
|
+
};
|
960
|
+
this.config = mergeConfigs(
|
961
|
+
defaultConfig,
|
962
|
+
config || {},
|
963
|
+
normaliseDataset($module.dataset)
|
964
|
+
);
|
711
965
|
}
|
712
966
|
|
713
967
|
ErrorSummary.prototype.init = function () {
|
@@ -715,16 +969,37 @@ ErrorSummary.prototype.init = function () {
|
|
715
969
|
if (!$module) {
|
716
970
|
return
|
717
971
|
}
|
718
|
-
$module.focus();
|
719
972
|
|
973
|
+
this.setFocus();
|
720
974
|
$module.addEventListener('click', this.handleClick.bind(this));
|
721
975
|
};
|
722
976
|
|
723
977
|
/**
|
724
|
-
*
|
725
|
-
|
726
|
-
|
727
|
-
|
978
|
+
* Focus the error summary
|
979
|
+
*/
|
980
|
+
ErrorSummary.prototype.setFocus = function () {
|
981
|
+
var $module = this.$module;
|
982
|
+
|
983
|
+
if (this.config.disableAutoFocus) {
|
984
|
+
return
|
985
|
+
}
|
986
|
+
|
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
|
+
*/
|
728
1003
|
ErrorSummary.prototype.handleClick = function (event) {
|
729
1004
|
var target = event.target;
|
730
1005
|
if (this.focusTarget(target)) {
|
@@ -848,6 +1123,14 @@ ErrorSummary.prototype.getAssociatedLegendOrLabel = function ($input) {
|
|
848
1123
|
$input.closest('label')
|
849
1124
|
};
|
850
1125
|
|
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
|
+
*/
|
1133
|
+
|
851
1134
|
return ErrorSummary;
|
852
1135
|
|
853
1136
|
})));
|
@@ -8,7 +8,7 @@
|
|
8
8
|
$govuk-footer-text: $govuk-text-colour;
|
9
9
|
$govuk-footer-link-hover-colour: null; // Only used with the legacy palette
|
10
10
|
|
11
|
-
@if
|
11
|
+
@if $govuk-use-legacy-palette {
|
12
12
|
$govuk-footer-border-top: #a1acb2;
|
13
13
|
$govuk-footer-border: govuk-colour("grey-2");
|
14
14
|
$govuk-footer-text: #454a4c;
|
@@ -35,7 +35,7 @@
|
|
35
35
|
.govuk-footer__link {
|
36
36
|
@include govuk-link-common;
|
37
37
|
|
38
|
-
@if
|
38
|
+
@if $govuk-use-legacy-palette {
|
39
39
|
&:link,
|
40
40
|
&:visited {
|
41
41
|
color: $govuk-footer-text;
|
@@ -52,7 +52,7 @@
|
|
52
52
|
// alphagov/govuk_template includes a specific a:link:focus selector
|
53
53
|
// designed to make unvisited links a slightly darker blue when focussed, so
|
54
54
|
// we need to override the text colour for that combination of selectors.
|
55
|
-
@include
|
55
|
+
@include _govuk-compatibility(govuk_template) {
|
56
56
|
&:link:focus {
|
57
57
|
@include govuk-text-colour;
|
58
58
|
}
|
@@ -67,23 +67,16 @@
|
|
67
67
|
}
|
68
68
|
|
69
69
|
.govuk-footer__meta {
|
70
|
-
display: -webkit-box;
|
71
|
-
display: -webkit-flex;
|
72
70
|
display: -ms-flexbox;
|
73
71
|
display: flex; // Support: Flexbox
|
74
72
|
margin-right: -$govuk-gutter-half;
|
75
73
|
margin-left: -$govuk-gutter-half;
|
76
|
-
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
-
|
81
|
-
-
|
82
|
-
align-items: flex-end; // Support: Flexbox
|
83
|
-
-webkit-box-pack: center;
|
84
|
-
-webkit-justify-content: center;
|
85
|
-
-ms-flex-pack: center;
|
86
|
-
justify-content: center; // Support: Flexbox
|
74
|
+
-ms-flex-wrap: wrap;
|
75
|
+
flex-wrap: wrap; // Support: Flexbox
|
76
|
+
-ms-flex-align: end;
|
77
|
+
align-items: flex-end; // Support: Flexbox
|
78
|
+
-ms-flex-pack: center;
|
79
|
+
justify-content: center; // Support: Flexbox
|
87
80
|
}
|
88
81
|
|
89
82
|
.govuk-footer__meta-item {
|
@@ -93,14 +86,11 @@
|
|
93
86
|
}
|
94
87
|
|
95
88
|
.govuk-footer__meta-item--grow {
|
96
|
-
-
|
97
|
-
|
98
|
-
-ms-flex: 1;
|
99
|
-
flex: 1; // Support: Flexbox
|
89
|
+
-ms-flex: 1;
|
90
|
+
flex: 1; // Support: Flexbox
|
100
91
|
@include govuk-media-query ($until: tablet) {
|
101
|
-
-
|
102
|
-
|
103
|
-
flex-basis: 320px; // Support: Flexbox
|
92
|
+
-ms-flex-preferred-size: 320px;
|
93
|
+
flex-basis: 320px; // Support: Flexbox
|
104
94
|
}
|
105
95
|
}
|
106
96
|
|