Skip to content

Commit

Permalink
Merge pull request #1216 from alex-ju/allow-scoped-init
Browse files Browse the repository at this point in the history
Allow initAll to be scoped to a specific part of a page
  • Loading branch information
NickColley authored Mar 8, 2019
2 parents 241a2fe + 586e294 commit 74f6d5a
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 12 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@

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

- Allow initAll to be scoped to a specific part of a page

See ["Initialise GOV.UK Frontend in only certain sections of a page"](docs/installation/installing-with-npm.md#initialise-govuk-frontend-in-only-certain-sections-of-a-page) for more information.

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

🔧 Fixes:

- Pull Request Title goes here
Expand Down Expand Up @@ -157,7 +163,7 @@
Also thanks to [Malcolm Butler](https://github.com/MoJ-Longbeard) for exploring a [previous version of this fix](https://github.com/alphagov/govuk-frontend/pull/1185).

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


## 2.7.0 (Feature release)

Expand Down
63 changes: 63 additions & 0 deletions app/views/examples/scoped-initialisation/index.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{% extends "template.njk" %}

{% from "checkboxes/macro.njk" import govukCheckboxes %}

{% block head %}
<!--[if !IE 8]><!-->
<link rel="stylesheet" href="/public/app.css">
<!--<![endif]-->
<!--[if IE 8]>
<link rel="stylesheet" href="/public/app-ie8.css">
<![endif]-->
<!--[if lt IE 9]>
<script src="/vendor/html5-shiv/html5shiv.js"></script>
<![endif]-->
{% endblock %}

{% block content %}
<h1 class="govuk-heading-xl">Scoped initialisation</h1>
<h2 class="govuk-heading-m">Unscoped section</h2>
<p class="govuk-body">This example should intentionally not have JavaScript functionality</p>

{{ govukCheckboxes({
idPrefix: "not-scoped",
name: "not-scoped",
items: [
{
value: "not-scoped",
text: "Not scoped",
conditional: {
html: '<p class="govuk-body">Revealed not scoped text</p>'
}
}
]
}) }}

<h2 class="govuk-heading-m">Scoped section</h2>
<p class="govuk-body">Only this example should have JavaScript functionality</p>
<div id="scoped">
{{ govukCheckboxes({
idPrefix: "scoped",
name: "scoped",
items: [
{
value: "scoped",
text: "Scoped",
conditional: {
html: '<p class="govuk-body">Revealed scoped text</p>'
}
}
]
}) }}
</div>
{% endblock %}

{% block bodyEnd %}
<script src="/public/all.js"></script>
<script>
var $scope = document.getElementById('scoped')
window.GOVUKFrontend.initAll({
scope: $scope
})
</script>
{% endblock %}
15 changes: 15 additions & 0 deletions docs/installation/installing-with-npm.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,21 @@ Including the script elsewhere will stop components from functioning or displayi
</html>
```

#### Initialise GOV.UK Frontend in only certain sections of a page

By default, the `initAll` function from GOV.UK Frontend initialises all components scoped to an entire page with the `document` object.

You can change this by passing the `scope` parameter to the `initAll` function.

For example, if you have a modal dialog box that opens with new markup you could do the following:

```js
var $modal = document.querySelector('.modal')
window.GOVUKFrontend.initAll({
scope: $modal
})
```

#### Initialise individual included components

GOV.UK Frontend components with JavaScript behaviour have the `data-module` attribute set in their markup.
Expand Down
29 changes: 18 additions & 11 deletions src/all.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,46 +9,53 @@ import Header from './components/header/header'
import Radios from './components/radios/radios'
import Tabs from './components/tabs/tabs'

function initAll () {
// Find all buttons with [role=button] on the document to enhance.
new Button(document).init()
function initAll (options) {
// Set the options to an empty object by default if no options are passed.
options = typeof options !== 'undefined' ? options : {}

// Allow the user to initialise GOV.UK Frontend in only certain sections of the page
// Defaults to the entire document if nothing is set.
var scope = typeof options.scope !== 'undefined' ? options.scope : document

// Find all buttons with [role=button] on the scope to enhance.
new Button(scope).init()

// Find all global accordion components to enhance.
var $accordions = document.querySelectorAll('[data-module="accordion"]')
var $accordions = scope.querySelectorAll('[data-module="accordion"]')
nodeListForEach($accordions, function ($accordion) {
new Accordion($accordion).init()
})

// Find all global details elements to enhance.
var $details = document.querySelectorAll('details')
var $details = scope.querySelectorAll('details')
nodeListForEach($details, function ($detail) {
new Details($detail).init()
})

var $characterCount = document.querySelectorAll('[data-module="character-count"]')
var $characterCount = scope.querySelectorAll('[data-module="character-count"]')
nodeListForEach($characterCount, function ($characterCount) {
new CharacterCount($characterCount).init()
})

var $checkboxes = document.querySelectorAll('[data-module="checkboxes"]')
var $checkboxes = scope.querySelectorAll('[data-module="checkboxes"]')
nodeListForEach($checkboxes, function ($checkbox) {
new Checkboxes($checkbox).init()
})

// Find first error summary module to enhance.
var $errorSummary = document.querySelector('[data-module="error-summary"]')
var $errorSummary = scope.querySelector('[data-module="error-summary"]')
new ErrorSummary($errorSummary).init()

// Find first header module to enhance.
var $toggleButton = document.querySelector('[data-module="header"]')
var $toggleButton = scope.querySelector('[data-module="header"]')
new Header($toggleButton).init()

var $radios = document.querySelectorAll('[data-module="radios"]')
var $radios = scope.querySelectorAll('[data-module="radios"]')
nodeListForEach($radios, function ($radio) {
new Radios($radio).init()
})

var $tabs = document.querySelectorAll('[data-module="tabs"]')
var $tabs = scope.querySelectorAll('[data-module="tabs"]')
nodeListForEach($tabs, function ($tabs) {
new Tabs($tabs).init()
})
Expand Down
22 changes: 22 additions & 0 deletions src/all.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,28 @@ describe('GOV.UK Frontend', () => {
}, component)
})
})
it('can be initialised scoped to certain sections of the page', async () => {
await page.goto(baseUrl + '/examples/scoped-initialisation', { waitUntil: 'load' })

// To test that certain parts of the page are scoped we have two similar components
// that we can interact with to check if they're interactive.

// Check that the conditional reveal component has a conditional section that would open if enhanced.
await page.waitForSelector('#conditional-not-scoped-1', { hidden: true })

await page.click('[for="not-scoped-1"]')

// Check that when it is clicked that nothing opens, which shows that it has not been enhanced.
await page.waitForSelector('#conditional-not-scoped-1', { hidden: true })

// Check the other conditional reveal which has been enhanced based on it's scope.
await page.waitForSelector('#conditional-scoped-1', { hidden: true })

await page.click('[for="scoped-1"]')

// Check that it has opened as expected.
await page.waitForSelector('#conditional-scoped-1', { hidden: false })
})
})
describe('global styles', async () => {
it('are disabled by default', async () => {
Expand Down

0 comments on commit 74f6d5a

Please sign in to comment.