idsk_frontend_toolkit 7.4.2
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.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/.gitmodules +3 -0
- data/.ruby-version +1 -0
- data/.travis/govuk_frontend_toolkit_gem_push.enc +0 -0
- data/.travis/govuk_frontend_toolkit_gem_push.pub +1 -0
- data/.travis.yml +23 -0
- data/CONTRIBUTING.md +13 -0
- data/Gemfile +3 -0
- data/LICENCE +20 -0
- data/README.md +61 -0
- data/Rakefile +10 -0
- data/app/assets/.gitignore +5 -0
- data/app/assets/.ruby-version +1 -0
- data/app/assets/.travis/README.md +23 -0
- data/app/assets/.travis/govuk_frontend_toolkit_push.enc +0 -0
- data/app/assets/.travis/govuk_frontend_toolkit_push.pub +1 -0
- data/app/assets/.travis.yml +18 -0
- data/app/assets/CHANGELOG.md +381 -0
- data/app/assets/CONTRIBUTING.md +23 -0
- data/app/assets/Gemfile +4 -0
- data/app/assets/Gemfile.lock +48 -0
- data/app/assets/Gruntfile.js +68 -0
- data/app/assets/LICENCE +20 -0
- data/app/assets/README.md +170 -0
- data/app/assets/VERSION.txt +1 -0
- data/app/assets/create-release.sh +38 -0
- data/app/assets/docs/analytics.md +270 -0
- data/app/assets/docs/functions.md +62 -0
- data/app/assets/docs/javascript.md +337 -0
- data/app/assets/docs/mixins.md +617 -0
- data/app/assets/images/accordion-arrow-2x.png +0 -0
- data/app/assets/images/accordion-arrow.png +0 -0
- data/app/assets/images/arrow-sprite.png +0 -0
- data/app/assets/images/crests/bis_crest_13px.png +0 -0
- data/app/assets/images/crests/bis_crest_13px_x2.png +0 -0
- data/app/assets/images/crests/bis_crest_18px.png +0 -0
- data/app/assets/images/crests/bis_crest_18px_x2.png +0 -0
- data/app/assets/images/crests/bis_crest_27px.png +0 -0
- data/app/assets/images/crests/bis_crest_27px_x2.png +0 -0
- data/app/assets/images/crests/coastguard_13px.png +0 -0
- data/app/assets/images/crests/coastguard_13px_x2.png +0 -0
- data/app/assets/images/crests/coastguard_18px.png +0 -0
- data/app/assets/images/crests/coastguard_18px_x2.png +0 -0
- data/app/assets/images/crests/coastguard_27px.png +0 -0
- data/app/assets/images/crests/coastguard_27px_x2.png +0 -0
- data/app/assets/images/crests/dit_crest_13px.png +0 -0
- data/app/assets/images/crests/dit_crest_13px_x2.png +0 -0
- data/app/assets/images/crests/dit_crest_18px.png +0 -0
- data/app/assets/images/crests/dit_crest_18px_x2.png +0 -0
- data/app/assets/images/crests/dit_crest_27px.png +0 -0
- data/app/assets/images/crests/dit_crest_27px_x2.png +0 -0
- data/app/assets/images/crests/hmrc_crest_13px.png +0 -0
- data/app/assets/images/crests/hmrc_crest_13px_x2.png +0 -0
- data/app/assets/images/crests/hmrc_crest_18px.png +0 -0
- data/app/assets/images/crests/hmrc_crest_18px_x2.png +0 -0
- data/app/assets/images/crests/hmrc_crest_27px.png +0 -0
- data/app/assets/images/crests/hmrc_crest_27px_x2.png +0 -0
- data/app/assets/images/crests/ho_crest_13px.png +0 -0
- data/app/assets/images/crests/ho_crest_13px_x2.png +0 -0
- data/app/assets/images/crests/ho_crest_18px.png +0 -0
- data/app/assets/images/crests/ho_crest_18px_x2.png +0 -0
- data/app/assets/images/crests/ho_crest_27px.png +0 -0
- data/app/assets/images/crests/ho_crest_27px_x2.png +0 -0
- data/app/assets/images/crests/mod_crest_13px.png +0 -0
- data/app/assets/images/crests/mod_crest_13px_x2.png +0 -0
- data/app/assets/images/crests/mod_crest_18px.png +0 -0
- data/app/assets/images/crests/mod_crest_18px_x2.png +0 -0
- data/app/assets/images/crests/mod_crest_27px.png +0 -0
- data/app/assets/images/crests/mod_crest_27px_x2.png +0 -0
- data/app/assets/images/crests/org_crest_13px.png +0 -0
- data/app/assets/images/crests/org_crest_13px_x2.png +0 -0
- data/app/assets/images/crests/org_crest_18px.png +0 -0
- data/app/assets/images/crests/org_crest_18px_x2.png +0 -0
- data/app/assets/images/crests/org_crest_27px.png +0 -0
- data/app/assets/images/crests/org_crest_27px_x2.png +0 -0
- data/app/assets/images/crests/portcullis_13px.png +0 -0
- data/app/assets/images/crests/portcullis_13px_x2.png +0 -0
- data/app/assets/images/crests/portcullis_18px.png +0 -0
- data/app/assets/images/crests/portcullis_18px_x2.png +0 -0
- data/app/assets/images/crests/portcullis_27px.png +0 -0
- data/app/assets/images/crests/portcullis_27px_x2.png +0 -0
- data/app/assets/images/crests/so_crest_13px.png +0 -0
- data/app/assets/images/crests/so_crest_13px_x2.png +0 -0
- data/app/assets/images/crests/so_crest_18px.png +0 -0
- data/app/assets/images/crests/so_crest_18px_x2.png +0 -0
- data/app/assets/images/crests/so_crest_27px.png +0 -0
- data/app/assets/images/crests/so_crest_27px_x2.png +0 -0
- data/app/assets/images/crests/ukaea_crest_13px.png +0 -0
- data/app/assets/images/crests/ukaea_crest_13px_x2.png +0 -0
- data/app/assets/images/crests/ukaea_crest_18px.png +0 -0
- data/app/assets/images/crests/ukaea_crest_18px_x2.png +0 -0
- data/app/assets/images/crests/ukaea_crest_27px.png +0 -0
- data/app/assets/images/crests/ukaea_crest_27px_x2.png +0 -0
- data/app/assets/images/crests/ukho_13px.png +0 -0
- data/app/assets/images/crests/ukho_13px_x2.png +0 -0
- data/app/assets/images/crests/ukho_18px.png +0 -0
- data/app/assets/images/crests/ukho_18px_x2.png +0 -0
- data/app/assets/images/crests/ukho_27px.png +0 -0
- data/app/assets/images/crests/ukho_27px_x2.png +0 -0
- data/app/assets/images/crests/wales_crest_13px.png +0 -0
- data/app/assets/images/crests/wales_crest_13px_x2.png +0 -0
- data/app/assets/images/crests/wales_crest_18px.png +0 -0
- data/app/assets/images/crests/wales_crest_18px_x2.png +0 -0
- data/app/assets/images/crests/wales_crest_27px.png +0 -0
- data/app/assets/images/crests/wales_crest_27px_x2.png +0 -0
- data/app/assets/images/icon-arrow-left.png +0 -0
- data/app/assets/images/icon-calendar-2x.png +0 -0
- data/app/assets/images/icon-calendar.png +0 -0
- data/app/assets/images/icon-file-download-2x.png +0 -0
- data/app/assets/images/icon-file-download.png +0 -0
- data/app/assets/images/icon-important-2x.png +0 -0
- data/app/assets/images/icon-important.png +0 -0
- data/app/assets/images/icon-information-2x.png +0 -0
- data/app/assets/images/icon-information.png +0 -0
- data/app/assets/images/icon-locator-2x.png +0 -0
- data/app/assets/images/icon-locator.png +0 -0
- data/app/assets/images/icon-pointer-2x.png +0 -0
- data/app/assets/images/icon-pointer-black-2x.png +0 -0
- data/app/assets/images/icon-pointer-black.png +0 -0
- data/app/assets/images/icon-pointer-indexed.png +0 -0
- data/app/assets/images/icon-pointer.png +0 -0
- data/app/assets/images/icon-search-2x.png +0 -0
- data/app/assets/images/icon-search.png +0 -0
- data/app/assets/images/icon-steps/icon-step-1-2x.png +0 -0
- data/app/assets/images/icon-steps/icon-step-1.png +0 -0
- data/app/assets/images/icon-steps/icon-step-10-2x.png +0 -0
- data/app/assets/images/icon-steps/icon-step-10.png +0 -0
- data/app/assets/images/icon-steps/icon-step-11-2x.png +0 -0
- data/app/assets/images/icon-steps/icon-step-11.png +0 -0
- data/app/assets/images/icon-steps/icon-step-12-2x.png +0 -0
- data/app/assets/images/icon-steps/icon-step-12.png +0 -0
- data/app/assets/images/icon-steps/icon-step-13-2x.png +0 -0
- data/app/assets/images/icon-steps/icon-step-13.png +0 -0
- data/app/assets/images/icon-steps/icon-step-14-2x.png +0 -0
- data/app/assets/images/icon-steps/icon-step-14.png +0 -0
- data/app/assets/images/icon-steps/icon-step-2-2x.png +0 -0
- data/app/assets/images/icon-steps/icon-step-2.png +0 -0
- data/app/assets/images/icon-steps/icon-step-3-2x.png +0 -0
- data/app/assets/images/icon-steps/icon-step-3.png +0 -0
- data/app/assets/images/icon-steps/icon-step-4-2x.png +0 -0
- data/app/assets/images/icon-steps/icon-step-4.png +0 -0
- data/app/assets/images/icon-steps/icon-step-5-2x.png +0 -0
- data/app/assets/images/icon-steps/icon-step-5.png +0 -0
- data/app/assets/images/icon-steps/icon-step-6-2x.png +0 -0
- data/app/assets/images/icon-steps/icon-step-6.png +0 -0
- data/app/assets/images/icon-steps/icon-step-7-2x.png +0 -0
- data/app/assets/images/icon-steps/icon-step-7.png +0 -0
- data/app/assets/images/icon-steps/icon-step-8-2x.png +0 -0
- data/app/assets/images/icon-steps/icon-step-8.png +0 -0
- data/app/assets/images/icon-steps/icon-step-9-2x.png +0 -0
- data/app/assets/images/icon-steps/icon-step-9.png +0 -0
- data/app/assets/images/player-icon-forward.png +0 -0
- data/app/assets/images/player-icon-pause.png +0 -0
- data/app/assets/images/player-icon-play.png +0 -0
- data/app/assets/images/player-icon-rewind.png +0 -0
- data/app/assets/images/player-icon-volume.png +0 -0
- data/app/assets/images/separator-2x.png +0 -0
- data/app/assets/images/separator.png +0 -0
- data/app/assets/javascripts/govuk/analytics/analytics.js +143 -0
- data/app/assets/javascripts/govuk/analytics/download-link-tracker.js +41 -0
- data/app/assets/javascripts/govuk/analytics/error-tracking.js +51 -0
- data/app/assets/javascripts/govuk/analytics/external-link-tracker.js +56 -0
- data/app/assets/javascripts/govuk/analytics/google-analytics-universal-tracker.js +166 -0
- data/app/assets/javascripts/govuk/analytics/govuk-tracker.js +134 -0
- data/app/assets/javascripts/govuk/analytics/mailto-link-tracker.js +38 -0
- data/app/assets/javascripts/govuk/analytics/print-intent.js +39 -0
- data/app/assets/javascripts/govuk/details.polyfill.js +240 -0
- data/app/assets/javascripts/govuk/modules/auto-track-event.js +30 -0
- data/app/assets/javascripts/govuk/modules.js +61 -0
- data/app/assets/javascripts/govuk/primary-links.js +57 -0
- data/app/assets/javascripts/govuk/selection-buttons.js +116 -0
- data/app/assets/javascripts/govuk/shim-links-with-button-role.js +34 -0
- data/app/assets/javascripts/govuk/show-hide-content.js +172 -0
- data/app/assets/javascripts/govuk/stick-at-top-when-scrolling.js +128 -0
- data/app/assets/javascripts/govuk/stop-scrolling-at-footer.js +139 -0
- data/app/assets/javascripts/govuk_toolkit.js +1 -0
- data/app/assets/javascripts/stageprompt.js +69 -0
- data/app/assets/javascripts/vendor/jquery/jquery.player.min.js +25 -0
- data/app/assets/javascripts/vendor/polyfills/bind.js +40 -0
- data/app/assets/package.json +25 -0
- data/app/assets/spec/manifest.js +41 -0
- data/app/assets/spec/stylesheets/_colour_contrast_spec.scss +12 -0
- data/app/assets/spec/support/LocalTestRunner.html +21 -0
- data/app/assets/spec/support/console-runner.js +102 -0
- data/app/assets/spec/support/load.js +47 -0
- data/app/assets/spec/support/run_jasmine_test.js +62 -0
- data/app/assets/spec/unit/analytics/analytics.spec.js +315 -0
- data/app/assets/spec/unit/analytics/download-link-tracker.spec.js +72 -0
- data/app/assets/spec/unit/analytics/error-tracking.spec.js +65 -0
- data/app/assets/spec/unit/analytics/external-link-tracker.spec.js +109 -0
- data/app/assets/spec/unit/analytics/google-analytics-universal-tracker.spec.js +180 -0
- data/app/assets/spec/unit/analytics/govuk-tracker.spec.js +171 -0
- data/app/assets/spec/unit/analytics/mailto-link-tracker.spec.js +62 -0
- data/app/assets/spec/unit/details.polyfill.spec.js +91 -0
- data/app/assets/spec/unit/modules/auto-track-event.spec.js +54 -0
- data/app/assets/spec/unit/modules.spec.js +93 -0
- data/app/assets/spec/unit/primary-links.spec.js +55 -0
- data/app/assets/spec/unit/selection-button.spec.js +761 -0
- data/app/assets/spec/unit/shim-links-with-button-role.spec.js +41 -0
- data/app/assets/spec/unit/show-hide-content.spec.js +306 -0
- data/app/assets/spec/unit/stick-at-top-when-scrolling.spec.js +137 -0
- data/app/assets/stylesheets/.gitkeep +0 -0
- data/app/assets/stylesheets/_colours.scss +2 -0
- data/app/assets/stylesheets/_conditionals.scss +81 -0
- data/app/assets/stylesheets/_css3.scss +90 -0
- data/app/assets/stylesheets/_device-pixels.scss +10 -0
- data/app/assets/stylesheets/_font_stack.scss +25 -0
- data/app/assets/stylesheets/_grid_layout.scss +136 -0
- data/app/assets/stylesheets/_helpers.scss +16 -0
- data/app/assets/stylesheets/_measurements.scss +14 -0
- data/app/assets/stylesheets/_shims.scss +55 -0
- data/app/assets/stylesheets/_typography.scss +249 -0
- data/app/assets/stylesheets/_url-helpers.scss +16 -0
- data/app/assets/stylesheets/colours/_organisation.scss +104 -0
- data/app/assets/stylesheets/colours/_palette.scss +77 -0
- data/app/assets/stylesheets/design-patterns/_alpha-beta.scss +67 -0
- data/app/assets/stylesheets/design-patterns/_breadcrumbs.scss +53 -0
- data/app/assets/stylesheets/design-patterns/_buttons.scss +145 -0
- data/app/assets/stylesheets/design-patterns/_media-player.scss +264 -0
- data/app/assets/trigger.sh +24 -0
- data/idsk_frontend_toolkit.gemspec +49 -0
- data/lib/idsk_frontend_toolkit/engine.rb +4 -0
- data/lib/idsk_frontend_toolkit/version.rb +5 -0
- data/lib/idsk_frontend_toolkit.rb +4 -0
- data/publish.sh +30 -0
- metadata +314 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
;(function (global) {
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
var $ = global.jQuery
|
|
5
|
+
var GOVUK = global.GOVUK || {}
|
|
6
|
+
|
|
7
|
+
var GoogleAnalyticsUniversalTracker = function (trackingId, fieldsObject) {
|
|
8
|
+
function configureProfile () {
|
|
9
|
+
// https://developers.google.com/analytics/devguides/collection/analyticsjs/command-queue-reference#create
|
|
10
|
+
sendToGa('create', trackingId, fieldsObject)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function anonymizeIp () {
|
|
14
|
+
// https://developers.google.com/analytics/devguides/collection/analyticsjs/advanced#anonymizeip
|
|
15
|
+
sendToGa('set', 'anonymizeIp', true)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function disableAdTracking () {
|
|
19
|
+
// https://support.google.com/analytics/answer/2444872?hl=en
|
|
20
|
+
sendToGa('set', 'displayFeaturesTask', null)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Support legacy cookieDomain param
|
|
24
|
+
if (typeof fieldsObject === 'string') {
|
|
25
|
+
fieldsObject = { cookieDomain: fieldsObject }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
configureProfile()
|
|
29
|
+
anonymizeIp()
|
|
30
|
+
disableAdTracking()
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
GoogleAnalyticsUniversalTracker.load = function () {
|
|
34
|
+
/* eslint-disable */
|
|
35
|
+
(function (i, s, o, g, r, a, m) { i['GoogleAnalyticsObject'] = r; i[r] = i[r] || function () {
|
|
36
|
+
(i[r].q = i[r].q || []).push(arguments) }, i[r].l = 1 * new Date(); a = s.createElement(o),
|
|
37
|
+
m = s.getElementsByTagName(o)[0]; a.async = 1; a.src = g; m.parentNode.insertBefore(a, m)
|
|
38
|
+
})(global, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga')
|
|
39
|
+
/* eslint-enable */
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// https://developers.google.com/analytics/devguides/collection/analyticsjs/pages
|
|
43
|
+
GoogleAnalyticsUniversalTracker.prototype.trackPageview = function (path, title, options) {
|
|
44
|
+
var pageviewObject
|
|
45
|
+
|
|
46
|
+
if (typeof path === 'string') {
|
|
47
|
+
pageviewObject = { page: path }
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (typeof title === 'string') {
|
|
51
|
+
pageviewObject = pageviewObject || {}
|
|
52
|
+
pageviewObject.title = title
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Set an options object for the pageview (e.g. transport, sessionControl)
|
|
56
|
+
// https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference#transport
|
|
57
|
+
if (typeof options === 'object') {
|
|
58
|
+
pageviewObject = $.extend(pageviewObject || {}, options)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (!$.isEmptyObject(pageviewObject)) {
|
|
62
|
+
sendToGa('send', 'pageview', pageviewObject)
|
|
63
|
+
} else {
|
|
64
|
+
sendToGa('send', 'pageview')
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// https://developers.google.com/analytics/devguides/collection/analyticsjs/events
|
|
69
|
+
GoogleAnalyticsUniversalTracker.prototype.trackEvent = function (category, action, options) {
|
|
70
|
+
options = options || {}
|
|
71
|
+
var value
|
|
72
|
+
var evt = {
|
|
73
|
+
hitType: 'event',
|
|
74
|
+
eventCategory: category,
|
|
75
|
+
eventAction: action
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Label is optional
|
|
79
|
+
if (typeof options.label === 'string') {
|
|
80
|
+
evt.eventLabel = options.label
|
|
81
|
+
delete options.label
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Value is optional, but when used must be an
|
|
85
|
+
// integer, otherwise the event will be invalid
|
|
86
|
+
// and not logged
|
|
87
|
+
if (options.value || options.value === 0) {
|
|
88
|
+
value = parseInt(options.value, 10)
|
|
89
|
+
if (typeof value === 'number' && !isNaN(value)) {
|
|
90
|
+
options.eventValue = value
|
|
91
|
+
}
|
|
92
|
+
delete options.value
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Prevents an event from affecting bounce rate
|
|
96
|
+
// https://developers.google.com/analytics/devguides/collection/analyticsjs/events#implementation
|
|
97
|
+
if (options.nonInteraction) {
|
|
98
|
+
options.nonInteraction = 1
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (typeof options === 'object') {
|
|
102
|
+
$.extend(evt, options)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
sendToGa('send', evt)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/*
|
|
109
|
+
https://developers.google.com/analytics/devguides/collection/analyticsjs/social-interactions
|
|
110
|
+
network – The network on which the action occurs (e.g. Facebook, Twitter)
|
|
111
|
+
action – The type of action that happens (e.g. Like, Send, Tweet)
|
|
112
|
+
target – Specifies the target of a social interaction.
|
|
113
|
+
This value is typically a URL but can be any text.
|
|
114
|
+
*/
|
|
115
|
+
GoogleAnalyticsUniversalTracker.prototype.trackSocial = function (network, action, target, options) {
|
|
116
|
+
var trackingOptions = {
|
|
117
|
+
'hitType': 'social',
|
|
118
|
+
'socialNetwork': network,
|
|
119
|
+
'socialAction': action,
|
|
120
|
+
'socialTarget': target
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
$.extend(trackingOptions, options)
|
|
124
|
+
|
|
125
|
+
sendToGa('send', trackingOptions)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/*
|
|
129
|
+
https://developers.google.com/analytics/devguides/collection/analyticsjs/cross-domain
|
|
130
|
+
trackerId - the UA account code to track the domain against
|
|
131
|
+
name - name for the tracker
|
|
132
|
+
domain - the domain to track
|
|
133
|
+
*/
|
|
134
|
+
GoogleAnalyticsUniversalTracker.prototype.addLinkedTrackerDomain = function (trackerId, name, domain) {
|
|
135
|
+
sendToGa('create',
|
|
136
|
+
trackerId,
|
|
137
|
+
'auto',
|
|
138
|
+
{'name': name})
|
|
139
|
+
// Load the plugin.
|
|
140
|
+
sendToGa('require', 'linker')
|
|
141
|
+
sendToGa(name + '.require', 'linker')
|
|
142
|
+
|
|
143
|
+
// Define which domains to autoLink.
|
|
144
|
+
sendToGa('linker:autoLink', [domain])
|
|
145
|
+
sendToGa(name + '.linker:autoLink', [domain])
|
|
146
|
+
|
|
147
|
+
sendToGa(name + '.set', 'anonymizeIp', true)
|
|
148
|
+
sendToGa(name + '.set', 'displayFeaturesTask', null)
|
|
149
|
+
sendToGa(name + '.send', 'pageview')
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// https://developers.google.com/analytics/devguides/collection/analyticsjs/custom-dims-mets
|
|
153
|
+
GoogleAnalyticsUniversalTracker.prototype.setDimension = function (index, value) {
|
|
154
|
+
sendToGa('set', 'dimension' + index, String(value))
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function sendToGa () {
|
|
158
|
+
if (typeof global.ga === 'function') {
|
|
159
|
+
global.ga.apply(global, arguments)
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
GOVUK.GoogleAnalyticsUniversalTracker = GoogleAnalyticsUniversalTracker
|
|
164
|
+
|
|
165
|
+
global.GOVUK = GOVUK
|
|
166
|
+
})(window)
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
;(function (global) {
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
var $ = global.jQuery
|
|
5
|
+
var GOVUK = global.GOVUK || {}
|
|
6
|
+
|
|
7
|
+
var GOVUKTracker = function (gifUrl) {
|
|
8
|
+
this.gifUrl = gifUrl
|
|
9
|
+
this.dimensions = []
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
GOVUKTracker.load = function () {}
|
|
13
|
+
|
|
14
|
+
GOVUKTracker.prototype.trackPageview = function (path, title, options) {
|
|
15
|
+
var pageviewObject
|
|
16
|
+
|
|
17
|
+
if (typeof path === 'string') {
|
|
18
|
+
pageviewObject = { page: path }
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (typeof title === 'string') {
|
|
22
|
+
pageviewObject = pageviewObject || {}
|
|
23
|
+
pageviewObject.title = title
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Set an options object for the pageview (e.g. transport, sessionControl)
|
|
27
|
+
// https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference#transport
|
|
28
|
+
if (typeof options === 'object') {
|
|
29
|
+
pageviewObject = $.extend(pageviewObject || {}, options)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (!$.isEmptyObject(pageviewObject)) {
|
|
33
|
+
this.sendToTracker('pageview', pageviewObject)
|
|
34
|
+
} else {
|
|
35
|
+
this.sendToTracker('pageview')
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// https://developers.google.com/analytics/devguides/collection/analyticsjs/events
|
|
40
|
+
GOVUKTracker.prototype.trackEvent = function (category, action, options) {
|
|
41
|
+
options = options || {}
|
|
42
|
+
var evt = {
|
|
43
|
+
eventCategory: category,
|
|
44
|
+
eventAction: action
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (options.label) {
|
|
48
|
+
evt.eventLabel = options.label
|
|
49
|
+
delete options.label
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (options.value) {
|
|
53
|
+
evt.eventValue = options.value.toString()
|
|
54
|
+
delete options.value
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (typeof options === 'object') {
|
|
58
|
+
$.extend(evt, options)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
this.sendToTracker('event', evt)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
GOVUKTracker.prototype.trackSocial = function (network, action, target, options) {
|
|
65
|
+
var trackingOptions = {
|
|
66
|
+
'socialNetwork': network,
|
|
67
|
+
'socialAction': action,
|
|
68
|
+
'socialTarget': target
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
$.extend(trackingOptions, options)
|
|
72
|
+
|
|
73
|
+
this.sendToTracker('social', trackingOptions)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
GOVUKTracker.prototype.addLinkedTrackerDomain = function () { /* noop */ }
|
|
77
|
+
|
|
78
|
+
GOVUKTracker.prototype.setDimension = function (index, value) {
|
|
79
|
+
this.dimensions['dimension' + index] = value
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
GOVUKTracker.prototype.payloadParams = function (type, payload) {
|
|
83
|
+
var data = $.extend({},
|
|
84
|
+
payload,
|
|
85
|
+
this.dimensions,
|
|
86
|
+
{
|
|
87
|
+
eventType: type,
|
|
88
|
+
referrer: global.document.referrer,
|
|
89
|
+
gaClientId: this.gaClientId,
|
|
90
|
+
windowWidth: global.innerWidth,
|
|
91
|
+
windowHeight: global.innerHeight,
|
|
92
|
+
screenWidth: global.screen.width,
|
|
93
|
+
screenHeight: global.screen.height,
|
|
94
|
+
colorDepth: global.screen.colorDepth
|
|
95
|
+
}
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
if (global.performance) {
|
|
99
|
+
data.navigationType = global.performance.navigation.type.toString()
|
|
100
|
+
data.redirectCount = global.performance.navigation.redirectCount.toString()
|
|
101
|
+
|
|
102
|
+
for (var k in global.performance.timing) {
|
|
103
|
+
var v = global.performance.timing[k]
|
|
104
|
+
if (typeof v === 'string' || typeof v === 'number') {
|
|
105
|
+
data['timing_' + k] = v.toString()
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return data
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
GOVUKTracker.prototype.sendData = function (params) {
|
|
114
|
+
var url = this.gifUrl + '?' + $.param(params)
|
|
115
|
+
$.get(url)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
GOVUKTracker.prototype.sendToTracker = function (type, payload) {
|
|
119
|
+
$(global.document).ready(function () {
|
|
120
|
+
if (global.ga) {
|
|
121
|
+
global.ga(function (tracker) {
|
|
122
|
+
this.gaClientId = tracker.get('clientId')
|
|
123
|
+
this.sendData(this.payloadParams(type, payload))
|
|
124
|
+
}.bind(this))
|
|
125
|
+
} else {
|
|
126
|
+
this.sendData(this.payloadParams(type, payload))
|
|
127
|
+
}
|
|
128
|
+
}.bind(this))
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
GOVUK.GOVUKTracker = GOVUKTracker
|
|
132
|
+
|
|
133
|
+
global.GOVUK = GOVUK
|
|
134
|
+
})(window)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
;(function (global) {
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
var $ = global.jQuery
|
|
5
|
+
var GOVUK = global.GOVUK || {}
|
|
6
|
+
|
|
7
|
+
GOVUK.analyticsPlugins = GOVUK.analyticsPlugins || {}
|
|
8
|
+
GOVUK.analyticsPlugins.mailtoLinkTracker = function () {
|
|
9
|
+
var mailtoLinkSelector = 'a[href^="mailto:"]'
|
|
10
|
+
|
|
11
|
+
$('body').on('click', mailtoLinkSelector, trackClickEvent)
|
|
12
|
+
|
|
13
|
+
function trackClickEvent (evt) {
|
|
14
|
+
var $link = getLinkFromEvent(evt)
|
|
15
|
+
var options = { transport: 'beacon' }
|
|
16
|
+
var href = $link.attr('href')
|
|
17
|
+
var linkText = $.trim($link.text())
|
|
18
|
+
|
|
19
|
+
if (linkText) {
|
|
20
|
+
options.label = linkText
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
GOVUK.analytics.trackEvent('Mailto Link Clicked', href, options)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function getLinkFromEvent (evt) {
|
|
27
|
+
var $target = $(evt.target)
|
|
28
|
+
|
|
29
|
+
if (!$target.is('a')) {
|
|
30
|
+
$target = $target.parents('a')
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return $target
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
global.GOVUK = GOVUK
|
|
38
|
+
})(window)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// Extension to monitor attempts to print pages.
|
|
2
|
+
;(function (global) {
|
|
3
|
+
'use strict'
|
|
4
|
+
|
|
5
|
+
var GOVUK = global.GOVUK || {}
|
|
6
|
+
|
|
7
|
+
GOVUK.analyticsPlugins = GOVUK.analyticsPlugins || {}
|
|
8
|
+
|
|
9
|
+
GOVUK.analyticsPlugins.printIntent = function () {
|
|
10
|
+
var printAttempt = function () {
|
|
11
|
+
GOVUK.analytics.trackEvent('Print Intent', document.location.pathname)
|
|
12
|
+
GOVUK.analytics.trackPageview('/print' + document.location.pathname)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Most browsers
|
|
16
|
+
if (global.matchMedia) {
|
|
17
|
+
var mediaQueryList = global.matchMedia('print')
|
|
18
|
+
var mqlListenerCount = 0
|
|
19
|
+
mediaQueryList.addListener(function (mql) {
|
|
20
|
+
if (!mql.matches && mqlListenerCount === 0) {
|
|
21
|
+
printAttempt()
|
|
22
|
+
mqlListenerCount++
|
|
23
|
+
// If we try and print again within 3 seconds, don't log it
|
|
24
|
+
setTimeout(function () {
|
|
25
|
+
mqlListenerCount = 0
|
|
26
|
+
// printing will be tracked again now
|
|
27
|
+
}, 3000)
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// IE < 10
|
|
33
|
+
if (global.onafterprint) {
|
|
34
|
+
global.onafterprint = printAttempt
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
global.GOVUK = GOVUK
|
|
39
|
+
})(window)
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
// <details> polyfill
|
|
2
|
+
// http://caniuse.com/#feat=details
|
|
3
|
+
|
|
4
|
+
// FF Support for HTML5's <details> and <summary>
|
|
5
|
+
// https://bugzilla.mozilla.org/show_bug.cgi?id=591737
|
|
6
|
+
|
|
7
|
+
// http://www.sitepoint.com/fixing-the-details-element/
|
|
8
|
+
|
|
9
|
+
;(function (global) {
|
|
10
|
+
'use strict'
|
|
11
|
+
|
|
12
|
+
var GOVUK = global.GOVUK || {}
|
|
13
|
+
|
|
14
|
+
GOVUK.details = {
|
|
15
|
+
NATIVE_DETAILS: typeof document.createElement('details').open === 'boolean',
|
|
16
|
+
KEY_ENTER: 13,
|
|
17
|
+
KEY_SPACE: 32,
|
|
18
|
+
|
|
19
|
+
// Create a started flag so we can prevent the initialisation
|
|
20
|
+
// function firing from both DOMContentLoaded and window.onload
|
|
21
|
+
started: false,
|
|
22
|
+
|
|
23
|
+
// Add event construct for modern browsers or IE
|
|
24
|
+
// which fires the callback with a pre-converted target reference
|
|
25
|
+
addEvent: function (node, type, callback) {
|
|
26
|
+
if (node.addEventListener) {
|
|
27
|
+
node.addEventListener(type, function (e) {
|
|
28
|
+
callback(e, e.target)
|
|
29
|
+
}, false)
|
|
30
|
+
} else if (node.attachEvent) {
|
|
31
|
+
node.attachEvent('on' + type, function (e) {
|
|
32
|
+
callback(e, e.srcElement)
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
removeEvent: function (node, type) {
|
|
38
|
+
if (node.removeEventListener) {
|
|
39
|
+
node.removeEventListener(type, function (e) {
|
|
40
|
+
}, false)
|
|
41
|
+
} else if (node.detachEvent) {
|
|
42
|
+
node.detachEvent('on' + type, function (e) {
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
// Cross-browser character code / key pressed
|
|
48
|
+
charCode: function (e) {
|
|
49
|
+
return (typeof e.which === 'number') ? e.which : e.keyCode
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
// Cross-browser preventing default action
|
|
53
|
+
preventDefault: function (e) {
|
|
54
|
+
if (e.preventDefault) {
|
|
55
|
+
e.preventDefault()
|
|
56
|
+
} else {
|
|
57
|
+
e.returnValue = false
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
// Handle cross-modal click events
|
|
62
|
+
addClickEvent: function (node, callback) {
|
|
63
|
+
GOVUK.details.addEvent(node, 'keypress', function (e, target) {
|
|
64
|
+
// When the key gets pressed - check if it is enter or space
|
|
65
|
+
if (GOVUK.details.charCode(e) === GOVUK.details.KEY_ENTER || GOVUK.details.charCode(e) === GOVUK.details.KEY_SPACE) {
|
|
66
|
+
if (target.nodeName.toLowerCase() === 'summary') {
|
|
67
|
+
// Prevent space from scrolling the page
|
|
68
|
+
// and enter from submitting a form
|
|
69
|
+
GOVUK.details.preventDefault(e)
|
|
70
|
+
// Click to let the click event do all the necessary action
|
|
71
|
+
if (target.click) {
|
|
72
|
+
target.click()
|
|
73
|
+
} else {
|
|
74
|
+
// except Safari 5.1 and under don't support .click() here
|
|
75
|
+
callback(e, target)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
// Prevent keyup to prevent clicking twice in Firefox when using space key
|
|
82
|
+
GOVUK.details.addEvent(node, 'keyup', function (e, target) {
|
|
83
|
+
if (GOVUK.details.charCode(e) === GOVUK.details.KEY_SPACE) {
|
|
84
|
+
if (target.nodeName === 'SUMMARY') {
|
|
85
|
+
GOVUK.details.preventDefault(e)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
GOVUK.details.addEvent(node, 'click', function (e, target) {
|
|
91
|
+
callback(e, target)
|
|
92
|
+
})
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
// Get the nearest ancestor element of a node that matches a given tag name
|
|
96
|
+
getAncestor: function (node, match) {
|
|
97
|
+
do {
|
|
98
|
+
if (!node || node.nodeName.toLowerCase() === match) {
|
|
99
|
+
break
|
|
100
|
+
}
|
|
101
|
+
node = node.parentNode
|
|
102
|
+
} while (node)
|
|
103
|
+
|
|
104
|
+
return node
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
// Initialisation function
|
|
108
|
+
addDetailsPolyfill: function (list, container) {
|
|
109
|
+
container = container || document.body
|
|
110
|
+
// If this has already happened, just return
|
|
111
|
+
// else set the flag so it doesn't happen again
|
|
112
|
+
if (GOVUK.details.started) {
|
|
113
|
+
return
|
|
114
|
+
}
|
|
115
|
+
GOVUK.details.started = true
|
|
116
|
+
// Get the collection of details elements, but if that's empty
|
|
117
|
+
// then we don't need to bother with the rest of the scripting
|
|
118
|
+
if ((list = container.getElementsByTagName('details')).length === 0) {
|
|
119
|
+
return
|
|
120
|
+
}
|
|
121
|
+
// else iterate through them to apply their initial state
|
|
122
|
+
var n = list.length
|
|
123
|
+
var i = 0
|
|
124
|
+
for (i; i < n; i++) {
|
|
125
|
+
var details = list[i]
|
|
126
|
+
|
|
127
|
+
// Save shortcuts to the inner summary and content elements
|
|
128
|
+
details.__summary = details.getElementsByTagName('summary').item(0)
|
|
129
|
+
details.__content = details.getElementsByTagName('div').item(0)
|
|
130
|
+
|
|
131
|
+
if (!details.__summary || !details.__content) {
|
|
132
|
+
return
|
|
133
|
+
}
|
|
134
|
+
// If the content doesn't have an ID, assign it one now
|
|
135
|
+
// which we'll need for the summary's aria-controls assignment
|
|
136
|
+
if (!details.__content.id) {
|
|
137
|
+
details.__content.id = 'details-content-' + i
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Add ARIA role="group" to details
|
|
141
|
+
details.setAttribute('role', 'group')
|
|
142
|
+
|
|
143
|
+
// Add role=button to summary
|
|
144
|
+
details.__summary.setAttribute('role', 'button')
|
|
145
|
+
|
|
146
|
+
// Add aria-controls
|
|
147
|
+
details.__summary.setAttribute('aria-controls', details.__content.id)
|
|
148
|
+
|
|
149
|
+
// Set tabIndex so the summary is keyboard accessible for non-native elements
|
|
150
|
+
// http://www.saliences.com/browserBugs/tabIndex.html
|
|
151
|
+
if (!GOVUK.details.NATIVE_DETAILS) {
|
|
152
|
+
details.__summary.tabIndex = 0
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Detect initial open state
|
|
156
|
+
var openAttr = details.getAttribute('open') !== null
|
|
157
|
+
if (openAttr === true) {
|
|
158
|
+
details.__summary.setAttribute('aria-expanded', 'true')
|
|
159
|
+
details.__content.setAttribute('aria-hidden', 'false')
|
|
160
|
+
} else {
|
|
161
|
+
details.__summary.setAttribute('aria-expanded', 'false')
|
|
162
|
+
details.__content.setAttribute('aria-hidden', 'true')
|
|
163
|
+
if (!GOVUK.details.NATIVE_DETAILS) {
|
|
164
|
+
details.__content.style.display = 'none'
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Create a circular reference from the summary back to its
|
|
169
|
+
// parent details element, for convenience in the click handler
|
|
170
|
+
details.__summary.__details = details
|
|
171
|
+
|
|
172
|
+
// If this is not a native implementation, create an arrow
|
|
173
|
+
// inside the summary
|
|
174
|
+
if (!GOVUK.details.NATIVE_DETAILS) {
|
|
175
|
+
var twisty = document.createElement('i')
|
|
176
|
+
|
|
177
|
+
if (openAttr === true) {
|
|
178
|
+
twisty.className = 'arrow arrow-open'
|
|
179
|
+
twisty.appendChild(document.createTextNode('\u25bc'))
|
|
180
|
+
} else {
|
|
181
|
+
twisty.className = 'arrow arrow-closed'
|
|
182
|
+
twisty.appendChild(document.createTextNode('\u25ba'))
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
details.__summary.__twisty = details.__summary.insertBefore(twisty, details.__summary.firstChild)
|
|
186
|
+
details.__summary.__twisty.setAttribute('aria-hidden', 'true')
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Bind a click event to handle summary elements
|
|
191
|
+
GOVUK.details.addClickEvent(container, function (e, summary) {
|
|
192
|
+
if (!(summary = GOVUK.details.getAncestor(summary, 'summary'))) {
|
|
193
|
+
return true
|
|
194
|
+
}
|
|
195
|
+
return GOVUK.details.statechange(summary)
|
|
196
|
+
})
|
|
197
|
+
},
|
|
198
|
+
|
|
199
|
+
// Define a statechange function that updates aria-expanded and style.display
|
|
200
|
+
// Also update the arrow position
|
|
201
|
+
statechange: function (summary) {
|
|
202
|
+
var expanded = summary.__details.__summary.getAttribute('aria-expanded') === 'true'
|
|
203
|
+
var hidden = summary.__details.__content.getAttribute('aria-hidden') === 'true'
|
|
204
|
+
|
|
205
|
+
summary.__details.__summary.setAttribute('aria-expanded', (expanded ? 'false' : 'true'))
|
|
206
|
+
summary.__details.__content.setAttribute('aria-hidden', (hidden ? 'false' : 'true'))
|
|
207
|
+
|
|
208
|
+
if (!GOVUK.details.NATIVE_DETAILS) {
|
|
209
|
+
summary.__details.__content.style.display = (expanded ? 'none' : '')
|
|
210
|
+
|
|
211
|
+
var hasOpenAttr = summary.__details.getAttribute('open') !== null
|
|
212
|
+
if (!hasOpenAttr) {
|
|
213
|
+
summary.__details.setAttribute('open', 'open')
|
|
214
|
+
} else {
|
|
215
|
+
summary.__details.removeAttribute('open')
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (summary.__twisty) {
|
|
220
|
+
summary.__twisty.firstChild.nodeValue = (expanded ? '\u25ba' : '\u25bc')
|
|
221
|
+
summary.__twisty.setAttribute('class', (expanded ? 'arrow arrow-closed' : 'arrow arrow-open'))
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return true
|
|
225
|
+
},
|
|
226
|
+
|
|
227
|
+
destroy: function (node) {
|
|
228
|
+
GOVUK.details.removeEvent(node, 'click')
|
|
229
|
+
},
|
|
230
|
+
|
|
231
|
+
// Bind two load events for modern and older browsers
|
|
232
|
+
// If the first one fires it will set a flag to block the second one
|
|
233
|
+
// but if it's not supported then the second one will fire
|
|
234
|
+
init: function ($container) {
|
|
235
|
+
GOVUK.details.addEvent(document, 'DOMContentLoaded', GOVUK.details.addDetailsPolyfill)
|
|
236
|
+
GOVUK.details.addEvent(window, 'load', GOVUK.details.addDetailsPolyfill)
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
global.GOVUK = GOVUK
|
|
240
|
+
})(window)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
;(function (global) {
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
var GOVUK = global.GOVUK || {}
|
|
5
|
+
GOVUK.Modules = GOVUK.Modules || {}
|
|
6
|
+
|
|
7
|
+
GOVUK.Modules.AutoTrackEvent = function () {
|
|
8
|
+
this.start = function (element) {
|
|
9
|
+
var options = { nonInteraction: 1 } // automatic events shouldn't affect bounce rate
|
|
10
|
+
var category = element.data('track-category')
|
|
11
|
+
var action = element.data('track-action')
|
|
12
|
+
var label = element.data('track-label')
|
|
13
|
+
var value = element.data('track-value')
|
|
14
|
+
|
|
15
|
+
if (typeof label === 'string') {
|
|
16
|
+
options.label = label
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (value || value === 0) {
|
|
20
|
+
options.value = value
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (GOVUK.analytics && GOVUK.analytics.trackEvent) {
|
|
24
|
+
GOVUK.analytics.trackEvent(category, action, options)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
global.GOVUK = GOVUK
|
|
30
|
+
})(window)
|