govuk_frontend_toolkit 3.1.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,22 @@
1
+ // Extension to track errors using google analytics as a data store.
2
+ (function() {
3
+
4
+ "use strict";
5
+ var trackJavaScriptError = function (e) {
6
+ var errorSource = e.filename + ': ' + e.lineno;
7
+ GOVUK.analytics.trackEvent('JavaScript Error', e.message, {
8
+ label: errorSource,
9
+ value: 1,
10
+ nonInteraction: true
11
+ });
12
+ };
13
+
14
+ if (window.addEventListener) {
15
+ window.addEventListener('error', trackJavaScriptError, false);
16
+ } else if (window.attachEvent) {
17
+ window.attachEvent('onerror', trackJavaScriptError);
18
+ } else {
19
+ window.onerror = trackJavaScriptError;
20
+ }
21
+
22
+ }());
@@ -0,0 +1,111 @@
1
+ (function() {
2
+ "use strict";
3
+ window.GOVUK = window.GOVUK || {};
4
+
5
+ var GoogleAnalyticsClassicTracker = function(id, cookieDomain) {
6
+ window._gaq = window._gaq || [];
7
+ configureProfile(id, cookieDomain);
8
+ allowCrossDomainTracking();
9
+ anonymizeIp();
10
+
11
+ function configureProfile(id, cookieDomain) {
12
+ _gaq.push(['_setAccount', id]);
13
+ _gaq.push(['_setDomainName', cookieDomain]);
14
+ }
15
+
16
+ function allowCrossDomainTracking() {
17
+ _gaq.push(['_setAllowLinker', true]);
18
+ }
19
+
20
+ // https://developers.google.com/analytics/devguides/collection/gajs/methods/gaJSApi_gat#_gat._anonymizeIp
21
+ function anonymizeIp() {
22
+ _gaq.push(['_gat._anonymizeIp']);
23
+ }
24
+ };
25
+
26
+ GoogleAnalyticsClassicTracker.load = function() {
27
+ var ga = document.createElement('script'),
28
+ s = document.getElementsByTagName('script')[0];
29
+
30
+ ga.async = true;
31
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
32
+ s.parentNode.insertBefore(ga, s);
33
+ };
34
+
35
+ // https://developers.google.com/analytics/devguides/collection/gajs/asyncMigrationExamples#VirtualPageviews
36
+ GoogleAnalyticsClassicTracker.prototype.trackPageview = function(path) {
37
+ var pageview = ['_trackPageview'];
38
+
39
+ if (typeof path === "string") {
40
+ pageview.push(path);
41
+ }
42
+
43
+ _gaq.push(pageview);
44
+ };
45
+
46
+ // https://developers.google.com/analytics/devguides/collection/gajs/eventTrackerGuide
47
+ GoogleAnalyticsClassicTracker.prototype.trackEvent = function(category, action, options) {
48
+ var value,
49
+ options = options || {},
50
+ hasLabel = false,
51
+ hasValue = false,
52
+ evt = ["_trackEvent", category, action];
53
+
54
+ // Label is optional
55
+ if (typeof options.label === "string") {
56
+ hasLabel = true;
57
+ evt.push(options.label);
58
+ }
59
+
60
+ // Value is optional, but when used must be an
61
+ // integer, otherwise the event will be invalid
62
+ // and not logged
63
+ if (options.value || options.value === 0) {
64
+ value = parseInt(options.value, 10);
65
+ if (typeof value === "number" && !isNaN(value)) {
66
+ hasValue = true;
67
+
68
+ // Push an empty label if not set for correct final argument order
69
+ if (!hasLabel) {
70
+ evt.push('');
71
+ }
72
+
73
+ evt.push(value);
74
+ }
75
+ }
76
+
77
+ // Prevents an event from affecting bounce rate
78
+ // https://developers.google.com/analytics/devguides/collection/gajs/eventTrackerGuide#non-interaction
79
+ if (options.nonInteraction) {
80
+
81
+ // Push empty label/value if not already set, for correct final argument order
82
+ if (!hasValue) {
83
+ if (!hasLabel) {
84
+ evt.push('');
85
+ }
86
+ evt.push(0);
87
+ }
88
+
89
+ evt.push(true);
90
+ }
91
+
92
+ _gaq.push(evt);
93
+ };
94
+
95
+ /*
96
+ https://developers.google.com/analytics/devguides/collection/gajs/methods/gaJSApiSocialTracking
97
+ network – The network on which the action occurs (e.g. Facebook, Twitter)
98
+ action – The type of action that happens (e.g. Like, Send, Tweet)
99
+ target – The text value that indicates the subject of the action
100
+ */
101
+ GoogleAnalyticsClassicTracker.prototype.trackSocial = function(network, action, target) {
102
+ _gaq.push(['_trackSocial', network, action, target]);
103
+ };
104
+
105
+ // https://developers.google.com/analytics/devguides/collection/gajs/gaTrackingCustomVariables
106
+ GoogleAnalyticsClassicTracker.prototype.setCustomVariable = function(index, value, name, scope) {
107
+ _gaq.push(['_setCustomVar', index, name, String(value), scope]);
108
+ };
109
+
110
+ GOVUK.GoogleAnalyticsClassicTracker = GoogleAnalyticsClassicTracker;
111
+ })();
@@ -0,0 +1,104 @@
1
+ (function() {
2
+ "use strict";
3
+ window.GOVUK = window.GOVUK || {};
4
+
5
+ var GoogleAnalyticsUniversalTracker = function(id, cookieDomain) {
6
+ configureProfile(id, cookieDomain);
7
+ anonymizeIp();
8
+
9
+ function configureProfile(id, cookieDomain) {
10
+ sendToGa('create', id, {'cookieDomain': cookieDomain});
11
+ }
12
+
13
+ function anonymizeIp() {
14
+ // https://developers.google.com/analytics/devguides/collection/analyticsjs/advanced#anonymizeip
15
+ sendToGa('set', 'anonymizeIp', true);
16
+ }
17
+ };
18
+
19
+ GoogleAnalyticsUniversalTracker.load = function() {
20
+ (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
21
+ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
22
+ m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
23
+ })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
24
+ };
25
+
26
+ // https://developers.google.com/analytics/devguides/collection/analyticsjs/pages
27
+ GoogleAnalyticsUniversalTracker.prototype.trackPageview = function(path, title) {
28
+ if (typeof path === "string") {
29
+ var pageviewObject = {
30
+ page: path
31
+ };
32
+
33
+ if (typeof title === "string") {
34
+ pageviewObject.title = title;
35
+ }
36
+ sendToGa('send', 'pageview', pageviewObject);
37
+ } else {
38
+ sendToGa('send', 'pageview');
39
+ }
40
+ };
41
+
42
+ // https://developers.google.com/analytics/devguides/collection/analyticsjs/events
43
+ GoogleAnalyticsUniversalTracker.prototype.trackEvent = function(category, action, options) {
44
+ var value,
45
+ options = options || {},
46
+ evt = {
47
+ hitType: 'event',
48
+ eventCategory: category,
49
+ eventAction: action
50
+ };
51
+
52
+ // Label is optional
53
+ if (typeof options.label === "string") {
54
+ evt.eventLabel = options.label;
55
+ }
56
+
57
+ // Value is optional, but when used must be an
58
+ // integer, otherwise the event will be invalid
59
+ // and not logged
60
+ if (options.value || options.value === 0) {
61
+ value = parseInt(options.value, 10);
62
+ if (typeof value === "number" && !isNaN(value)) {
63
+ evt.eventValue = value;
64
+ }
65
+ }
66
+
67
+ // Prevents an event from affecting bounce rate
68
+ // https://developers.google.com/analytics/devguides/collection/analyticsjs/events#implementation
69
+ if (options.nonInteraction) {
70
+ evt.nonInteraction = 1;
71
+ }
72
+
73
+ sendToGa('send', evt);
74
+ };
75
+
76
+ /*
77
+ https://developers.google.com/analytics/devguides/collection/analyticsjs/social-interactions
78
+ network – The network on which the action occurs (e.g. Facebook, Twitter)
79
+ action – The type of action that happens (e.g. Like, Send, Tweet)
80
+ target – Specifies the target of a social interaction.
81
+ This value is typically a URL but can be any text.
82
+ */
83
+ GoogleAnalyticsUniversalTracker.prototype.trackSocial = function(network, action, target) {
84
+ sendToGa('send', {
85
+ 'hitType': 'social',
86
+ 'socialNetwork': network,
87
+ 'socialAction': action,
88
+ 'socialTarget': target
89
+ });
90
+ };
91
+
92
+ // https://developers.google.com/analytics/devguides/collection/analyticsjs/custom-dims-mets
93
+ GoogleAnalyticsUniversalTracker.prototype.setDimension = function(index, value) {
94
+ sendToGa('set', 'dimension' + index, String(value));
95
+ };
96
+
97
+ function sendToGa() {
98
+ if (typeof window.ga === "function") {
99
+ ga.apply(window, arguments);
100
+ }
101
+ }
102
+
103
+ GOVUK.GoogleAnalyticsUniversalTracker = GoogleAnalyticsUniversalTracker;
104
+ })();
@@ -0,0 +1,31 @@
1
+ // Extension to monitor attempts to print pages.
2
+ (function () {
3
+
4
+ "use strict";
5
+ var printAttempt = (function () {
6
+ GOVUK.analytics.trackEvent('Print Intent', document.location.pathname);
7
+ });
8
+
9
+ // Most browsers
10
+ if (window.matchMedia) {
11
+ var mediaQueryList = window.matchMedia('print'),
12
+ mqlListenerCount = 0;
13
+ mediaQueryList.addListener(function (mql) {
14
+ if (!mql.matches && mqlListenerCount === 0) {
15
+ printAttempt();
16
+ mqlListenerCount++;
17
+ // If we try and print again in 3 seconds, don't log it
18
+ window.setTimeout(function () {
19
+ mqlListenerCount = 0;
20
+ // printing will be tracked again now
21
+ }, 1e3);
22
+ }
23
+ });
24
+ }
25
+
26
+ // IE < 10
27
+ if (window.onafterprint) {
28
+ window.onafterprint = printAttempt;
29
+ }
30
+
31
+ }());
@@ -0,0 +1,61 @@
1
+ (function() {
2
+ "use strict";
3
+ window.GOVUK = window.GOVUK || {};
4
+
5
+ // For usage and initialisation see:
6
+ // https://github.com/alphagov/govuk_frontend_toolkit/blob/master/docs/analytics.md#create-an-analytics-tracker
7
+
8
+ var Tracker = function(config) {
9
+ this.universal = new GOVUK.GoogleAnalyticsUniversalTracker(config.universalId, config.cookieDomain);
10
+ this.classic = new GOVUK.GoogleAnalyticsClassicTracker(config.classicId, config.cookieDomain);
11
+ };
12
+
13
+ Tracker.load = function() {
14
+ GOVUK.GoogleAnalyticsClassicTracker.load();
15
+ GOVUK.GoogleAnalyticsUniversalTracker.load();
16
+ };
17
+
18
+ Tracker.prototype.trackPageview = function(path, title) {
19
+ this.classic.trackPageview(path);
20
+ this.universal.trackPageview(path, title);
21
+ };
22
+
23
+ /*
24
+ https://developers.google.com/analytics/devguides/collection/analyticsjs/events
25
+ options.label – Useful for categorizing events (eg nav buttons)
26
+ options.value – Values must be non-negative. Useful to pass counts
27
+ options.nonInteraction – Prevent event from impacting bounce rate
28
+ */
29
+ Tracker.prototype.trackEvent = function(category, action, options) {
30
+ this.classic.trackEvent(category, action, options);
31
+ this.universal.trackEvent(category, action, options);
32
+ };
33
+
34
+ Tracker.prototype.trackShare = function(network) {
35
+ var target = location.pathname;
36
+ this.classic.trackSocial(network, 'share', target);
37
+ this.universal.trackSocial(network, 'share', target);
38
+ };
39
+
40
+ /*
41
+ Assumes that the index of the dimension is the same for both classic and universal.
42
+ Check this for your app before using this
43
+ */
44
+ Tracker.prototype.setDimension = function(index, value, name, scope) {
45
+ var PAGE_LEVEL_SCOPE = 3;
46
+ scope = scope || PAGE_LEVEL_SCOPE;
47
+
48
+ if (typeof index !== "number") {
49
+ index = parseInt(index, 10);
50
+ }
51
+
52
+ if (typeof scope !== "number") {
53
+ scope = parseInt(scope, 10);
54
+ }
55
+
56
+ this.universal.setDimension(index, value);
57
+ this.classic.setCustomVariable(index, value, name, scope);
58
+ };
59
+
60
+ GOVUK.Tracker = Tracker;
61
+ })();
@@ -6,7 +6,7 @@
6
6
  "grunt": "~0.4.2",
7
7
  "grunt-cli": "0.1.11",
8
8
  "grunt-contrib-clean":"~0.6.0",
9
- "grunt-contrib-jasmine": "~0.5.2",
9
+ "grunt-contrib-jasmine": "~0.8.2",
10
10
  "grunt-contrib-sass": "0.7.4",
11
11
  "grunt-scss-lint": "0.3.4",
12
12
  "jquery-browser": "~1.7.2-3"
@@ -6,7 +6,7 @@ describe("MultivariateTest", function() {
6
6
 
7
7
  describe("#run", function() {
8
8
  it("should pick a random cohort on first run", function() {
9
- GOVUK.cookie.andReturn(null);
9
+ GOVUK.cookie.and.returnValue(null);
10
10
  var fooSpy = jasmine.createSpy('fooSpy');
11
11
  var barSpy = jasmine.createSpy('barSpy');
12
12
  var test = new GOVUK.MultivariateTest({
@@ -18,9 +18,9 @@ describe("MultivariateTest", function() {
18
18
  }
19
19
  });
20
20
 
21
- expect(GOVUK.cookie.callCount).toEqual(2);
22
- expect(GOVUK.cookie.argsForCall[1][0]).toEqual('multivariatetest_cohort_stuff');
23
- if (GOVUK.cookie.argsForCall[1][1] == 'foo') {
21
+ expect(GOVUK.cookie.calls.count()).toEqual(2);
22
+ expect(GOVUK.cookie.calls.argsFor(1)[0]).toEqual('multivariatetest_cohort_stuff');
23
+ if (GOVUK.cookie.calls.argsFor(1)[1] == 'foo') {
24
24
  expect(fooSpy).toHaveBeenCalled();
25
25
  }
26
26
  else {
@@ -29,7 +29,7 @@ describe("MultivariateTest", function() {
29
29
  });
30
30
 
31
31
  it("should use an existing cohort choice on subsequent runs", function() {
32
- GOVUK.cookie.andReturn('foo');
32
+ GOVUK.cookie.and.returnValue('foo');
33
33
  var fooSpy = jasmine.createSpy('fooSpy');
34
34
  var barSpy = jasmine.createSpy('barSpy');
35
35
  var test = new GOVUK.MultivariateTest({
@@ -44,7 +44,7 @@ describe("MultivariateTest", function() {
44
44
  });
45
45
 
46
46
  it("should set a custom var", function() {
47
- GOVUK.cookie.andReturn('foo');
47
+ GOVUK.cookie.and.returnValue('foo');
48
48
  var test = new GOVUK.MultivariateTest({
49
49
  name: 'stuff',
50
50
  cohorts: {
@@ -73,7 +73,7 @@ describe("MultivariateTest", function() {
73
73
  });
74
74
 
75
75
  it("should set html for a cohort", function() {
76
- GOVUK.cookie.andReturn('foo');
76
+ GOVUK.cookie.and.returnValue('foo');
77
77
  var $el = $('<div>');
78
78
  var test = new GOVUK.MultivariateTest({
79
79
  name: 'stuff',
@@ -90,7 +90,7 @@ describe("MultivariateTest", function() {
90
90
  it("should call the callback for a cohort", function() {
91
91
  var fooSpy = jasmine.createSpy('fooSpy');
92
92
  var barSpy = jasmine.createSpy('barSpy');
93
- GOVUK.cookie.andReturn('bar');
93
+ GOVUK.cookie.and.returnValue('bar');
94
94
  var $el = $('<div>');
95
95
  var test = new GOVUK.MultivariateTest({
96
96
  name: 'stuff',
@@ -105,7 +105,7 @@ describe("MultivariateTest", function() {
105
105
  });
106
106
 
107
107
  it("should call the callback for a cohort if it is a string", function() {
108
- GOVUK.cookie.andReturn('foo');
108
+ GOVUK.cookie.and.returnValue('foo');
109
109
  var test = new GOVUK.MultivariateTest({
110
110
  name: 'stuff',
111
111
  customVarIndex: 1,
@@ -123,7 +123,7 @@ describe("MultivariateTest", function() {
123
123
  it("should assign a new random cohort if the assigned cohort does not exist", function() {
124
124
  var fooSpy = jasmine.createSpy('fooSpy');
125
125
  var barSpy = jasmine.createSpy('barSpy');
126
- GOVUK.cookie.andReturn('baz');
126
+ GOVUK.cookie.and.returnValue('baz');
127
127
  var test = new GOVUK.MultivariateTest({
128
128
  name: 'stuff',
129
129
  customVarIndex: 1,
@@ -132,7 +132,7 @@ describe("MultivariateTest", function() {
132
132
  bar: {callback: barSpy}
133
133
  }
134
134
  });
135
- if (GOVUK.cookie.argsForCall[1][1] == 'foo') {
135
+ if (GOVUK.cookie.calls.argsFor(1)[1] == 'foo') {
136
136
  expect(fooSpy).toHaveBeenCalled();
137
137
  }
138
138
  else {
@@ -694,7 +694,7 @@ describe("selection-buttons", function () {
694
694
  clickCallbackCancelled = false,
695
695
  focusBlurCallbackCancelled = false;
696
696
 
697
- spyOn($.fn, "on").andCallFake(function (evt, callback) {
697
+ spyOn($.fn, "on").and.callFake(function (evt, callback) {
698
698
  if (this === $radioButtons) {
699
699
  if (evt === "click") {
700
700
  clickCallbackBound = callback;
@@ -706,7 +706,7 @@ describe("selection-buttons", function () {
706
706
  return this;
707
707
  });
708
708
 
709
- spyOn($.fn, "off").andCallFake(function (evt, callback) {
709
+ spyOn($.fn, "off").and.callFake(function (evt, callback) {
710
710
  if (this === $radioButtons) {
711
711
  if (evt === "click") {
712
712
  clickCallbackCancelled = callback;
@@ -731,7 +731,7 @@ describe("selection-buttons", function () {
731
731
  clickCallbackCancelled = false,
732
732
  focusBlurCallbackCancelled = false;
733
733
 
734
- spyOn($.fn, "on").andCallFake(function (evt, selector, callback) {
734
+ spyOn($.fn, "on").and.callFake(function (evt, selector, callback) {
735
735
  if ((this[0] === document) && (selector === "label.selectable input[type='checkbox']")) {
736
736
  if (evt === "click") {
737
737
  clickCallbackBound = callback;
@@ -743,7 +743,7 @@ describe("selection-buttons", function () {
743
743
  return this;
744
744
  });
745
745
 
746
- spyOn($.fn, "off").andCallFake(function (evt, selector, callback) {
746
+ spyOn($.fn, "off").and.callFake(function (evt, selector, callback) {
747
747
  if ((this[0] === document) && (selector === "label.selectable input[type='checkbox']")) {
748
748
  if (evt === "click") {
749
749
  clickCallbackCancelled = callback;