diff --git a/.travis.yml b/.travis.yml
index 62fea3bfb..9ea2b6da2 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,7 +6,7 @@ before_install:
install:
- npm install
script:
-- "./node_modules/grunt-cli/bin/grunt test"
+- npm test
notifications:
email: false
before_deploy:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 7e19f27c3..94bec39e1 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -5,6 +5,7 @@ guidelines:
## Indentation and whitespace
+Your JavaScript code should pass [linting](https://github.com/alphagov/govuk_prototype_kit/blob/0d9835b7ad8d7bc06aa288204eb3ce9a07116be2/docs/linting.md).
2-space, soft-tabs only. No trailing whitespace.
## Versioning
diff --git a/Gruntfile.js b/Gruntfile.js
index b9c436544..cd6057c2c 100755
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -1,5 +1,4 @@
module.exports = function (grunt) {
-
grunt.initConfig({
// Builds Sass
@@ -14,7 +13,7 @@ module.exports = function (grunt) {
'public/stylesheets/elements-page-ie6.css': 'public/sass/elements-page-ie6.scss',
'public/stylesheets/elements-page-ie7.css': 'public/sass/elements-page-ie7.scss',
'public/stylesheets/elements-page-ie8.css': 'public/sass/elements-page-ie8.scss',
- 'public/stylesheets/prism.css': 'public/sass/prism.scss',
+ 'public/stylesheets/prism.css': 'public/sass/prism.scss'
},
options: {
includePaths: [
@@ -29,7 +28,7 @@ module.exports = function (grunt) {
// Empty encoded snippets folder
clean: {
- contents: ['app/views/snippets/encoded/*'],
+ contents: ['app/views/snippets/encoded/*']
},
// Copies templates and assets from external modules and dirs
@@ -59,11 +58,11 @@ module.exports = function (grunt) {
govuk_template_jinja: {
files: [{
expand: true,
- cwd: 'govuk_modules/govuk_template/views/layouts/',
- src: '**',
- dest: 'lib/'
- }]
- },
+ cwd: 'govuk_modules/govuk_template/views/layouts/',
+ src: '**',
+ dest: 'lib/'
+ }]
+ }
},
// Encode HTML snippets
@@ -71,7 +70,7 @@ module.exports = function (grunt) {
files: {
src: ['app/views/snippets/*.html'],
dest: 'app/views/snippets/encoded/'
- },
+ }
},
// workaround for libsass
@@ -124,9 +123,9 @@ module.exports = function (grunt) {
}
}
- });
+ })
- [
+ ;[
'grunt-contrib-clean',
'grunt-contrib-copy',
'grunt-contrib-watch',
@@ -136,8 +135,8 @@ module.exports = function (grunt) {
'grunt-shell',
'grunt-htmlentities'
].forEach(function (task) {
- grunt.loadNpmTasks(task);
- });
+ grunt.loadNpmTasks(task)
+ })
grunt.registerTask('default', [
'clean',
@@ -145,7 +144,7 @@ module.exports = function (grunt) {
'encode_snippets',
'sass',
'concurrent:target'
- ]);
+ ])
grunt.registerTask(
'test_default',
@@ -154,45 +153,45 @@ module.exports = function (grunt) {
'copy',
'sass'
]
- );
+ )
grunt.registerTask(
'encode_snippets',
'Encode HTML snippets',
- function() {
- grunt.task.run('htmlentities');
+ function () {
+ grunt.task.run('htmlentities')
}
- );
+ )
grunt.registerTask(
'lint',
'Use govuk-scss-lint to lint the sass files',
- function() {
- grunt.task.run('shell', 'lint_message');
+ function () {
+ grunt.task.run('shell', 'lint_message')
}
- );
+ )
grunt.registerTask(
'lint_message',
'Output a message once linting is complete',
- function() {
- grunt.log.write("scss lint is complete, without errors.");
+ function () {
+ grunt.log.write('scss lint is complete, without errors.')
}
- );
+ )
grunt.registerTask(
'test',
'Lint the Sass files, then check the app runs',
- function() {
- grunt.task.run('lint', 'test_default', 'test_message');
+ function () {
+ grunt.task.run('lint', 'test_default', 'test_message')
}
- );
+ )
grunt.registerTask(
'test_message',
'Output a message once the tests are complete',
- function() {
- grunt.log.write("scss lint is complete and the app runs, without errors.");
+ function () {
+ grunt.log.write('scss lint is complete and the app runs, without errors.')
}
- );
-};
+ )
+}
diff --git a/README.md b/README.md
index fd47374c8..7416c284d 100644
--- a/README.md
+++ b/README.md
@@ -150,6 +150,22 @@ Run the app
Go to [localhost:3000](http://localhost:3000) in your browser.
+## Linting
+
+### GOV.UK lint
+[GOV.UK elements uses govuk-lint](https://github.com/alphagov/govuk-lint#sass), which uses [scss-lint](https://github.com/brigade/scss-lint) as its scss linter.
+
+### Standard JavaScript
+GOV.UK elements uses [standardjs](http://standardjs.com/), an opinionated JavaScript linter. All JavaScript files follow its conventions.
+
+Both linters run on CI to ensure that new pull requests are in line with them.
+
+## Linting
+
+To check the whole codebase, run:
+
+ npm test
+
## Running Wraith to compare changes
GOV.UK elements uses Wraith so that regressions can be easily spotted.
diff --git a/app/config.js b/app/config.js
index 4f41d2ea2..5ad868b04 100644
--- a/app/config.js
+++ b/app/config.js
@@ -7,4 +7,4 @@ module.exports = {
// Cookie warning
cookieText: 'GOV.UK uses cookies to make the site simpler. Find out more about cookies'
-};
+}
diff --git a/app/routes.js b/app/routes.js
index ceef8ece1..3f0bb0ead 100755
--- a/app/routes.js
+++ b/app/routes.js
@@ -1,221 +1,219 @@
module.exports = {
- bind : function (app, asset_path) {
-
+ bind: function (app, assetPath) {
app.get('/', function (req, res) {
- res.render('index', {'asset_path' : asset_path });
- });
+ res.render('index', { 'asset_path': assetPath })
+ })
// Redirect snippets page to the index page
app.get('/snippets', function (req, res) {
- res.redirect('/');
- });
+ res.redirect('/')
+ })
app.get('/style-guide', function (req, res) {
- var page_name = "Front-end style guide";
- res.render('guide_style_guide', { 'page_name' : page_name });
- });
+ var pageName = 'Front-end style guide'
+ res.render('guide_style_guide', { 'page_name': pageName })
+ })
// Layout
app.get('/layout', function (req, res) {
- var page_name = "Layout";
- res.render('guide_layout', { 'page_name' : page_name });
- });
+ var pageName = 'Layout'
+ res.render('guide_layout', { 'page_name': pageName })
+ })
// Example page: Grid layout
app.get('/layout/example-grid-layout', function (req, res) {
- var section = "layout";
- var section_name = "Layout";
- var page_name = "Example: Grid layout";
- res.render('examples/example_grid_layout', { 'section': section, 'section_name' : section_name, 'page_name' : page_name });
- });
+ var section = 'layout'
+ var sectionName = 'Layout'
+ var pageName = 'Example: Grid layout'
+ res.render('examples/example_grid_layout', { 'section': section, 'section_name': sectionName, 'page_name': pageName })
+ })
// Redirect examples from /examples/ to /section/example-name-of-example
app.get('/examples/grid-layout', function (req, res) {
- res.redirect('/layout/example-grid-layout');
- });
+ res.redirect('/layout/example-grid-layout')
+ })
// Typography
app.get('/typography', function (req, res) {
- var page_name = "Typography";
- res.render('guide_typography', { 'page_name' : page_name });
- });
+ var pageName = 'Typography'
+ res.render('guide_typography', { 'page_name': pageName })
+ })
// Example page: Typography
app.get('/typography/example-typography', function (req, res) {
- var section = "typography";
- var section_name = "Typography";
- var page_name = "Example: Typography";
- res.render('examples/example_typography', { 'section': section, 'section_name' : section_name, 'page_name' : page_name });
- });
+ var section = 'typography'
+ var sectionName = 'Typography'
+ var pageName = 'Example: Typography'
+ res.render('examples/example_typography', { 'section': section, 'section_name': sectionName, 'page_name': pageName })
+ })
// Redirect examples from /examples/ to /section/example-name-of-example
app.get('/examples/typography', function (req, res) {
- res.redirect('/typography/example-typography');
- });
+ res.redirect('/typography/example-typography')
+ })
// Example page: Progressive disclosure
app.get('/typography/example-details-summary', function (req, res) {
- var section = "typography";
- var section_name = "Typography";
- var page_name = "Example: Details summary";
- res.render('examples/example_details_summary', { 'section': section, 'section_name' : section_name, 'page_name' : page_name });
- });
+ var section = 'typography'
+ var sectionName = 'Typography'
+ var pageName = 'Example: Details summary'
+ res.render('examples/example_details_summary', { 'section': section, 'section_name': sectionName, 'page_name': pageName })
+ })
// Redirect examples from /patterns/ to /section/example-name-of-example
app.get('/patterns/details-summary', function (req, res) {
- res.redirect('/typography/example-details-summary');
- });
+ res.redirect('/typography/example-details-summary')
+ })
// Colour
app.get('/colour', function (req, res) {
- var page_name = "Colour";
- res.render('guide_colour', { 'page_name' : page_name });
- });
+ var pageName = 'Colour'
+ res.render('guide_colour', { 'page_name': pageName })
+ })
// Icons and images
app.get('/icons-images', function (req, res) {
- var page_name = "Icons and images";
- res.render('guide_icons_images', { 'page_name' : page_name });
- });
+ var pageName = 'Icons and images'
+ res.render('guide_icons_images', { 'page_name': pageName })
+ })
// Example page: Icons
app.get('/icons-images/example-icons', function (req, res) {
- var section = "icons-images";
- var section_name = "Icons and images";
- var page_name = "Example: Icons";
- res.render('examples/example_icons', { 'section': section, 'section_name' : section_name, 'page_name' : page_name });
- });
+ var section = 'icons-images'
+ var sectionName = 'Icons and images'
+ var pageName = 'Example: Icons'
+ res.render('examples/example_icons', { 'section': section, 'section_name': sectionName, 'page_name': pageName })
+ })
// Data
app.get('/data', function (req, res) {
- var page_name = "Data";
- res.render('guide_data', { 'page_name' : page_name });
- });
+ var pageName = 'Data'
+ res.render('guide_data', { 'page_name': pageName })
+ })
// Buttons
app.get('/buttons', function (req, res) {
- var page_name = "Buttons";
- res.render('guide_buttons', { 'page_name' : page_name });
- });
+ var pageName = 'Buttons'
+ res.render('guide_buttons', { 'page_name': pageName })
+ })
// Forms
app.get('/form-elements', function (req, res) {
- var page_name = "Form elements";
- res.render('guide_form_elements', { 'page_name' : page_name });
- });
+ var pageName = 'Form elements'
+ res.render('guide_form_elements', { 'page_name': pageName })
+ })
// Example page: Basic form
app.get('/form-elements/example-forms', function (req, res) {
- var section = "form-elements";
- var section_name = "Form elements";
- var page_name = "Example: Form";
- res.render('examples/example_forms', { 'section': section, 'section_name' : section_name, 'page_name' : page_name });
- });
+ var section = 'form-elements'
+ var sectionName = 'Form elements'
+ var pageName = 'Example: Form'
+ res.render('examples/example_forms', { 'section': section, 'section_name': sectionName, 'page_name': pageName })
+ })
// Redirect examples from /examples/ to /section/example-name-of-example
app.get('/examples/forms', function (req, res) {
- res.redirect('/form-elements/example-forms');
- });
+ res.redirect('/form-elements/example-forms')
+ })
// Example page: Date pattern
app.get('/form-elements/example-date', function (req, res) {
- var section = "form-elements";
- var section_name = "Form elements";
- var page_name = "Example: Date";
- res.render('examples/example_date', { 'section': section, 'section_name' : section_name, 'page_name' : page_name });
- });
+ var section = 'form-elements'
+ var sectionName = 'Form elements'
+ var pageName = 'Example: Date'
+ res.render('examples/example_date', { 'section': section, 'section_name': sectionName, 'page_name': pageName })
+ })
// Redirect examples from /patterns/ to /section/example-name-of-example
app.get('/patterns/date', function (req, res) {
- res.redirect('/form-elements/example-date');
- });
+ res.redirect('/form-elements/example-date')
+ })
// Example page: Radio buttons and checkboxes
app.get('/form-elements/example-radios-checkboxes', function (req, res) {
- var section = "form-elements";
- var section_name = "Form elements";
- var page_name = "Example: Radio buttons and checkboxes";
- res.render('examples/example_radios_checkboxes', { 'section': section, 'section_name' : section_name, 'page_name' : page_name });
- });
+ var section = 'form-elements'
+ var sectionName = 'Form elements'
+ var pageName = 'Example: Radio buttons and checkboxes'
+ res.render('examples/example_radios_checkboxes', { 'section': section, 'section_name': sectionName, 'page_name': pageName })
+ })
// Redirect examples from /patterns/ to /section/example-name-of-example
app.get('/patterns/radios-checkboxes', function (req, res) {
- res.redirect('/form-elements/example-radios-checkboxes');
- });
+ res.redirect('/form-elements/example-radios-checkboxes')
+ })
// Example page: Form elements
app.get('/form-elements/example-form-elements', function (req, res) {
- var section = "form-elements";
- var section_name = "Form elements";
- var page_name = "Example: Form elements";
- res.render('examples/example_form_elements', { 'section': section, 'section_name' : section_name, 'page_name' : page_name });
- });
+ var section = 'form-elements'
+ var sectionName = 'Form elements'
+ var pageName = 'Example: Form elements'
+ res.render('examples/example_form_elements', { 'section': section, 'section_name': sectionName, 'page_name': pageName })
+ })
// Errors and validation
app.get('/errors', function (req, res) {
- var page_name = "Errors and validation";
- res.render('guide_errors', { 'page_name' : page_name });
- });
+ var pageName = 'Errors and validation'
+ res.render('guide_errors', { 'page_name': pageName })
+ })
// Example page: Form validation
app.get('/errors/example-form-validation-single-question-radio', function (req, res) {
- var section = "errors";
- var section_name = "Errors and validation";
- var page_name = "Example: Form validation - single question";
- res.render('examples/example_form_validation_single_question_radio', { 'section': section, 'section_name' : section_name, 'page_name' : page_name });
- });
+ var section = 'errors'
+ var sectionName = 'Errors and validation'
+ var pageName = 'Example: Form validation - single question'
+ res.render('examples/example_form_validation_single_question_radio', { 'section': section, 'section_name': sectionName, 'page_name': pageName })
+ })
app.post('/errors/example-form-validation-single-question-radio', function (req, res) {
- var section = "errors";
- var section_name = "Errors and validation";
- var page_name = "Example: Form validation - single question";
- var personal_details = req.body.personal_details;
- var error = false;
- if (!personal_details) {
- error = true;
+ var section = 'errors'
+ var sectionName = 'Errors and validation'
+ var pageName = 'Example: Form validation - single question'
+ var personalDetails = req.body.personalDetails
+ var error = false
+ if (!personalDetails) {
+ error = true
} else {
- error = false;
+ error = false
}
- res.render('examples/example_form_validation_single_question_radio', { 'section': section, 'section_name' : section_name, 'page_name' : page_name, 'personal_details': personal_details, 'error': error});
- });
+ res.render('examples/example_form_validation_single_question_radio', { 'section': section, 'section_name': sectionName, 'page_name': pageName, 'personal_details': personalDetails, 'error': error })
+ })
// Redirect examples from /examples/ to /section/example-name-of-example
app.get('/examples/form-validation-single-question-radio', function (req, res) {
- res.redirect('/errors/example-form-validation-single-question-radio');
- });
+ res.redirect('/errors/example-form-validation-single-question-radio')
+ })
app.get('/errors/example-form-validation-multiple-questions', function (req, res) {
- var section = "errors";
- var section_name = "Errors and validation";
- var page_name = "Example: Form validation - multiple questions";
- res.render('examples/example_form_validation_multiple_questions', { 'section': section, 'section_name' : section_name, 'page_name' : page_name });
- });
+ var section = 'errors'
+ var sectionName = 'Errors and validation'
+ var pageName = 'Example: Form validation - multiple questions'
+ res.render('examples/example_form_validation_multiple_questions', { 'section': section, 'section_name': sectionName, 'page_name': pageName })
+ })
app.post('/errors/example-form-validation-multiple-questions', function (req, res) {
- var section = "errors";
- var section_name = "Errors and validation";
- var page_name = "Example: Form validation - multiple questions";
- var fullName = req.body.fullName;
- var niNo = req.body.niNo;
- var error = false;
+ var section = 'errors'
+ var sectionName = 'Errors and validation'
+ var pageName = 'Example: Form validation - multiple questions'
+ var fullName = req.body.fullName
+ var niNo = req.body.niNo
+ var error = false
if (!fullName || !niNo) {
- error = true;
+ error = true
} else {
- error = false;
+ error = false
}
- res.render('examples/example_form_validation_multiple_questions', { 'section': section, 'section_name' : section_name, 'page_name' : page_name, 'fullName': fullName, 'niNo': niNo, 'error': error});
- });
+ res.render('examples/example_form_validation_multiple_questions', { 'section': section, 'section_name': sectionName, 'page_name': pageName, 'fullName': fullName, 'niNo': niNo, 'error': error })
+ })
// Redirect examples from /examples/ to /section/example-name-of-example
app.get('/examples/form-validation-multiple-questions', function (req, res) {
- res.redirect('/errors/example-form-validation-multiple-questions');
- });
+ res.redirect('/errors/example-form-validation-multiple-questions')
+ })
// Alpha and beta banners
app.get('/alpha-beta-banners', function (req, res) {
- var page_name = "Alpha and beta banners";
- res.render('guide_alpha_beta', { 'page_name' : page_name });
- });
-
+ var pageName = 'Alpha and beta banners'
+ res.render('guide_alpha_beta', { 'page_name': pageName })
+ })
}
-};
+}
diff --git a/app/views/includes/scripts.html b/app/views/includes/scripts.html
index 434f496f9..da56e7a26 100644
--- a/app/views/includes/scripts.html
+++ b/app/views/includes/scripts.html
@@ -6,5 +6,5 @@
-
+
diff --git a/app/views/snippets/form_error_radio.html b/app/views/snippets/form_error_radio.html
index 72b02affc..f702987d8 100644
--- a/app/views/snippets/form_error_radio.html
+++ b/app/views/snippets/form_error_radio.html
@@ -42,12 +42,12 @@
diff --git a/app/views/snippets/form_error_radio_show_errors.html b/app/views/snippets/form_error_radio_show_errors.html
index a9c7453de..7054488e5 100644
--- a/app/views/snippets/form_error_radio_show_errors.html
+++ b/app/views/snippets/form_error_radio_show_errors.html
@@ -38,12 +38,12 @@
diff --git a/package.json b/package.json
index 32a4871b4..42391ca10 100644
--- a/package.json
+++ b/package.json
@@ -28,10 +28,18 @@
"grunt-sass": "^1.0.0",
"grunt-shell": "^1.3.0",
"node-sass": "^3.2.0",
- "readdir": "0.0.6"
+ "readdir": "0.0.6",
+ "standard": "^7.1.2"
},
- "scripts": {
- "test": "./node_modules/grunt-cli/bin/grunt test"
+ "scripts":{
+ "test": "standard && ./node_modules/grunt-cli/bin/grunt test"
+ },
+ "standard": {
+ "ignore": [
+ "lib",
+ "public/javascripts/vendor/",
+ "tests"
+ ]
},
"bugs": {
"url": "https://github.com/alphagov/govuk_elements/issues"
diff --git a/public/javascripts/application.js b/public/javascripts/application.js
index f4540ac75..d3b7d86f4 100644
--- a/public/javascripts/application.js
+++ b/public/javascripts/application.js
@@ -1,161 +1,142 @@
-function ShowHideContent() {
- var self = this;
+/* global $ */
+/* global jQuery */
+/* global GOVUK */
+function ShowHideContent () {
+ var self = this
- self.escapeElementName = function(str) {
- result = str.replace('[', '\\[').replace(']', '\\]')
- return(result);
- };
+ self.escapeElementName = function (str) {
+ var result = str.replace('[', '\\[').replace(']', '\\]')
+ return (result)
+ }
self.showHideRadioToggledContent = function () {
$(".block-label input[type='radio']").each(function () {
+ var $radio = $(this)
+ var $radioGroupName = $radio.attr('name')
+ var $radioLabel = $radio.parent('label')
- var $radio = $(this);
- var $radioGroupName = $radio.attr('name');
- var $radioLabel = $radio.parent('label');
-
- var dataTarget = $radioLabel.attr('data-target');
+ var dataTarget = $radioLabel.attr('data-target')
// Add ARIA attributes
// If the data-target attribute is defined
if (dataTarget) {
-
// Set aria-controls
- $radio.attr('aria-controls', dataTarget);
+ $radio.attr('aria-controls', dataTarget)
$radio.on('click', function () {
-
// Select radio buttons in the same group
- $radio.closest('form').find(".block-label input[name=" + self.escapeElementName($radioGroupName) + "]").each(function () {
- var $this = $(this);
+ $radio.closest('form').find('.block-label input[name=' + self.escapeElementName($radioGroupName) + ']').each(function () {
+ var $this = $(this)
- var groupDataTarget = $this.parent('label').attr('data-target');
- var $groupDataTarget = $('#' + groupDataTarget);
+ var groupDataTarget = $this.parent('label').attr('data-target')
+ var $groupDataTarget = $('#' + groupDataTarget)
// Hide toggled content
- $groupDataTarget.addClass('js-hidden');
+ $groupDataTarget.addClass('js-hidden')
// Set aria-expanded and aria-hidden for hidden content
- $this.attr('aria-expanded', 'false');
- $groupDataTarget.attr('aria-hidden', 'true');
- });
+ $this.attr('aria-expanded', 'false')
+ $groupDataTarget.attr('aria-hidden', 'true')
+ })
- var $dataTarget = $('#' + dataTarget);
- $dataTarget.removeClass('js-hidden');
+ var $dataTarget = $('#' + dataTarget)
+ $dataTarget.removeClass('js-hidden')
// Set aria-expanded and aria-hidden for clicked radio
- $radio.attr('aria-expanded', 'true');
- $dataTarget.attr('aria-hidden', 'false');
-
- });
-
+ $radio.attr('aria-expanded', 'true')
+ $dataTarget.attr('aria-hidden', 'false')
+ })
} else {
// If the data-target attribute is undefined for a radio button,
// hide visible data-target content for radio buttons in the same group
$radio.on('click', function () {
-
// Select radio buttons in the same group
- $(".block-label input[name=" + self.escapeElementName($radioGroupName) + "]").each(function () {
-
- var groupDataTarget = $(this).parent('label').attr('data-target');
- var $groupDataTarget = $('#' + groupDataTarget);
+ $('.block-label input[name=' + self.escapeElementName($radioGroupName) + ']').each(function () {
+ var groupDataTarget = $(this).parent('label').attr('data-target')
+ var $groupDataTarget = $('#' + groupDataTarget)
// Hide toggled content
- $groupDataTarget.addClass('js-hidden');
+ $groupDataTarget.addClass('js-hidden')
// Set aria-expanded and aria-hidden for hidden content
- $(this).attr('aria-expanded', 'false');
- $groupDataTarget.attr('aria-hidden', 'true');
- });
-
- });
+ $(this).attr('aria-expanded', 'false')
+ $groupDataTarget.attr('aria-hidden', 'true')
+ })
+ })
}
-
- });
+ })
}
self.showHideCheckboxToggledContent = function () {
+ $(".block-label input[type='checkbox']").each(function () {
+ var $checkbox = $(this)
+ var $checkboxLabel = $(this).parent()
- $(".block-label input[type='checkbox']").each(function() {
-
- var $checkbox = $(this);
- var $checkboxLabel = $(this).parent();
-
- var $dataTarget = $checkboxLabel.attr('data-target');
+ var $dataTarget = $checkboxLabel.attr('data-target')
// Add ARIA attributes
// If the data-target attribute is defined
if (typeof $dataTarget !== 'undefined' && $dataTarget !== false) {
-
// Set aria-controls
- $checkbox.attr('aria-controls', $dataTarget);
+ $checkbox.attr('aria-controls', $dataTarget)
// Set aria-expanded and aria-hidden
- $checkbox.attr('aria-expanded', 'false');
- $('#'+$dataTarget).attr('aria-hidden', 'true');
+ $checkbox.attr('aria-expanded', 'false')
+ $('#' + $dataTarget).attr('aria-hidden', 'true')
// For checkboxes revealing hidden content
- $checkbox.on('click', function() {
-
- var state = $(this).attr('aria-expanded') === 'false' ? true : false;
+ $checkbox.on('click', function () {
+ var state = $(this).attr('aria-expanded') === 'false'
// Toggle hidden content
- $('#'+$dataTarget).toggleClass('js-hidden');
+ $('#' + $dataTarget).toggleClass('js-hidden')
// Update aria-expanded and aria-hidden attributes
- $(this).attr('aria-expanded', state);
- $('#'+$dataTarget).attr('aria-hidden', !state);
-
- });
+ $(this).attr('aria-expanded', state)
+ $('#' + $dataTarget).attr('aria-hidden', !state)
+ })
}
-
- });
+ })
}
}
-$(document).ready(function() {
-
+$(document).ready(function () {
// Turn off jQuery animation
- jQuery.fx.off = true;
+ jQuery.fx.off = true
// Use GOV.UK selection-buttons.js to set selected
// and focused states for block labels
- var $blockLabels = $(".block-label input[type='radio'], .block-label input[type='checkbox']");
- new GOVUK.SelectionButtons($blockLabels);
+ var $blockLabels = $(".block-label input[type='radio'], .block-label input[type='checkbox']")
+ new GOVUK.SelectionButtons($blockLabels) // eslint-disable-line
// Use GOV.UK shim-links-with-button-role.js to trigger a link styled to look like a button,
// with role="button" when the space key is pressed.
- GOVUK.shimLinksWithButtonRole.init();
+ GOVUK.shimLinksWithButtonRole.init()
// Details/summary polyfill
// See /javascripts/vendor/details.polyfill.js
// Where .block-label uses the data-target attribute
// to toggle hidden content
- var toggleContent = new ShowHideContent();
- toggleContent.showHideRadioToggledContent();
- toggleContent.showHideCheckboxToggledContent();
-
-});
-
-$(window).load(function() {
+ var toggleContent = new ShowHideContent()
+ toggleContent.showHideRadioToggledContent()
+ toggleContent.showHideCheckboxToggledContent()
+})
+$(window).load(function () {
// Only set focus for the error example pages
- if ($(".js-error-example").length) {
-
+ if ($('.js-error-example').length) {
// If there is an error summary, set focus to the summary
- if ($(".error-summary").length) {
- $(".error-summary").focus();
- $(".error-summary a").click(function(e) {
- e.preventDefault();
- var href = $(this).attr("href");
- $(href).focus();
- });
- }
- // Otherwise, set focus to the field with the error
- else {
- $(".error input:first").focus();
+ if ($('.error-summary').length) {
+ $('.error-summary').focus()
+ $('.error-summary a').click(function (e) {
+ e.preventDefault()
+ var href = $(this).attr('href')
+ $(href).focus()
+ })
+ } else {
+ // Otherwise, set focus to the field with the error
+ $('.error input:first').focus()
}
}
-
-});
-
+})
diff --git a/public/javascripts/vendor/details.polyfill.js b/public/javascripts/govuk/details.polyfill.js
similarity index 67%
rename from public/javascripts/vendor/details.polyfill.js
rename to public/javascripts/govuk/details.polyfill.js
index e0a9c4073..43cba922b 100644
--- a/public/javascripts/vendor/details.polyfill.js
+++ b/public/javascripts/govuk/details.polyfill.js
@@ -6,188 +6,185 @@
// http://www.sitepoint.com/fixing-the-details-element/
-(function () {
- 'use strict';
+;(function () {
+ 'use strict'
- var NATIVE_DETAILS = typeof document.createElement('details').open === 'boolean';
+ var NATIVE_DETAILS = typeof document.createElement('details').open === 'boolean'
// Add event construct for modern browsers or IE
// which fires the callback with a pre-converted target reference
- function addEvent(node, type, callback) {
+ function addEvent (node, type, callback) {
if (node.addEventListener) {
node.addEventListener(type, function (e) {
- callback(e, e.target);
- }, false);
+ callback(e, e.target)
+ }, false)
} else if (node.attachEvent) {
node.attachEvent('on' + type, function (e) {
- callback(e, e.srcElement);
- });
+ callback(e, e.srcElement)
+ })
}
}
// Handle cross-modal click events
- function addClickEvent(node, callback) {
+ function addClickEvent (node, callback) {
// Prevent space(32) from scrolling the page
addEvent(node, 'keypress', function (e, target) {
if (target.nodeName === 'SUMMARY') {
if (e.keyCode === 32) {
if (e.preventDefault) {
- e.preventDefault();
+ e.preventDefault()
} else {
- e.returnValue = false;
+ e.returnValue = false
}
}
}
- });
+ })
// When the key comes up - check if it is enter(13) or space(32)
addEvent(node, 'keyup', function (e, target) {
- if (e.keyCode === 13 || e.keyCode === 32) { callback(e, target); }
- });
+ if (e.keyCode === 13 || e.keyCode === 32) { callback(e, target) }
+ })
addEvent(node, 'mouseup', function (e, target) {
- callback(e, target);
- });
+ callback(e, target)
+ })
}
// Get the nearest ancestor element of a node that matches a given tag name
- function getAncestor(node, match) {
+ function getAncestor (node, match) {
do {
if (!node || node.nodeName.toLowerCase() === match) {
- break;
+ break
}
- } while (node = node.parentNode);
+ node = node.parentNode
+ } while (node)
- return node;
+ return node
}
// Create a started flag so we can prevent the initialisation
// function firing from both DOMContentLoaded and window.onload
- var started = false;
+ var started = false
// Initialisation function
- function addDetailsPolyfill(list) {
-
+ function addDetailsPolyfill (list) {
// If this has already happened, just return
// else set the flag so it doesn't happen again
if (started) {
- return;
+ return
}
- started = true;
+ started = true
// Get the collection of details elements, but if that's empty
// then we don't need to bother with the rest of the scripting
if ((list = document.getElementsByTagName('details')).length === 0) {
- return;
+ return
}
// else iterate through them to apply their initial state
- var n = list.length, i = 0;
+ var n = list.length
+ var i = 0
for (i; i < n; i++) {
- var details = list[i];
+ var details = list[i]
// Save shortcuts to the inner summary and content elements
- details.__summary = details.getElementsByTagName('summary').item(0);
- details.__content = details.getElementsByTagName('div').item(0);
+ details.__summary = details.getElementsByTagName('summary').item(0)
+ details.__content = details.getElementsByTagName('div').item(0)
// If the content doesn't have an ID, assign it one now
// which we'll need for the summary's aria-controls assignment
if (!details.__content.id) {
- details.__content.id = 'details-content-' + i;
+ details.__content.id = 'details-content-' + i
}
// Add ARIA role="group" to details
- details.setAttribute('role', 'group');
+ details.setAttribute('role', 'group')
// Add role=button to summary
- details.__summary.setAttribute('role', 'button');
+ details.__summary.setAttribute('role', 'button')
// Add aria-controls
- details.__summary.setAttribute('aria-controls', details.__content.id);
+ details.__summary.setAttribute('aria-controls', details.__content.id)
// Set tabIndex so the summary is keyboard accessible for non-native elements
// http://www.saliences.com/browserBugs/tabIndex.html
if (!NATIVE_DETAILS) {
- details.__summary.tabIndex = 0;
+ details.__summary.tabIndex = 0
}
// Detect initial open state
- var openAttr = details.getAttribute('open') !== null;
+ var openAttr = details.getAttribute('open') !== null
if (openAttr === true) {
- details.__summary.setAttribute('aria-expanded', 'true');
- details.__content.setAttribute('aria-hidden', 'false');
+ details.__summary.setAttribute('aria-expanded', 'true')
+ details.__content.setAttribute('aria-hidden', 'false')
} else {
- details.__summary.setAttribute('aria-expanded', 'false');
- details.__content.setAttribute('aria-hidden', 'true');
+ details.__summary.setAttribute('aria-expanded', 'false')
+ details.__content.setAttribute('aria-hidden', 'true')
if (!NATIVE_DETAILS) {
- details.__content.style.display = 'none';
+ details.__content.style.display = 'none'
}
}
// Create a circular reference from the summary back to its
// parent details element, for convenience in the click handler
- details.__summary.__details = details;
+ details.__summary.__details = details
// If this is not a native implementation, create an arrow
// inside the summary
if (!NATIVE_DETAILS) {
-
- var twisty = document.createElement('i');
+ var twisty = document.createElement('i')
if (openAttr === true) {
- twisty.className = 'arrow arrow-open';
- twisty.appendChild(document.createTextNode('\u25bc'));
+ twisty.className = 'arrow arrow-open'
+ twisty.appendChild(document.createTextNode('\u25bc'))
} else {
- twisty.className = 'arrow arrow-closed';
- twisty.appendChild(document.createTextNode('\u25ba'));
+ twisty.className = 'arrow arrow-closed'
+ twisty.appendChild(document.createTextNode('\u25ba'))
}
- details.__summary.__twisty = details.__summary.insertBefore(twisty, details.__summary.firstChild);
- details.__summary.__twisty.setAttribute('aria-hidden', 'true');
-
+ details.__summary.__twisty = details.__summary.insertBefore(twisty, details.__summary.firstChild)
+ details.__summary.__twisty.setAttribute('aria-hidden', 'true')
}
}
// Define a statechange function that updates aria-expanded and style.display
// Also update the arrow position
- function statechange(summary) {
+ function statechange (summary) {
+ var expanded = summary.__details.__summary.getAttribute('aria-expanded') === 'true'
+ var hidden = summary.__details.__content.getAttribute('aria-hidden') === 'true'
- var expanded = summary.__details.__summary.getAttribute('aria-expanded') === 'true';
- var hidden = summary.__details.__content.getAttribute('aria-hidden') === 'true';
-
- summary.__details.__summary.setAttribute('aria-expanded', (expanded ? 'false' : 'true'));
- summary.__details.__content.setAttribute('aria-hidden', (hidden ? 'false' : 'true'));
+ summary.__details.__summary.setAttribute('aria-expanded', (expanded ? 'false' : 'true'))
+ summary.__details.__content.setAttribute('aria-hidden', (hidden ? 'false' : 'true'))
if (!NATIVE_DETAILS) {
- summary.__details.__content.style.display = (expanded ? 'none' : '');
+ summary.__details.__content.style.display = (expanded ? 'none' : '')
- var hasOpenAttr = summary.__details.getAttribute('open') !== null;
+ var hasOpenAttr = summary.__details.getAttribute('open') !== null
if (!hasOpenAttr) {
- summary.__details.setAttribute('open', 'open');
+ summary.__details.setAttribute('open', 'open')
} else {
- summary.__details.removeAttribute('open');
+ summary.__details.removeAttribute('open')
}
}
if (summary.__twisty) {
- summary.__twisty.firstChild.nodeValue = (expanded ? '\u25ba' : '\u25bc');
- summary.__twisty.setAttribute('class', (expanded ? 'arrow arrow-closed' : 'arrow arrow-open'));
+ summary.__twisty.firstChild.nodeValue = (expanded ? '\u25ba' : '\u25bc')
+ summary.__twisty.setAttribute('class', (expanded ? 'arrow arrow-closed' : 'arrow arrow-open'))
}
- return true;
+ return true
}
// Bind a click event to handle summary elements
- addClickEvent(document, function(e, summary) {
+ addClickEvent(document, function (e, summary) {
if (!(summary = getAncestor(summary, 'summary'))) {
- return true;
+ return true
}
- return statechange(summary);
- });
+ return statechange(summary)
+ })
}
// Bind two load events for modern and older browsers
// If the first one fires it will set a flag to block the second one
// but if it's not supported then the second one will fire
- addEvent(document, 'DOMContentLoaded', addDetailsPolyfill);
- addEvent(window, 'load', addDetailsPolyfill);
-
-})();
+ addEvent(document, 'DOMContentLoaded', addDetailsPolyfill)
+ addEvent(window, 'load', addDetailsPolyfill)
+})()
diff --git a/public/javascripts/redirect.js b/public/javascripts/redirect.js
index 24507d621..952b2d83e 100644
--- a/public/javascripts/redirect.js
+++ b/public/javascripts/redirect.js
@@ -1,10 +1,9 @@
// Redirect all the existing URLs with fragment identifiers in to the new section
-(function () {
- 'use strict';
-
+;(function () {
+ 'use strict'
var getNewRouteFor = function (fragment) {
- var baseURL = window.location.protocol + '//' +window.location.host;
+ var baseURL = window.location.protocol + '//' + window.location.host
var newRoutes = {
'#guide-layout': '/layout',
'#layout-spacing': '/layout/#layout-spacing',
@@ -50,25 +49,24 @@
'#guide-alpha-beta': '/alpha-beta-banners',
'#guide-alpha-beta-govuk': '/alpha-beta-banners/#alpha-banner',
'#alpha-beta-creating-banners': '/alpha-beta-banners/#creating-phase-banners'
- };
+ }
if (newRoutes[fragment] !== 'undefined') {
- return baseURL + newRoutes[fragment];
+ return baseURL + newRoutes[fragment]
}
- return false;
- };
+ return false
+ }
- var fragment = window.location.hash;
- var newRoute;
+ var fragment = window.location.hash
+ var newRoute
if (fragment === '') {
- return;
+ return
}
- newRoute = getNewRouteFor(fragment);
+ newRoute = getNewRouteFor(fragment)
if (newRoute) {
- window.location.href = newRoute;
+ window.location.href = newRoute
}
-
-}());
+}())
diff --git a/server.js b/server.js
index 28694dc6e..2925de5c5 100755
--- a/server.js
+++ b/server.js
@@ -1,53 +1,53 @@
-var bodyParser = require('body-parser'),
- config = require(__dirname + '/app/config.js'),
- express = require('express'),
- nunjucks = require('express-nunjucks'),
- path = require('path'),
- routes = require(__dirname + '/app/routes.js'),
- app = express(),
- port = (process.env.PORT || 3000);
+var path = require('path')
+var express = require('express')
+var nunjucks = require('express-nunjucks')
+var routes = require('./app/routes.js')
+var app = express()
+var bodyParser = require('body-parser')
+var config = require('./app/config.js')
+var port = (process.env.PORT || 3000)
// Application settings
-app.set('view engine', 'html');
-app.set('views', [__dirname + '/app/views', __dirname + '/lib/']);
+app.set('view engine', 'html')
+app.set('views', [path.join(__dirname, '/app/views'), path.join(__dirname, '/lib/')])
nunjucks.setup({
autoescape: true,
watch: true,
noCache: true
-}, app);
+}, app)
// Middleware to serve static assets
-app.use('/public', express.static(__dirname + '/public'));
-app.use('/public', express.static(__dirname + '/govuk_modules/public'));
-app.use('/public', express.static(__dirname + '/govuk_modules/govuk_template/assets'));
-app.use('/public', express.static(__dirname + '/govuk_modules/govuk_frontend_toolkit'));
+app.use('/public', express.static(path.join(__dirname, '/public')))
+app.use('/public', express.static(path.join(__dirname, '/govuk_modules/public')))
+app.use('/public', express.static(path.join(__dirname, '/govuk_modules/govuk_template/assets')))
+app.use('/public', express.static(path.join(__dirname, '/govuk_modules/govuk_frontend_toolkit')))
// Support for parsing data in POSTs
-app.use(bodyParser.json());
+app.use(bodyParser.json())
app.use(bodyParser.urlencoded({
- extended: true
-}));
+ extended: true
+}))
// send assetPath to all views
app.use(function (req, res, next) {
- res.locals.asset_path="/public/";
- next();
-});
+ res.locals.asset_path = '/public/'
+ next()
+})
// Add variables that are available in all views
app.use(function (req, res, next) {
- res.locals.cookieText=config.cookieText;
- next();
-});
+ res.locals.cookieText = config.cookieText
+ next()
+})
// routes (found in routes.js)
-routes.bind(app, '/public/');
+routes.bind(app, '/public/')
// start the app
-app.listen(port);
-console.log('');
-console.log('Listening on port ' + port);
-console.log('');
+app.listen(port)
+console.log('')
+console.log('Listening on port ' + port)
+console.log('')
diff --git a/start.js b/start.js
index 0a45aa8bb..1a136488f 100755
--- a/start.js
+++ b/start.js
@@ -1,15 +1,19 @@
-var fs = require('fs'),
- pidFile = __dirname + '/.start.pid',
- fileOptions = { encoding : 'utf-8' };
+var path = require('path')
+var fs = require('fs')
+var pidFile = path.join(__dirname, '/.start.pid')
+var fileOptions = { encoding: 'utf-8' }
// start grunt
+var gruntfile = path.join(__dirname, '/Gruntfile.js')
+require('./node_modules/grunt/lib/grunt.js').cli({
+ 'gruntfile': gruntfile
+})
-require(__dirname + '/node_modules/grunt/lib/grunt.js').cli();
-fs.writeFileSync(pidFile, process.pid, fileOptions);
-process.on('SIGINT', function() {
- var pid = fs.readFileSync(pidFile, fileOptions);
+fs.writeFileSync(pidFile, process.pid, fileOptions)
+process.on('SIGINT', function () {
+ var pid = fs.readFileSync(pidFile, fileOptions)
- fs.unlink(pidFile);
- process.kill(pid, 'SIGTERM');
- process.exit();
+ fs.unlink(pidFile)
+ process.kill(pid, 'SIGTERM')
+ process.exit()
})