diff --git a/CHANGELOG.md b/CHANGELOG.md index cfa5da8d2a..8c1164c8bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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)) @@ -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 diff --git a/app/assets/javascripts/govuk_publishing_components/all_components.js b/app/assets/javascripts/govuk_publishing_components/all_components.js index 0351d88f06..1b203f7fd6 100644 --- a/app/assets/javascripts/govuk_publishing_components/all_components.js +++ b/app/assets/javascripts/govuk_publishing_components/all_components.js @@ -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 () {} diff --git a/app/assets/javascripts/govuk_publishing_components/components/accordion.js b/app/assets/javascripts/govuk_publishing_components/components/accordion.js index 4bfc836ba9..f7a1fac093 100644 --- a/app/assets/javascripts/govuk_publishing_components/components/accordion.js +++ b/app/assets/javascripts/govuk_publishing_components/components/accordion.js @@ -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 diff --git a/app/assets/javascripts/govuk_publishing_components/components/button.js b/app/assets/javascripts/govuk_publishing_components/components/button.js new file mode 100644 index 0000000000..ca940893b2 --- /dev/null +++ b/app/assets/javascripts/govuk_publishing_components/components/button.js @@ -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 diff --git a/app/assets/javascripts/govuk_publishing_components/components/character-count.js b/app/assets/javascripts/govuk_publishing_components/components/character-count.js index 6f7315a069..a62080c237 100644 --- a/app/assets/javascripts/govuk_publishing_components/components/character-count.js +++ b/app/assets/javascripts/govuk_publishing_components/components/character-count.js @@ -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 diff --git a/app/assets/javascripts/govuk_publishing_components/components/checkboxes.js b/app/assets/javascripts/govuk_publishing_components/components/checkboxes.js index b636e4c43b..27b40bbbeb 100644 --- a/app/assets/javascripts/govuk_publishing_components/components/checkboxes.js +++ b/app/assets/javascripts/govuk_publishing_components/components/checkboxes.js @@ -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' diff --git a/app/assets/javascripts/govuk_publishing_components/components/error-summary.js b/app/assets/javascripts/govuk_publishing_components/components/error-summary.js index e59cbc91bc..63152d0df9 100644 --- a/app/assets/javascripts/govuk_publishing_components/components/error-summary.js +++ b/app/assets/javascripts/govuk_publishing_components/components/error-summary.js @@ -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 diff --git a/app/assets/javascripts/govuk_publishing_components/components/header.js b/app/assets/javascripts/govuk_publishing_components/components/header.js new file mode 100644 index 0000000000..5d02474bba --- /dev/null +++ b/app/assets/javascripts/govuk_publishing_components/components/header.js @@ -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 diff --git a/app/assets/javascripts/govuk_publishing_components/components/radio.js b/app/assets/javascripts/govuk_publishing_components/components/radio.js index 960cef74ce..763d727878 100644 --- a/app/assets/javascripts/govuk_publishing_components/components/radio.js +++ b/app/assets/javascripts/govuk_publishing_components/components/radio.js @@ -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 diff --git a/app/assets/javascripts/govuk_publishing_components/components/tabs.js b/app/assets/javascripts/govuk_publishing_components/components/tabs.js new file mode 100644 index 0000000000..d053dbadb4 --- /dev/null +++ b/app/assets/javascripts/govuk_publishing_components/components/tabs.js @@ -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 diff --git a/app/assets/javascripts/govuk_publishing_components/lib.js b/app/assets/javascripts/govuk_publishing_components/lib.js new file mode 100644 index 0000000000..6288933c96 --- /dev/null +++ b/app/assets/javascripts/govuk_publishing_components/lib.js @@ -0,0 +1 @@ +// = require_tree ./lib diff --git a/app/assets/javascripts/govuk_publishing_components/modules.js b/app/assets/javascripts/govuk_publishing_components/modules.js index e0441b62ce..abee7ae508 100644 --- a/app/assets/javascripts/govuk_publishing_components/modules.js +++ b/app/assets/javascripts/govuk_publishing_components/modules.js @@ -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) } } diff --git a/app/controllers/govuk_publishing_components/component_guide_controller.rb b/app/controllers/govuk_publishing_components/component_guide_controller.rb index beeea48d68..e846ee1ed2 100644 --- a/app/controllers/govuk_publishing_components/component_guide_controller.rb +++ b/app/controllers/govuk_publishing_components/component_guide_controller.rb @@ -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 @@ -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 @@ -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_-]+)/) diff --git a/app/views/govuk_publishing_components/component_guide/index.html.erb b/app/views/govuk_publishing_components/component_guide/index.html.erb index 8405c90279..ec7c1cc91e 100644 --- a/app/views/govuk_publishing_components/component_guide/index.html.erb +++ b/app/views/govuk_publishing_components/component_guide/index.html.erb @@ -20,7 +20,7 @@
diff --git a/docs/install-and-use.md b/docs/install-and-use.md index c9ba2940fc..2b1171c0a3 100644 --- a/docs/install-and-use.md +++ b/docs/install-and-use.md @@ -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) @@ -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 diff --git a/spec/component_guide/component_index_spec.rb b/spec/component_guide/component_index_spec.rb index e9b8c29dd3..1f39ecaab7 100644 --- a/spec/component_guide/component_index_spec.rb +++ b/spec/component_guide/component_index_spec.rb @@ -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 @@ -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") diff --git a/spec/javascripts/govuk_publishing_components/modules.spec.js b/spec/javascripts/govuk_publishing_components/modules.spec.js index 91cab74acb..60952bd76b 100644 --- a/spec/javascripts/govuk_publishing_components/modules.spec.js +++ b/spec/javascripts/govuk_publishing_components/modules.spec.js @@ -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 = $('') }) 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 = $('') - var container = $('').append(module) + var legacyModule = $('') + var publishingModule = $('') + var frontendModule = $('') + 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 = $('') - $('').append(module) + var module = $('') + 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 = $('') - var container = $('').append(module) + it('passes the HTML element to the module’s start method', function () { + var module = $('') + 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 = $( - '' + - '' + - '' + '' + + '' + + '' + + '' + + '' ) $('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() }) })