Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release v2.4.0 #1066

Merged
merged 1 commit into from
Nov 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@

([PR #N](https://github.com/alphagov/govuk-frontend/pull/N))

🔧 Fixes:

- Pull Request Title goes here

Description goes here (optional)

([PR #N](https://github.com/alphagov/govuk-frontend/pull/N))

## 2.4.0 (Feature release)

🆕 New features:

- Scroll to label or legend when linked from error summary

When users click links in the error summary, the corresponding label or legend
Expand All @@ -41,12 +53,6 @@

🔧 Fixes:

- Pull Request Title goes here

Description goes here (optional)

([PR #N](https://github.com/alphagov/govuk-frontend/pull/N))

- Remove implicit dependency on Element for classList

([PR #1063](https://github.com/alphagov/govuk-frontend/pull/1063))
Expand Down
2 changes: 1 addition & 1 deletion dist/VERSION.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.3.0
2.4.0
File renamed without changes.

Large diffs are not rendered by default.

162 changes: 161 additions & 1 deletion package/all.js
Original file line number Diff line number Diff line change
Expand Up @@ -1159,7 +1159,7 @@ Details.prototype.destroy = function (node) {

if (detect) return

// Polyfill from https://raw.githubusercontent.com/Financial-Times/polyfill-service/8717a9e04ac7aff99b4980fbedead98036b0929a/packages/polyfill-library/polyfills/Element/prototype/classList/polyfill.js
// Polyfill from https://cdn.polyfill.io/v2/polyfill.js?features=Element.prototype.classList&flags=always
(function (global) {
var dpSupport = true;
var defineGetter = function (object, name, fn, configurable) {
Expand Down Expand Up @@ -1470,6 +1470,53 @@ Checkboxes.prototype.handleClick = function (event) {
}
};

(function(undefined) {

// Detection from https://raw.githubusercontent.com/Financial-Times/polyfill-service/1f3c09b402f65bf6e393f933a15ba63f1b86ef1f/packages/polyfill-library/polyfills/Element/prototype/matches/detect.js
var detect = (
'document' in this && "matches" in document.documentElement
);

if (detect) return

// Polyfill from https://raw.githubusercontent.com/Financial-Times/polyfill-service/1f3c09b402f65bf6e393f933a15ba63f1b86ef1f/packages/polyfill-library/polyfills/Element/prototype/matches/polyfill.js
Element.prototype.matches = Element.prototype.webkitMatchesSelector || Element.prototype.oMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.mozMatchesSelector || function matches(selector) {
var element = this;
var elements = (element.document || element.ownerDocument).querySelectorAll(selector);
var index = 0;

while (elements[index] && elements[index] !== element) {
++index;
}

return !!elements[index];
};

}).call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});

(function(undefined) {

// Detection from https://raw.githubusercontent.com/Financial-Times/polyfill-service/1f3c09b402f65bf6e393f933a15ba63f1b86ef1f/packages/polyfill-library/polyfills/Element/prototype/closest/detect.js
var detect = (
'document' in this && "closest" in document.documentElement
);

if (detect) return

// Polyfill from https://raw.githubusercontent.com/Financial-Times/polyfill-service/1f3c09b402f65bf6e393f933a15ba63f1b86ef1f/packages/polyfill-library/polyfills/Element/prototype/closest/polyfill.js
Element.prototype.closest = function closest(selector) {
var node = this;

while (node) {
if (node.matches(selector)) return node;
else node = 'SVGElement' in window && node instanceof SVGElement ? node.parentNode : node.parentElement;
}

return null;
};

}).call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});

function ErrorSummary ($module) {
this.$module = $module;
}
Expand All @@ -1482,6 +1529,119 @@ ErrorSummary.prototype.init = function () {
window.addEventListener('load', function () {
$module.focus();
});

$module.addEventListener('click', this.handleClick.bind(this));
};

/**
* Click event handler
*
* @param {MouseEvent} event - Click event
*/
ErrorSummary.prototype.handleClick = function (event) {
var target = event.target;
if (this.focusTarget(target)) {
event.preventDefault();
}
};

/**
* Focus the target element
*
* By default, the browser will scroll the target into view. Because our labels
* or legends appear above the input, this means the user will be presented with
* an input without any context, as the label or legend will be off the top of
* the screen.
*
* Manually handling the click event, scrolling the question into view and then
* focussing the element solves this.
*
* This also results in the label and/or legend being announced correctly in
* NVDA (as tested in 2018.3.2) - without this only the field type is announced
* (e.g. "Edit, has autocomplete").
*
* @param {HTMLElement} $target - Event target
* @returns {boolean} True if the target was able to be focussed
*/
ErrorSummary.prototype.focusTarget = function ($target) {
// If the element that was clicked was not a link, return early
if ($target.tagName !== 'A' || $target.href === false) {
return false
}

var inputId = this.getFragmentFromUrl($target.href);
var $input = document.getElementById(inputId);
if (!$input) {
return false
}

var $legendOrLabel = this.getAssociatedLegendOrLabel($input);
if (!$legendOrLabel) {
return false
}

// Prefer using the history API where possible, as updating
// window.location.hash causes the viewport to jump to the input briefly
// before then scrolling to the label/legend in IE10, IE11 and Edge (as tested
// in Edge 17).
if (window.history.pushState) {
window.history.pushState(null, null, '#' + inputId);
} else {
window.location.hash = inputId;
}

// Scroll the legend or label into view *before* calling focus on the input to
// avoid extra scrolling in browsers that don't support `preventScroll` (which
// at time of writing is most of them...)
$legendOrLabel.scrollIntoView();
$input.focus({ preventScroll: true });

return true
};

/**
* Get fragment from URL
*
* Extract the fragment (everything after the hash) from a URL, but not including
* the hash.
*
* @param {string} url - URL
* @returns {string} Fragment from URL, without the hash
*/
ErrorSummary.prototype.getFragmentFromUrl = function (url) {
if (url.indexOf('#') === -1) {
return false
}

return url.split('#').pop()
};

/**
* Get associated legend or label
*
* Returns the first element that exists from this list:
*
* - The `<legend>` associated with the closest `<fieldset>` ancestor
* - The first `<label>` that is associated with the input using for="inputId"
* - The closest parent `<label>`
*
* @param {HTMLElement} $input - The input
* @returns {HTMLElement} Associated legend or label, or null if no associated
* legend or label can be found
*/
ErrorSummary.prototype.getAssociatedLegendOrLabel = function ($input) {
var $fieldset = $input.closest('fieldset');

if ($fieldset) {
var legends = $fieldset.getElementsByTagName('legend');

if (legends.length) {
return legends[0]
}
}

return document.querySelector("label[for='" + $input.getAttribute('id') + "']") ||
$input.closest('label')
};

function Header ($module) {
Expand Down
80 changes: 3 additions & 77 deletions package/components/back-link/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,85 +59,11 @@ In order to include the images used in the components, you need to configure you

app.use('/assets', express.static(path.join(__dirname, '/node_modules/govuk-frontend/assets')))

## Component arguments
## Component options

If you are using Nunjucks,then macros take the following arguments
Use options to customise the appearance, content and behaviour of a component when using a macro, for example, changing the text.

**If you’re using Nunjucks macros in production be aware that using `html` arguments, or ones ending with `Html` can be a [security risk](https://en.wikipedia.org/wiki/Cross-site_scripting). More about it in the [Nunjucks documentation](https://mozilla.github.io/nunjucks/api.html#user-defined-templates-warning).**

<table class="govuk-table">

<thead class="govuk-table__head">

<tr class="govuk-table__row">

<th class="govuk-table__header" scope="col">Name</th>

<th class="govuk-table__header" scope="col">Type</th>

<th class="govuk-table__header" scope="col">Required</th>

<th class="govuk-table__header" scope="col">Description</th>

</tr>

</thead>

<tbody class="govuk-table__body">

<tr class="govuk-table__row">

<th class="govuk-table__header" scope="row">text (or) html</th>

<td class="govuk-table__cell">string</td>

<td class="govuk-table__cell">Yes</td>

<td class="govuk-table__cell">Text or HTML to use within the back link component. If `html` is provided, the `text` argument will be ignored.</td>

</tr>

<tr class="govuk-table__row">

<th class="govuk-table__header" scope="row">href</th>

<td class="govuk-table__cell">string</td>

<td class="govuk-table__cell">Yes</td>

<td class="govuk-table__cell">The value of the link href attribute</td>

</tr>

<tr class="govuk-table__row">

<th class="govuk-table__header" scope="row">classes</th>

<td class="govuk-table__cell">string</td>

<td class="govuk-table__cell">No</td>

<td class="govuk-table__cell">Optional additional classes to add to the anchor tag.</td>

</tr>

<tr class="govuk-table__row">

<th class="govuk-table__header" scope="row">attributes</th>

<td class="govuk-table__cell">object</td>

<td class="govuk-table__cell">No</td>

<td class="govuk-table__cell">Any extra HTML attributes (for example data attributes) to add to the anchor tag.</td>

</tr>

</tbody>

</table>

**If you’re using Nunjucks macros in production be aware that using `html` arguments, or ones ending with `Html` can be a [security risk](https://en.wikipedia.org/wiki/Cross-site_scripting). More about it in the [Nunjucks documentation](https://mozilla.github.io/nunjucks/api.html#user-defined-templates-warning).**
See [options table](https://design-system.service.gov.uk/components/back-link/#options-example-default) for details.

### Setting up Nunjucks views and paths

Expand Down
Loading