govuk_frontend_toolkit 4.4.0 → 4.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7f7e29e171f3a719dcc43d1470a99ded731cc407
4
+ data.tar.gz: 0ef85b576091648e8779abc142ac523d358a6660
5
+ SHA512:
6
+ metadata.gz: 6b1d7075816ead4ec7dcdee8573a329a523c4e6d7ff8579e2e338f6c9014c98927a33946744e8cd431b93381a402ccf765f26b72cee16b6ff2465d06ffd73858
7
+ data.tar.gz: d22ceb97296f12f9ab556e507403a132a61d1f9af7b030a644a6851c8818e8fdbff25277c4adf383037f51c72b22ead629ec2bb6df67e2553a5bfbda37f7b2ec
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.2
@@ -0,0 +1 @@
1
+ 2.2
@@ -1,7 +1,5 @@
1
1
  language: node_js
2
2
  node_js:
3
3
  - "0.10"
4
- rvm:
5
- - 2.1.0
6
4
  before_install:
7
5
  - bundle install
@@ -1,3 +1,7 @@
1
+ # 4.5.0
2
+
3
+ - Find and auto-start JavaScript modules from markup: `data-module="module-name"`(PR #227)
4
+
1
5
  # 4.4.0
2
6
 
3
7
  - Add helpers partial for functions
@@ -29,7 +29,7 @@ module.exports = function(grunt) {
29
29
  jasmine: {
30
30
  javascripts: {
31
31
  src: [
32
- 'node_modules/jquery-browser/lib/jquery.js',
32
+ 'node_modules/jquery/dist/jquery.js',
33
33
  'javascripts/govuk/analytics/google-analytics-universal-tracker.js',
34
34
  'javascripts/govuk/analytics/analytics.js',
35
35
  'javascripts/**/*.js'
data/app/assets/README.md CHANGED
@@ -115,6 +115,7 @@ In production:
115
115
  * [Phase banner](/docs/mixins.md#-phase-banner)
116
116
  * [Phase tags](/docs/mixins.md#-phase-tags)
117
117
  * [JavaScript](/docs/javascript.md)
118
+ * [Modules](/docs/javascript.md#modules)
118
119
  * [Media player](/docs/javascript.md#media-player)
119
120
  * [Multivariate test framework](/docs/javascript.md#multivariate-test-framework)
120
121
  * [Primary links](/docs/javascript.md#primary-links)
@@ -1 +1 @@
1
- 4.4.0
1
+ 4.5.0
@@ -5,6 +5,115 @@ page. It can be included with the asset_pipeline by adding the line:
5
5
 
6
6
  //=require govuk_toolkit
7
7
 
8
+ ## Modules
9
+
10
+ The toolkit comes with a module pattern that makes it easy to write re-usable modular components, without having to worry about where and when the module should be instantiated.
11
+
12
+ ### Usage
13
+
14
+ Javascript modules can be specified in markup using `data-` attributes:
15
+
16
+ ```html
17
+ <div data-module="some-module">
18
+ <strong>Some other markup inside the module</strong>
19
+ </div>
20
+ ```
21
+
22
+ Modules can be found and started by including `govuk/modules.js` and running:
23
+
24
+ ```javascript
25
+ $(document).ready(function(){
26
+ GOVUK.modules.start();
27
+ });
28
+ ```
29
+
30
+ This will attempt to find and start all modules in the page. For the example above it will look for a module at `GOVUK.Modules.SomeModule`. Note the value of the data attribute has been converted to _PascalCase_.
31
+
32
+ The module will be instantiated and then its `start` method called. The HTML element with the `data-module` attribute is passed as the first argument to the module. This limits modules to acting only within their containing elements.
33
+
34
+ ```javascript
35
+ module = new GOVUK.Modules[type]();
36
+ module.start(element);
37
+ ```
38
+
39
+ Running `GOVUK.modules.start()` multiple times will have no additional affect. When a module is started a flag is set on the element using the data attribute `module-started`. `data-module-started` is a reserved attribute. It can however be called with an element as the first argument, to allow modules to be started in dynamically loaded content:
40
+
41
+ ```javascript
42
+ var container = $('.dynamic-content');
43
+ GOVUK.modules.start(container);
44
+ ```
45
+
46
+ ### Module structure
47
+
48
+ A module must add its constructor to `GOVUK.Modules` and it must have a `start` method.
49
+ The simplest module looks like:
50
+
51
+ ```javascript
52
+ (function(Modules) {
53
+ "use strict";
54
+ Modules.SomeModule = function() {
55
+ this.start = function(element) {
56
+ // module code
57
+ }
58
+ };
59
+ })(window.GOVUK.Modules);
60
+ ```
61
+
62
+ ### Writing modules
63
+
64
+ Whilst this isn’t prescriptive, it helps if modules look and behave in a similar manner.
65
+
66
+ #### Use `js-` prefixed classes for interaction hooks
67
+
68
+ Make it clear where a javascript module will be applying behaviour:
69
+
70
+ ```html
71
+ <div data-module="toggle-thing">
72
+ <a href="/" class="js-toggle">Toggle</a>
73
+ <div class="js-toggle-target">Target</div>
74
+ </div>
75
+ ```
76
+
77
+ #### Declare event listeners at the start
78
+
79
+ Beginning with a set of event listeners clearly indicates the module’s intentions.
80
+
81
+ ```js
82
+ this.start = function(element) {
83
+ element.on('click', '.js-toggle', toggle);
84
+ element.on('click', '.js-cancel', cancel);
85
+ }
86
+ ```
87
+
88
+ Where possible, assign listeners to the module element to minimise the number of listeners and to allow for flexible markup:
89
+
90
+ ```html
91
+ <div data-module="toggle-thing">
92
+ <a href="/" class="js-toggle">This toggles</a>
93
+ <div class="js-toggle-target">
94
+ <p>Some content</p>
95
+ <a href="/" class="js-toggle">This also toggles</a>
96
+ </div>
97
+ </div>
98
+ ```
99
+
100
+ #### Use data-attributes for configuration
101
+
102
+ Keep modules flexible by moving configuration to data attributes on the module’s element:
103
+
104
+ ```html
105
+ <div
106
+ data-module="html-stream"
107
+ data-url="/some/endpoint"
108
+ data-refresh-ms="5000">
109
+ <!-- updates with content from end point -->
110
+ </div>
111
+ ```
112
+
113
+ #### Include Jasmine specs
114
+
115
+ Modules should have their own tests, whether they’re being included with the toolkit or are app specific.
116
+
8
117
  ## Media player
9
118
 
10
119
  There is a forked version of the Nomensa video player included and custom
@@ -106,7 +215,7 @@ This code requires analytics to be loaded in order to run; static is the app tha
106
215
  6. Check that it works: launch the app, open the page of your app, and check that there is a cookie with the name you had picked in your experiment. You can delete the cookie and refresh the page to check whether you can be assigned to another cohort. Then in your browser console, go to the Networks tab and search for xid and xvar. The values should correspond to your contentExperimentId and the cohort your cookie indicates you were assigned to.
107
216
 
108
217
  7. If it works, in Google Universal Analytics, click on "Next Step" and then "Start Experiment". You can ignore the error messages relative to Experiment Code Validation as they don't concern us in our setup.
109
-
218
+
110
219
  ```js
111
220
  var test = new GOVUK.MultivariateTest({
112
221
  name: 'car_tax_button_text',
@@ -0,0 +1,56 @@
1
+ (function($, root) {
2
+ "use strict";
3
+ root.GOVUK = root.GOVUK || {};
4
+ GOVUK.Modules = GOVUK.Modules || {};
5
+
6
+ GOVUK.modules = {
7
+ find: function(container) {
8
+ var modules,
9
+ moduleSelector = '[data-module]',
10
+ container = container || $('body');
11
+
12
+ modules = container.find(moduleSelector);
13
+
14
+ // Container could be a module too
15
+ if (container.is(moduleSelector)) {
16
+ modules = modules.add(container);
17
+ }
18
+
19
+ return modules;
20
+ },
21
+
22
+ start: function(container) {
23
+ var modules = this.find(container);
24
+
25
+ for (var i = 0, l = modules.length; i < l; i++) {
26
+ var module,
27
+ element = $(modules[i]),
28
+ type = camelCaseAndCapitalise(element.data('module')),
29
+ started = element.data('module-started');
30
+
31
+ if (typeof GOVUK.Modules[type] === "function" && !started) {
32
+ module = new GOVUK.Modules[type]();
33
+ module.start(element);
34
+ element.data('module-started', true);
35
+ }
36
+ }
37
+
38
+ // eg selectable-table to SelectableTable
39
+ function camelCaseAndCapitalise(string) {
40
+ return capitaliseFirstLetter(camelCase(string));
41
+ }
42
+
43
+ // http://stackoverflow.com/questions/6660977/convert-hyphens-to-camel-case-camelcase
44
+ function camelCase(string) {
45
+ return string.replace(/-([a-z])/g, function (g) {
46
+ return g[1].toUpperCase();
47
+ });
48
+ }
49
+
50
+ // http://stackoverflow.com/questions/1026069/capitalize-the-first-letter-of-string-in-javascript
51
+ function capitaliseFirstLetter(string) {
52
+ return string.charAt(0).toUpperCase() + string.slice(1);
53
+ }
54
+ }
55
+ }
56
+ })(jQuery, window);
@@ -0,0 +1,26 @@
1
+ (function(Modules) {
2
+ "use strict";
3
+
4
+ Modules.AutoTrackEvent = function() {
5
+ this.start = function(element) {
6
+ var options = {nonInteraction: 1}, // automatic events shouldn't affect bounce rate
7
+ category = element.data('track-category'),
8
+ action = element.data('track-action'),
9
+ label = element.data('track-label'),
10
+ value = element.data('track-value');
11
+
12
+ if (typeof label === "string") {
13
+ options.label = label;
14
+ }
15
+
16
+ if (value || value === 0) {
17
+ options.value = value;
18
+ }
19
+
20
+ if (GOVUK.analytics && GOVUK.analytics.trackEvent) {
21
+ GOVUK.analytics.trackEvent(category, action, options);
22
+ }
23
+ }
24
+ };
25
+
26
+ })(window.GOVUK.Modules);
@@ -9,7 +9,7 @@
9
9
  "grunt-contrib-jasmine": "~0.8.2",
10
10
  "grunt-contrib-sass": "0.7.4",
11
11
  "grunt-scss-lint": "0.3.4",
12
- "jquery-browser": "~1.7.2-3"
12
+ "jquery": "~1.11.3"
13
13
  },
14
14
  "scripts": {
15
15
  "test": "node_modules/.bin/grunt test"
@@ -1,7 +1,9 @@
1
- // files are loaded from the /spec/support folder so paths are relative to that
1
+ // Paths are relative to the /spec/support folder
2
2
  var manifest = {
3
3
  support : [
4
- '../../node_modules/jquery-browser/lib/jquery.js',
4
+ '../../node_modules/jquery/dist/jquery.js',
5
+ '../../javascripts/govuk/modules.js',
6
+ '../../javascripts/govuk/modules/auto-track-event.js',
5
7
  '../../javascripts/govuk/multivariate-test.js',
6
8
  '../../javascripts/govuk/primary-links.js',
7
9
  '../../javascripts/govuk/stick-at-top-when-scrolling.js',
@@ -14,6 +16,8 @@ var manifest = {
14
16
  '../../javascripts/govuk/analytics/download-link-tracker.js'
15
17
  ],
16
18
  test : [
19
+ '../unit/ModulesSpec.js',
20
+ '../unit/Modules/AutoTrackEventSpec.js',
17
21
  '../unit/MultivariateTestSpec.js',
18
22
  '../unit/PrimaryLinksSpec.js',
19
23
  '../unit/StickAtTopWhenScrollingSpec.js',
@@ -0,0 +1,89 @@
1
+ describe('GOVUK Modules', function() {
2
+ "use strict";
3
+ var GOVUK = window.GOVUK;
4
+
5
+ it('finds modules', function() {
6
+ var module = $('<div data-module="a-module"></div>');
7
+ $('body').append(module);
8
+
9
+ expect(GOVUK.modules.find().length).toBe(1);
10
+ expect(GOVUK.modules.find().eq(0).is('[data-module="a-module"]')).toBe(true);
11
+ module.remove();
12
+ });
13
+
14
+ it('finds modules in a container', function() {
15
+ var module = $('<div data-module="a-module"></div>'),
16
+ container = $('<div></div>').append(module);
17
+
18
+ expect(GOVUK.modules.find(container).length).toBe(1);
19
+ expect(GOVUK.modules.find(container).eq(0).data('module')).toBe('a-module');
20
+ });
21
+
22
+ it('finds modules that are a container', function() {
23
+ var module = $('<div data-module="a-module"></div>'),
24
+ container = $('<div data-module="container-module"></div>').append(module);
25
+
26
+ expect(GOVUK.modules.find(container).length).toBe(2);
27
+ expect(GOVUK.modules.find(container).eq(0).data('module')).toBe('container-module');
28
+ expect(GOVUK.modules.find(container).eq(1).data('module')).toBe('a-module');
29
+ });
30
+
31
+ describe('when a module exists', function() {
32
+ var callback;
33
+
34
+ beforeEach(function() {
35
+ callback = jasmine.createSpy();
36
+ GOVUK.Modules.TestAlertModule = function() {
37
+ var that = this;
38
+ that.start = function(element) {
39
+ callback(element);
40
+ }
41
+ };
42
+ });
43
+
44
+ afterEach(function() {
45
+ delete GOVUK.Modules.TestAlertModule;
46
+ });
47
+
48
+ it('starts modules within a container', function() {
49
+ var module = $('<div data-module="test-alert-module"></div>'),
50
+ container = $('<div></div>').append(module);
51
+
52
+ GOVUK.modules.start(container);
53
+ expect(callback).toHaveBeenCalled();
54
+ });
55
+
56
+ it('does not start modules that are already started', function() {
57
+ var module = $('<div data-module="test-alert-module"></div>'),
58
+ container = $('<div></div>').append(module);
59
+
60
+ GOVUK.modules.start(module);
61
+ GOVUK.modules.start(module);
62
+ expect(callback.calls.count()).toBe(1);
63
+ });
64
+
65
+ it('passes the HTML element to the module\'s start method', function() {
66
+ var module = $('<div data-module="test-alert-module"></div>'),
67
+ container = $('<h1></h1>').append(module);
68
+
69
+ GOVUK.modules.start(container);
70
+
71
+ var args = callback.calls.argsFor(0);
72
+ expect(args[0].is('div[data-module="test-alert-module"]')).toBe(true);
73
+ });
74
+
75
+ it('starts all modules that are on the page', function() {
76
+ var modules = $(
77
+ '<div data-module="test-alert-module"></div>\
78
+ <strong data-module="test-alert-module"></strong>\
79
+ <span data-module="test-alert-module"></span>'
80
+ );
81
+
82
+ $('body').append(modules);
83
+ GOVUK.modules.start();
84
+ expect(callback.calls.count()).toBe(3);
85
+
86
+ modules.remove();
87
+ });
88
+ });
89
+ });
@@ -61,13 +61,13 @@ describe("selection-buttons", function () {
61
61
  });
62
62
 
63
63
  it("Should mark checked radios with the selected class", function () {
64
- $radioButtons.eq(0).attr('checked', true);
64
+ $radioButtons.eq(0).prop('checked', true);
65
65
  buttonsInstance = new GOVUK.SelectionButtons($radioButtons);
66
66
  expect($radioLabels.eq(0).hasClass('selected')).toBe(true);
67
67
  });
68
68
 
69
69
  it("Should mark checked radios with the custom selected class if given", function () {
70
- $radioButtons.eq(0).attr('checked', true);
70
+ $radioButtons.eq(0).prop('checked', true);
71
71
  buttonsInstance = new GOVUK.SelectionButtons($radioButtons, { 'selectedClass' : 'selectable-selected' });
72
72
  expect($radioLabels.eq(0).hasClass('selectable-selected')).toBe(true);
73
73
  });
@@ -108,18 +108,14 @@ describe("selection-buttons", function () {
108
108
  describe("If one of those radios is clicked", function () {
109
109
  it("Should mark that radio with the selected class", function () {
110
110
  buttonsInstance = new GOVUK.SelectionButtons($radioButtons);
111
- $radioButtons.eq(0)
112
- .attr('checked', true)
113
- .trigger('click');
111
+ $radioButtons.eq(0).trigger('click');
114
112
  expect($radioLabels.eq(0).hasClass('selected')).toBe(true);
115
113
  });
116
114
 
117
115
  it("Should remove the selected class from all other radios", function () {
118
116
  buttonsInstance = new GOVUK.SelectionButtons($radioButtons);
119
117
  $radioLabels.eq(1).addClass('selected');
120
- $radioButtons.eq(0)
121
- .attr('checked', true)
122
- .trigger('click');
118
+ $radioButtons.eq(0).trigger('click');
123
119
  expect($radioLabels.eq(2).hasClass('selected')).toBe(false);
124
120
  });
125
121
  });
@@ -135,21 +131,21 @@ describe("selection-buttons", function () {
135
131
  });
136
132
 
137
133
  it("Should mark checked checkboxes with the selected class", function () {
138
- $checkboxButtons.eq(0).attr('checked', true);
134
+ $checkboxButtons.eq(0).prop('checked', true);
139
135
  buttonsInstance = new GOVUK.SelectionButtons($checkboxButtons);
140
136
  expect($checkboxLabels.eq(0).hasClass('selected')).toBe(true);
141
137
  });
142
138
 
143
139
  it("Should mark all checked checkboxes with the selected class if there are more than one", function () {
144
- $checkboxButtons.eq(0).attr('checked', true);
145
- $checkboxButtons.eq(1).attr('checked', true);
140
+ $checkboxButtons.eq(0).prop('checked', true);
141
+ $checkboxButtons.eq(1).prop('checked', true);
146
142
  buttonsInstance = new GOVUK.SelectionButtons($checkboxButtons);
147
143
  expect($checkboxLabels.eq(0).hasClass('selected')).toBe(true);
148
144
  expect($checkboxLabels.eq(1).hasClass('selected')).toBe(true);
149
145
  });
150
146
 
151
147
  it("Should mark checked checkboxes with the custom selected class if given", function () {
152
- $checkboxButtons.eq(0).attr('checked', true);
148
+ $checkboxButtons.eq(0).prop('checked', true);
153
149
  buttonsInstance = new GOVUK.SelectionButtons($checkboxButtons, { 'selectedClass' : 'selectable-selected' });
154
150
  expect($checkboxLabels.eq(0).hasClass('selectable-selected')).toBe(true);
155
151
  });
@@ -190,17 +186,13 @@ describe("selection-buttons", function () {
190
186
  describe("If one of those checkboxes is clicked", function () {
191
187
  it("Should add the selected class to that checkbox", function () {
192
188
  buttonsInstance = new GOVUK.SelectionButtons($checkboxButtons);
193
- $checkboxButtons.eq(0)
194
- .attr('checked', true)
195
- .trigger('click');
189
+ $checkboxButtons.eq(0).trigger('click');
196
190
  expect($checkboxLabels.eq(0).hasClass('selected')).toBe(true);
197
191
  });
198
192
 
199
193
  it("Should add the selected class to that checkbox", function () {
200
194
  buttonsInstance = new GOVUK.SelectionButtons($checkboxButtons, { 'selectedClass' : 'selectable-selected' });
201
- $checkboxButtons.eq(0)
202
- .attr('checked', true)
203
- .trigger('click');
195
+ $checkboxButtons.eq(0).trigger('click');
204
196
  expect($checkboxLabels.eq(0).hasClass('selectable-selected')).toBe(true);
205
197
  });
206
198
  });
@@ -225,8 +217,8 @@ describe("selection-buttons", function () {
225
217
  });
226
218
 
227
219
  it("Should mark checked checkboxes or radios with the selected class", function () {
228
- $mixedButtons.eq(0).attr('checked', true);
229
- $mixedButtons.eq(3).attr('checked', true);
220
+ $mixedButtons.eq(0).prop('checked', true);
221
+ $mixedButtons.eq(3).prop('checked', true);
230
222
 
231
223
  buttonsInstance = new GOVUK.SelectionButtons($mixedButtons);
232
224
  expect($checkboxLabels.eq(0).hasClass('selected')).toBe(true);
@@ -234,8 +226,8 @@ describe("selection-buttons", function () {
234
226
  });
235
227
 
236
228
  it("Should mark checked checkboxes or radios with the custom selected class if given", function () {
237
- $mixedButtons.eq(0).attr('checked', true);
238
- $mixedButtons.eq(3).attr('checked', true);
229
+ $mixedButtons.eq(0).prop('checked', true);
230
+ $mixedButtons.eq(3).prop('checked', true);
239
231
 
240
232
  buttonsInstance = new GOVUK.SelectionButtons($mixedButtons, { 'selectedClass' : 'selectable-selected' });
241
233
  expect($checkboxLabels.eq(0).hasClass('selectable-selected')).toBe(true);
@@ -278,17 +270,13 @@ describe("selection-buttons", function () {
278
270
  describe("If one of those checkboxes is clicked", function () {
279
271
  it("Should add the selected class to that checkbox", function () {
280
272
  buttonsInstance = new GOVUK.SelectionButtons($mixedButtons);
281
- $checkboxButtons.eq(0)
282
- .attr('checked', true)
283
- .trigger('click');
273
+ $checkboxButtons.eq(0).trigger('click');
284
274
  expect($checkboxLabels.eq(0).hasClass('selected')).toBe(true);
285
275
  });
286
276
 
287
277
  it("Should add the selected class to that checkbox", function () {
288
278
  buttonsInstance = new GOVUK.SelectionButtons($mixedButtons, { 'selectedClass' : 'selectable-selected' });
289
- $checkboxButtons.eq(0)
290
- .attr('checked', true)
291
- .trigger('click');
279
+ $checkboxButtons.eq(0).trigger('click');
292
280
  expect($checkboxLabels.eq(0).hasClass('selectable-selected')).toBe(true);
293
281
  });
294
282
  });
@@ -328,18 +316,14 @@ describe("selection-buttons", function () {
328
316
  describe("If a radio in the set is clicked", function () {
329
317
  it("Should mark that radio with the selected class", function () {
330
318
  buttonsInstance = new GOVUK.SelectionButtons($mixedButtons);
331
- $radioButtons.eq(0)
332
- .attr('checked', true)
333
- .trigger('click');
319
+ $radioButtons.eq(0).trigger('click');
334
320
  expect($radioLabels.eq(0).hasClass('selected')).toBe(true);
335
321
  });
336
322
 
337
323
  it("Should remove the selected class from all other radios", function () {
338
324
  buttonsInstance = new GOVUK.SelectionButtons($mixedButtons);
339
325
  $radioLabels.eq(1).addClass('selected');
340
- $radioButtons.eq(0)
341
- .attr('checked', true)
342
- .trigger('click');
326
+ $radioButtons.eq(0).trigger('click');
343
327
  expect($radioLabels.eq(2).hasClass('selected')).toBe(false);
344
328
  });
345
329
  });
@@ -361,13 +345,13 @@ describe("selection-buttons", function () {
361
345
  });
362
346
 
363
347
  it("Should mark checked radios with the selected class", function () {
364
- $radioButtons.eq(0).attr('checked', true);
348
+ $radioButtons.eq(0).prop('checked', true);
365
349
  buttonsInstance = new GOVUK.SelectionButtons("label.selectable input[type='radio']");
366
350
  expect($radioLabels.eq(0).hasClass('selected')).toBe(true);
367
351
  });
368
352
 
369
353
  it("Should mark checked radios with the custom selected class if given", function () {
370
- $radioButtons.eq(0).attr('checked', true);
354
+ $radioButtons.eq(0).prop('checked', true);
371
355
  buttonsInstance = new GOVUK.SelectionButtons("label.selectable input[type='radio']", { 'selectedClass' : 'selectable-selected' });
372
356
  expect($radioLabels.eq(0).hasClass('selectable-selected')).toBe(true);
373
357
  });
@@ -408,18 +392,14 @@ describe("selection-buttons", function () {
408
392
  describe("If one of those radios is clicked", function () {
409
393
  it("Should mark that radio with the selected class", function () {
410
394
  buttonsInstance = new GOVUK.SelectionButtons("label.selectable input[type='radio']");
411
- $radioButtons.eq(0)
412
- .attr('checked', true)
413
- .trigger('click');
395
+ $radioButtons.eq(0).trigger('click');
414
396
  expect($radioLabels.eq(0).hasClass('selected')).toBe(true);
415
397
  });
416
398
 
417
399
  it("Should remove the selected class from all other radios", function () {
418
400
  buttonsInstance = new GOVUK.SelectionButtons("label.selectable input[type='radio']");
419
401
  $radioLabels.eq(1).addClass('selected');
420
- $radioButtons.eq(0)
421
- .attr('checked', true)
422
- .trigger('click');
402
+ $radioButtons.eq(0).trigger('click');
423
403
  expect($radioLabels.eq(2).hasClass('selected')).toBe(false);
424
404
  });
425
405
  });
@@ -439,21 +419,21 @@ describe("selection-buttons", function () {
439
419
  });
440
420
 
441
421
  it("Should mark checked checkboxes with the selected class", function () {
442
- $checkboxButtons.eq(0).attr('checked', true);
422
+ $checkboxButtons.eq(0).prop('checked', true);
443
423
  buttonsInstance = new GOVUK.SelectionButtons("label.selectable input[type='checkbox']");
444
424
  expect($checkboxLabels.eq(0).hasClass('selected')).toBe(true);
445
425
  });
446
426
 
447
427
  it("Should mark all checked checkboxes with the selected class if there are more than one", function () {
448
- $checkboxButtons.eq(0).attr('checked', true);
449
- $checkboxButtons.eq(1).attr('checked', true);
428
+ $checkboxButtons.eq(0).prop('checked', true);
429
+ $checkboxButtons.eq(1).prop('checked', true);
450
430
  buttonsInstance = new GOVUK.SelectionButtons("label.selectable input[type='checkbox']");
451
431
  expect($checkboxLabels.eq(0).hasClass('selected')).toBe(true);
452
432
  expect($checkboxLabels.eq(1).hasClass('selected')).toBe(true);
453
433
  });
454
434
 
455
435
  it("Should mark checked checkboxes with the custom selected class if given", function () {
456
- $checkboxButtons.eq(0).attr('checked', true);
436
+ $checkboxButtons.eq(0).prop('checked', true);
457
437
  buttonsInstance = new GOVUK.SelectionButtons("label.selectable input[type='checkbox']", { 'selectedClass' : 'selectable-selected' });
458
438
  expect($checkboxLabels.eq(0).hasClass('selectable-selected')).toBe(true);
459
439
  });
@@ -514,8 +494,8 @@ describe("selection-buttons", function () {
514
494
  });
515
495
 
516
496
  it("Should mark checked checkboxes or radios with the selected class", function () {
517
- $mixedButtons.eq(0).attr('checked', true);
518
- $mixedButtons.eq(3).attr('checked', true);
497
+ $mixedButtons.eq(0).prop('checked', true);
498
+ $mixedButtons.eq(3).prop('checked', true);
519
499
 
520
500
  buttonsInstance = new GOVUK.SelectionButtons("label.selectable input");
521
501
  expect($checkboxLabels.eq(0).hasClass('selected')).toBe(true);
@@ -523,8 +503,8 @@ describe("selection-buttons", function () {
523
503
  });
524
504
 
525
505
  it("Should mark checked checkboxes or radios with the custom selected class if given", function () {
526
- $mixedButtons.eq(0).attr('checked', true);
527
- $mixedButtons.eq(3).attr('checked', true);
506
+ $mixedButtons.eq(0).prop('checked', true);
507
+ $mixedButtons.eq(3).prop('checked', true);
528
508
 
529
509
  buttonsInstance = new GOVUK.SelectionButtons("label.selectable input", { 'selectedClass' : 'selectable-selected' });
530
510
  expect($checkboxLabels.eq(0).hasClass('selectable-selected')).toBe(true);
@@ -547,9 +527,7 @@ describe("selection-buttons", function () {
547
527
  contentCache = $('#content').html();
548
528
  $('#content').html('');
549
529
  $('#content').html(contentCache);
550
- $("label.selectable input[type='radio']").eq(0)
551
- .attr('checked', true)
552
- .trigger('click');
530
+ $("label.selectable input[type='radio']").eq(0).trigger('click');
553
531
  expect($("label.selectable input[type='radio']").eq(0).parent('label').hasClass('selected')).toBe(true);
554
532
  });
555
533
 
@@ -563,9 +541,7 @@ describe("selection-buttons", function () {
563
541
  $radioButtons = $("label.selectable input[type='radio']");
564
542
  $radioLabels = $radioButtons.parent('label');
565
543
  $radioLabels.eq(1).addClass('selected');
566
- $radioButtons.eq(0)
567
- .attr('checked', true)
568
- .trigger('click');
544
+ $radioButtons.eq(0).trigger('click');
569
545
  expect($radioLabels.eq(2).hasClass('selected')).toBe(false);
570
546
  });
571
547
  });
@@ -631,9 +607,7 @@ describe("selection-buttons", function () {
631
607
  contentCache = $('#content').html();
632
608
  $('#content').html('');
633
609
  $('#content').html(contentCache);
634
- $("label.selectable input[type='checkbox']").eq(0)
635
- .attr('checked', true)
636
- .trigger('click');
610
+ $("label.selectable input[type='checkbox']").eq(0).trigger('click');
637
611
  expect($("label.selectable input[type='checkbox']").eq(0).parent('label').hasClass('selected')).toBe(true);
638
612
  });
639
613
  });
@@ -0,0 +1,49 @@
1
+ describe('An auto event tracker', function() {
2
+ "use strict";
3
+
4
+ var tracker,
5
+ element;
6
+
7
+ beforeEach(function() {
8
+ GOVUK.analytics = {trackEvent: function() {}};
9
+ tracker = new GOVUK.Modules.AutoTrackEvent();
10
+ });
11
+
12
+ afterEach(function() {
13
+ delete GOVUK.analytics;
14
+ });
15
+
16
+ it('tracks non-interactive events on start', function() {
17
+ spyOn(GOVUK.analytics, 'trackEvent');
18
+
19
+ element = $('\
20
+ <div \
21
+ data-track-category="category"\
22
+ data-track-action="action">\
23
+ Some content\
24
+ </div>\
25
+ ');
26
+
27
+ tracker.start(element);
28
+ expect(GOVUK.analytics.trackEvent).toHaveBeenCalledWith(
29
+ 'category', 'action', {nonInteraction: 1});
30
+ });
31
+
32
+ it('can track non-interactive events with optional label and value', function() {
33
+ spyOn(GOVUK.analytics, 'trackEvent');
34
+
35
+ element = $('\
36
+ <div \
37
+ data-track-category="category"\
38
+ data-track-action="action"\
39
+ data-track-label="label"\
40
+ data-track-value="10">\
41
+ Some content\
42
+ </div>\
43
+ ');
44
+
45
+ tracker.start(element);
46
+ expect(GOVUK.analytics.trackEvent).toHaveBeenCalledWith(
47
+ 'category', 'action', {label: 'label', value: 10, nonInteraction: 1});
48
+ });
49
+ });
metadata CHANGED
@@ -1,52 +1,46 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: govuk_frontend_toolkit
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.4.0
5
- prerelease:
4
+ version: 4.5.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Bradley Wright
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2015-11-05 00:00:00.000000000 Z
11
+ date: 2015-11-17 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rails
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - ">="
20
18
  - !ruby/object:Gem::Version
21
19
  version: 3.1.0
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - ">="
28
25
  - !ruby/object:Gem::Version
29
26
  version: 3.1.0
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: sass
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - ">="
36
32
  - !ruby/object:Gem::Version
37
33
  version: 3.2.0
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - ">="
44
39
  - !ruby/object:Gem::Version
45
40
  version: 3.2.0
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: gem_publisher
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
45
  - - '='
52
46
  - !ruby/object:Gem::Version
@@ -54,7 +48,6 @@ dependencies:
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
52
  - - '='
60
53
  - !ruby/object:Gem::Version
@@ -62,7 +55,6 @@ dependencies:
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: rake
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
59
  - - '='
68
60
  - !ruby/object:Gem::Version
@@ -70,7 +62,6 @@ dependencies:
70
62
  type: :development
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
66
  - - '='
76
67
  - !ruby/object:Gem::Version
@@ -81,19 +72,16 @@ executables: []
81
72
  extensions: []
82
73
  extra_rdoc_files: []
83
74
  files:
84
- - .gitignore
85
- - .gitmodules
75
+ - ".gitignore"
76
+ - ".gitmodules"
77
+ - ".ruby-version"
86
78
  - CONTRIBUTING.md
87
79
  - Gemfile
88
80
  - LICENCE
89
81
  - README.md
90
82
  - Rakefile
91
- - govuk_frontend_toolkit.gemspec
92
- - jenkins.sh
93
- - lib/govuk_frontend_toolkit.rb
94
- - lib/govuk_frontend_toolkit/engine.rb
95
- - lib/govuk_frontend_toolkit/version.rb
96
83
  - app/assets/.gitignore
84
+ - app/assets/.ruby-version
97
85
  - app/assets/.scss-lint.yaml
98
86
  - app/assets/.travis.yml
99
87
  - app/assets/CHANGELOG.md
@@ -237,6 +225,8 @@ files:
237
225
  - app/assets/javascripts/govuk/analytics/external-link-tracker.js
238
226
  - app/assets/javascripts/govuk/analytics/google-analytics-universal-tracker.js
239
227
  - app/assets/javascripts/govuk/analytics/print-intent.js
228
+ - app/assets/javascripts/govuk/modules.js
229
+ - app/assets/javascripts/govuk/modules/auto-track-event.js
240
230
  - app/assets/javascripts/govuk/multivariate-test.js
241
231
  - app/assets/javascripts/govuk/primary-links.js
242
232
  - app/assets/javascripts/govuk/selection-buttons.js
@@ -253,6 +243,7 @@ files:
253
243
  - app/assets/spec/support/console-runner.js
254
244
  - app/assets/spec/support/load.js
255
245
  - app/assets/spec/support/run_jasmine_test.js
246
+ - app/assets/spec/unit/ModulesSpec.js
256
247
  - app/assets/spec/unit/MultivariateTestSpec.js
257
248
  - app/assets/spec/unit/PrimaryLinksSpec.js
258
249
  - app/assets/spec/unit/SelectionButtonSpec.js
@@ -262,6 +253,7 @@ files:
262
253
  - app/assets/spec/unit/analytics/ErrorTrackingSpec.js
263
254
  - app/assets/spec/unit/analytics/ExternalLinkTrackerSpec.js
264
255
  - app/assets/spec/unit/analytics/GoogleAnalyticsUniversalTrackerSpec.js
256
+ - app/assets/spec/unit/modules/AutoTrackEventSpec.js
265
257
  - app/assets/stylesheets/.gitkeep
266
258
  - app/assets/stylesheets/_colours.scss
267
259
  - app/assets/stylesheets/_conditionals.scss
@@ -277,36 +269,34 @@ files:
277
269
  - app/assets/stylesheets/design-patterns/_alpha-beta.scss
278
270
  - app/assets/stylesheets/design-patterns/_buttons.scss
279
271
  - app/assets/stylesheets/design-patterns/_media-player.scss
272
+ - govuk_frontend_toolkit.gemspec
273
+ - jenkins.sh
274
+ - lib/govuk_frontend_toolkit.rb
275
+ - lib/govuk_frontend_toolkit/engine.rb
276
+ - lib/govuk_frontend_toolkit/version.rb
280
277
  homepage: https://github.com/alphagov/govuk_frontend_toolkit
281
278
  licenses:
282
279
  - MIT
280
+ metadata: {}
283
281
  post_install_message:
284
282
  rdoc_options: []
285
283
  require_paths:
286
284
  - lib
287
285
  - app
288
286
  required_ruby_version: !ruby/object:Gem::Requirement
289
- none: false
290
287
  requirements:
291
- - - ! '>='
288
+ - - ">="
292
289
  - !ruby/object:Gem::Version
293
290
  version: '0'
294
- segments:
295
- - 0
296
- hash: -607685694881966234
297
291
  required_rubygems_version: !ruby/object:Gem::Requirement
298
- none: false
299
292
  requirements:
300
- - - ! '>='
293
+ - - ">="
301
294
  - !ruby/object:Gem::Version
302
295
  version: '0'
303
- segments:
304
- - 0
305
- hash: -607685694881966234
306
296
  requirements: []
307
297
  rubyforge_project:
308
- rubygems_version: 1.8.23
298
+ rubygems_version: 2.4.5.1
309
299
  signing_key:
310
- specification_version: 3
300
+ specification_version: 4
311
301
  summary: Tools for building frontend applications
312
302
  test_files: []