Skip to content

Commit

Permalink
Merge pull request #1472 from alphagov/allow-individual-js-imports
Browse files Browse the repository at this point in the history
Allow individual script imports
  • Loading branch information
alex-ju authored May 21, 2020
2 parents 551f2d2 + c7f05aa commit ee53b58
Show file tree
Hide file tree
Showing 17 changed files with 176 additions and 34 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
useful summary for people upgrading their application, not a replication
of the commit log.

## Unreleased

* Allow individual JavaScript imports ([PR #1472](https://github.com/alphagov/govuk_publishing_components/pull/1472))

To import individual components refer to ['Include the assets section in docs'](https://github.com/alphagov/govuk_publishing_components/blob/master/docs/install-and-use.md) and the 'Suggested imports for this application' section available on `/component-guide` in your application.

## 21.50.1

* Tweak action link ([PR #1518](https://github.com/alphagov/govuk_publishing_components/pull/1518))
Expand Down Expand Up @@ -202,7 +208,7 @@

## 21.26.0

* Allow individual components to be imported into apps ([PR #1159](https://github.com/alphagov/govuk_publishing_components/pull/1159))
* Allow individual Sass imports ([PR #1159](https://github.com/alphagov/govuk_publishing_components/pull/1159))

## 21.25.0

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
// = require_tree ./lib
// = require_tree ./components
// = require govuk/all.js

// Initialise all GOVUKFrontend components
window.GOVUKFrontend.initAll()
window.GOVUKFrontend.initAll = function () {}
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
// This component relies on JavaScript from GOV.UK Frontend
// = require govuk/components/accordion/accordion.js
window.GOVUK = window.GOVUK || {}
window.GOVUK.Modules = window.GOVUK.Modules || {}
window.GOVUK.Modules.Accordion = window.GOVUKFrontend
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// This component relies on JavaScript from GOV.UK Frontend
// = require govuk/components/button/button.js
window.GOVUK = window.GOVUK || {}
window.GOVUK.Modules = window.GOVUK.Modules || {}
window.GOVUK.Modules.Button = window.GOVUKFrontend
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
// This component relies on JavaScript from GOV.UK Frontend
// = require govuk/components/character-count/character-count.js
window.GOVUK = window.GOVUK || {}
window.GOVUK.Modules = window.GOVUK.Modules || {}
window.GOVUK.Modules.CharacterCount = window.GOVUKFrontend
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/* eslint-env jquery */
// = require govuk/components/checkboxes/checkboxes.js
window.GOVUK = window.GOVUK || {}
window.GOVUK.Modules = window.GOVUK.Modules || {};
window.GOVUK.Modules = window.GOVUK.Modules || {}
window.GOVUK.Modules.Checkboxes = window.GOVUKFrontend;

(function (Modules) {
'use strict'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
// This component relies on JavaScript from GOV.UK Frontend
// = require govuk/components/error-summary/error-summary.js
window.GOVUK = window.GOVUK || {}
window.GOVUK.Modules = window.GOVUK.Modules || {}
window.GOVUK.Modules.ErrorSummary = window.GOVUKFrontend
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// This component relies on JavaScript from GOV.UK Frontend
// = require govuk/components/header/header.js
window.GOVUK = window.GOVUK || {}
window.GOVUK.Modules = window.GOVUK.Modules || {}
window.GOVUK.Modules.Header = window.GOVUKFrontend
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
// This component relies on JavaScript from GOV.UK Frontend
// = require govuk/components/radios/radios.js
window.GOVUK = window.GOVUK || {}
window.GOVUK.Modules = window.GOVUK.Modules || {}
window.GOVUK.Modules.Radios = window.GOVUKFrontend
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// This component relies on JavaScript from GOV.UK Frontend
// = require govuk/components/tabs/tabs.js
window.GOVUK = window.GOVUK || {}
window.GOVUK.Modules = window.GOVUK.Modules || {}
window.GOVUK.Modules.Tabs = window.GOVUKFrontend
1 change: 1 addition & 0 deletions app/assets/javascripts/govuk_publishing_components/lib.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// = require_tree ./lib
18 changes: 15 additions & 3 deletions app/assets/javascripts/govuk_publishing_components/modules.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,25 @@
for (var i = 0, l = modules.length; i < l; i++) {
var module
var element = $(modules[i])
var type = camelCaseAndCapitalise(element.data('module'))
var moduleName = camelCaseAndCapitalise(element.data('module'))
var started = element.data('module-started')
var frontendModuleName = moduleName.replace('Govuk', '')

if (typeof GOVUK.Modules[type] === 'function' && !started) {
module = new GOVUK.Modules[type]()
if ( // GOV.UK Publishing & Legacy Modules
typeof GOVUK.Modules[moduleName] === 'function' &&
!GOVUK.Modules[moduleName].prototype.init &&
!started
) {
module = new GOVUK.Modules[moduleName]()
module.start(element)
element.data('module-started', true)
} else if ( // GOV.UK Frontend Modules
typeof GOVUK.Modules[frontendModuleName] === 'function' &&
GOVUK.Modules[frontendModuleName].prototype.init &&
!started
) {
module = new GOVUK.Modules[frontendModuleName](element[0]).init()
element.data('module-started', true)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ def index
@components_in_use_docs = components_in_use_docs.used_in_this_app
@components_in_use_sass = components_in_use_sass(false)
@components_in_use_print_sass = components_in_use_sass(true)
@components_in_use_js = components_in_use_js
end

def show
Expand Down Expand Up @@ -62,6 +63,25 @@ def components_in_use_sass(print_styles)
}.compact.uniq.sort.join("\n").squeeze("\n").prepend(additional_files)
end

def components_in_use_js
additional_files = "//= require govuk_publishing_components/lib\n"

components = components_in_use
extra_components = []

components.each do |component|
components_in_component = components_within_component(component)
extra_components << components_in_component
end

components << extra_components.compact
components = components.flatten.uniq.sort

components.map { |component|
"//= require govuk_publishing_components/components/#{component.gsub('_', '-')}" if component_has_js_file(component.gsub("_", "-"))
}.compact.uniq.sort.join("\n").squeeze("\n").prepend(additional_files)
end

private

def component_docs
Expand Down Expand Up @@ -95,6 +115,10 @@ def component_has_sass_file(component, print_styles)
Pathname.new(@component_gem_path + "/app/assets/stylesheets/govuk_publishing_components/components/#{print_path}_#{component}.scss").exist?
end

def component_has_js_file(component)
Pathname.new(@component_gem_path + "/app/assets/javascripts/govuk_publishing_components/components/#{component}.js").exist?
end

def components_within_component(component)
data = File.read(@component_gem_path + "/app/views/govuk_publishing_components/components/_#{component}.html.erb")
match = data.scan(/(govuk_publishing_components\/components\/[a-z_-]+)/)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<h2 class="component-doc-h2">Gem components used by this app (<%= @components_in_use_docs.length %>)</h2>

<%= render "govuk_publishing_components/components/details", {
title: "Suggested Sass for this application"
title: "Suggested imports for this application"
} do %>
<%= render "govuk_publishing_components/components/textarea", {
label: {
Expand All @@ -36,6 +36,13 @@
name: "print-sass",
value: @components_in_use_print_sass
} %>
<%= render "govuk_publishing_components/components/textarea", {
label: {
text: "Add this to your application's main js file, before your other local imports."
},
name: "main-js",
value: @components_in_use_js
} %>
<% end %>
<pre>

Expand Down
25 changes: 22 additions & 3 deletions docs/install-and-use.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ For example:
@import 'govuk_publishing_components/components/_back-link';
```

If you load the component guide in the application the suggested Sass for it has been generated for you. Click the 'Suggested Sass for this application' link, then copy and paste the output into your `application.scss` file. Remember to also copy the suggested print Sass into your application's `print.scss` file.
If you load the component guide in the application the suggested Sass for it has been generated for you. Click the 'Suggested imports for this application' link, then copy and paste the output into your `application.scss` file. Remember to also copy the suggested print Sass into your application's `print.scss` file.

### Import all Sass (deprecated, will be removed in a later version)

Expand All @@ -83,9 +83,28 @@ And for print styles
@import "govuk_publishing_components/all_components_print";
```

### Javascript
### Import JavaScript for individual components

If your application doesn't use Slimmer/Static (newer admin applications):
If your application doesn't use Slimmer/Static:

```js
# application.js
//= require govuk_publishing_components/dependencies
//= require govuk_publishing_components/lib
//= require govuk_publishing_components/components/button
```

If your application does use Slimmer/Static:

```js
# application.js
//= require govuk_publishing_components/lib
//= require govuk_publishing_components/components/button
```

### Import all Javascript (deprecated, will be removed in a later version)

If your application doesn't use Slimmer/Static:

```js
# application.js
Expand Down
13 changes: 12 additions & 1 deletion spec/component_guide/component_index_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
@import 'govuk_publishing_components/components/title';"

expect(page).to have_selector(".component-doc-h2", text: "Gem components used by this app (12)")
expect(page).to have_selector(".govuk-details__summary-text", text: "Suggested Sass for this application")
expect(page).to have_selector(".govuk-details__summary-text", text: "Suggested imports for this application")

expect(page.find(:css, 'textarea[name="main-sass"]', visible: false).value).to eq(expected_main_sass)
end
Expand All @@ -86,6 +86,17 @@
expect(page.find(:css, 'textarea[name="print-sass"]', visible: false).value).to eq(expected_print_sass)
end

it "includes suggested js for the application" do
visit "/component-guide"
expected_main_js = "//= require govuk_publishing_components/lib
//= require govuk_publishing_components/components/error-summary
//= require govuk_publishing_components/components/govspeak
//= require govuk_publishing_components/components/step-by-step-nav
//= require govuk_publishing_components/components/tabs"

expect(page.find(:css, 'textarea[name="main-js"]', visible: false).value).to eq(expected_main_js)
end

it "creates a page for the component" do
visit "/component-guide/test-component"
expect(body).to include("A test component for the dummy app")
Expand Down
78 changes: 57 additions & 21 deletions spec/javascripts/govuk_publishing_components/modules.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,61 +34,97 @@ describe('GOVUK Modules', function () {
container.remove()
})

describe('when a module exists', function () {
var callback
describe('when modules exist', function () {
var container
var callbackLegacyModule
var callbackGovukModule
var callbackFrontendModule

beforeEach(function () {
callback = jasmine.createSpy()
GOVUK.Modules.TestAlertModule = function () {
callbackLegacyModule = jasmine.createSpy()
callbackGovukModule = jasmine.createSpy()
callbackFrontendModule = jasmine.createSpy()

// GOV.UK Frontend Toolkit Modules
GOVUK.Modules.LegacyTestAlertModule = function () {
var that = this
that.start = function (element) {
callback(element)
callbackLegacyModule(element)
}
}

// GOV.UK Publishing Modules
function GovukTestAlertModule () { }
GovukTestAlertModule.prototype.start = function (element) {
callbackGovukModule(element)
}
GOVUK.Modules.GovukTestAlertModule = GovukTestAlertModule

// GOV.UK Frontend Modules
function TestAlertModule (element) {
this.element = element
}
TestAlertModule.prototype.init = function () {
callbackFrontendModule(this.element)
}
GOVUK.Modules.TestAlertModule = TestAlertModule

container = $('<div></div>')
})

afterEach(function () {
delete GOVUK.Modules.LegacyTestAlertModule
delete GOVUK.Modules.GovukTestAlertModule
delete GOVUK.Modules.TestAlertModule

container.remove()
})

it('starts modules within a container', function () {
var module = $('<div data-module="test-alert-module"></div>')
var container = $('<div></div>').append(module)
var legacyModule = $('<div data-module="legacy-test-alert-module"></div>')
var publishingModule = $('<div data-module="govuk-test-alert-module"></div>')
var frontendModule = $('<div data-module="test-alert-module"></div>')
container.append(legacyModule).append(publishingModule).append(frontendModule)

GOVUK.modules.start(container)
expect(callback).toHaveBeenCalled()
expect(callbackLegacyModule).toHaveBeenCalled()
expect(callbackGovukModule).toHaveBeenCalled()
expect(callbackFrontendModule).toHaveBeenCalled()
})

it('does not start modules that are already started', function () {
var module = $('<div data-module="test-alert-module"></div>')
$('<div></div>').append(module)
var module = $('<div data-module="legacy-test-alert-module"></div>')
container.append(module)

GOVUK.modules.start(module)
GOVUK.modules.start(module)
expect(callback.calls.count()).toBe(1)
expect(callbackLegacyModule.calls.count()).toBe(1)
})

it('passes the HTML element to the module\'s start method', function () {
var module = $('<div data-module="test-alert-module"></div>')
var container = $('<h1></h1>').append(module)
it('passes the HTML element to the modules start method', function () {
var module = $('<div data-module="legacy-test-alert-module"></div>')
container.append(module)

GOVUK.modules.start(container)

var args = callback.calls.argsFor(0)
expect(args[0].is('div[data-module="test-alert-module"]')).toBe(true)
var args = callbackLegacyModule.calls.argsFor(0)
expect(args[0].is('div[data-module="legacy-test-alert-module"]')).toBe(true)
})

it('starts all modules that are on the page', function () {
var modules = $(
'<div data-module="test-alert-module"></div>' +
'<strong data-module="test-alert-module"></strong>' +
'<span data-module="test-alert-module"></span>'
'<div data-module="legacy-test-alert-module"></div>' +
'<strong data-module="legacy-test-alert-module"></strong>' +
'<span data-module="legacy-test-alert-module"></span>' +
'<div data-module="govuk-test-alert-module"></div>' +
'<div data-module="test-alert-module"></div>'
)

$('body').append(modules)
GOVUK.modules.start()
expect(callback.calls.count()).toBe(3)

expect(callbackLegacyModule.calls.count()).toBe(3)
expect(callbackGovukModule.calls.count()).toBe(1)
expect(callbackFrontendModule.calls.count()).toBe(1)
modules.remove()
})
})
Expand Down

0 comments on commit ee53b58

Please sign in to comment.