jumbo-jekyll-theme 2.2.0 → 2.2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (239) hide show
  1. checksums.yaml +4 -4
  2. data/_config.yml +3 -0
  3. metadata +19 -241
  4. data/_data/authors.yml +0 -7
  5. data/_data/footer.yml +0 -55
  6. data/_data/nav.yml +0 -77
  7. data/_data/news.yaml +0 -230
  8. data/_data/settings.yml +0 -148
  9. data/_data/sidebar-nav.yml +0 -23
  10. data/_data/sticky-tab-bar.yml +0 -29
  11. data/_includes/breadcrumb.html +0 -97
  12. data/_includes/css.html +0 -9
  13. data/_includes/custom.html +0 -1
  14. data/_includes/display-blog-posts.html +0 -67
  15. data/_includes/disqus-comments.html +0 -14
  16. data/_includes/footer.html +0 -70
  17. data/_includes/github-edit.html +0 -73
  18. data/_includes/google-analytics-script.html +0 -9
  19. data/_includes/gtm-noscript.html +0 -5
  20. data/_includes/gtm-script.html +0 -7
  21. data/_includes/head.html +0 -44
  22. data/_includes/hero-banner.html +0 -21
  23. data/_includes/image.html +0 -6
  24. data/_includes/javascript.html +0 -9
  25. data/_includes/jumbotron.html +0 -87
  26. data/_includes/linaro-404.html +0 -13
  27. data/_includes/linaro-svg.html +0 -1
  28. data/_includes/media.html +0 -11
  29. data/_includes/members.html +0 -63
  30. data/_includes/nav.html +0 -132
  31. data/_includes/newsletter-script.html +0 -30
  32. data/_includes/owl-carousel-homepage.html +0 -103
  33. data/_includes/pagination-authors.html +0 -36
  34. data/_includes/pagination-news.html +0 -36
  35. data/_includes/pagination.html +0 -36
  36. data/_includes/post-comments.html +0 -9
  37. data/_includes/post-sidebar.html +0 -74
  38. data/_includes/post-tags.html +0 -9
  39. data/_includes/schema.html +0 -50
  40. data/_includes/shape-divider.html +0 -12
  41. data/_includes/shape.html +0 -52
  42. data/_includes/sidebar.html +0 -55
  43. data/_includes/sticky-tab-bar.html +0 -63
  44. data/_includes/universal-nav.html +0 -28
  45. data/_includes/youtube.html +0 -7
  46. data/_layouts/container-breadcrumb-left-sidebar.html +0 -10
  47. data/_layouts/container-breadcrumb-right-sidebar.html +0 -9
  48. data/_layouts/container-breadcrumb-tabs.html +0 -7
  49. data/_layouts/container-breadcrumb.html +0 -6
  50. data/_layouts/container-left-sidebar.html +0 -9
  51. data/_layouts/container-right-sidebar.html +0 -9
  52. data/_layouts/container.html +0 -9
  53. data/_layouts/default.html +0 -29
  54. data/_layouts/full-width-breadcrumb.html +0 -10
  55. data/_layouts/full-width.html +0 -9
  56. data/_layouts/home.html +0 -21
  57. data/_layouts/post-index.html +0 -19
  58. data/_layouts/post-no-sidebar.html +0 -0
  59. data/_layouts/post-old.html +0 -70
  60. data/_layouts/post.html +0 -240
  61. data/_sass/_bootstrap-compass.scss +0 -9
  62. data/_sass/_bootstrap-mincer.scss +0 -19
  63. data/_sass/_bootstrap-sprockets.scss +0 -9
  64. data/_sass/_bootstrap.scss +0 -56
  65. data/_sass/app/blog.scss +0 -58
  66. data/_sass/app/contact.scss +0 -3
  67. data/_sass/app/custom.scss +0 -1
  68. data/_sass/app/fly.scss +0 -10
  69. data/_sass/app/home.scss +0 -18
  70. data/_sass/app/overrides.scss +0 -36
  71. data/_sass/app/search.scss +0 -1
  72. data/_sass/blog.scss +0 -9
  73. data/_sass/bootstrap/_alerts.scss +0 -73
  74. data/_sass/bootstrap/_badges.scss +0 -68
  75. data/_sass/bootstrap/_breadcrumbs.scss +0 -28
  76. data/_sass/bootstrap/_button-groups.scss +0 -244
  77. data/_sass/bootstrap/_buttons.scss +0 -168
  78. data/_sass/bootstrap/_carousel.scss +0 -270
  79. data/_sass/bootstrap/_close.scss +0 -36
  80. data/_sass/bootstrap/_code.scss +0 -69
  81. data/_sass/bootstrap/_component-animations.scss +0 -37
  82. data/_sass/bootstrap/_dropdowns.scss +0 -216
  83. data/_sass/bootstrap/_forms.scss +0 -617
  84. data/_sass/bootstrap/_glyphicons.scss +0 -307
  85. data/_sass/bootstrap/_grid.scss +0 -84
  86. data/_sass/bootstrap/_input-groups.scss +0 -171
  87. data/_sass/bootstrap/_jumbotron.scss +0 -54
  88. data/_sass/bootstrap/_labels.scss +0 -66
  89. data/_sass/bootstrap/_list-group.scss +0 -130
  90. data/_sass/bootstrap/_media.scss +0 -66
  91. data/_sass/bootstrap/_mixins.scss +0 -40
  92. data/_sass/bootstrap/_modals.scss +0 -150
  93. data/_sass/bootstrap/_navbar.scss +0 -662
  94. data/_sass/bootstrap/_navs.scss +0 -242
  95. data/_sass/bootstrap/_normalize.scss +0 -424
  96. data/_sass/bootstrap/_pager.scss +0 -54
  97. data/_sass/bootstrap/_pagination.scss +0 -89
  98. data/_sass/bootstrap/_panels.scss +0 -271
  99. data/_sass/bootstrap/_popovers.scss +0 -131
  100. data/_sass/bootstrap/_print.scss +0 -101
  101. data/_sass/bootstrap/_progress-bars.scss +0 -87
  102. data/_sass/bootstrap/_responsive-embed.scss +0 -35
  103. data/_sass/bootstrap/_responsive-utilities.scss +0 -179
  104. data/_sass/bootstrap/_scaffolding.scss +0 -161
  105. data/_sass/bootstrap/_tables.scss +0 -234
  106. data/_sass/bootstrap/_theme.scss +0 -291
  107. data/_sass/bootstrap/_thumbnails.scss +0 -38
  108. data/_sass/bootstrap/_tooltip.scss +0 -101
  109. data/_sass/bootstrap/_type.scss +0 -298
  110. data/_sass/bootstrap/_utilities.scss +0 -55
  111. data/_sass/bootstrap/_variables.scss +0 -922
  112. data/_sass/bootstrap/_wells.scss +0 -29
  113. data/_sass/bootstrap/mixins/_alerts.scss +0 -14
  114. data/_sass/bootstrap/mixins/_background-variant.scss +0 -12
  115. data/_sass/bootstrap/mixins/_border-radius.scss +0 -18
  116. data/_sass/bootstrap/mixins/_buttons.scss +0 -65
  117. data/_sass/bootstrap/mixins/_center-block.scss +0 -7
  118. data/_sass/bootstrap/mixins/_clearfix.scss +0 -22
  119. data/_sass/bootstrap/mixins/_forms.scss +0 -88
  120. data/_sass/bootstrap/mixins/_gradients.scss +0 -58
  121. data/_sass/bootstrap/mixins/_grid-framework.scss +0 -81
  122. data/_sass/bootstrap/mixins/_grid.scss +0 -122
  123. data/_sass/bootstrap/mixins/_hide-text.scss +0 -21
  124. data/_sass/bootstrap/mixins/_image.scss +0 -33
  125. data/_sass/bootstrap/mixins/_labels.scss +0 -12
  126. data/_sass/bootstrap/mixins/_list-group.scss +0 -32
  127. data/_sass/bootstrap/mixins/_nav-divider.scss +0 -10
  128. data/_sass/bootstrap/mixins/_nav-vertical-align.scss +0 -9
  129. data/_sass/bootstrap/mixins/_opacity.scss +0 -8
  130. data/_sass/bootstrap/mixins/_pagination.scss +0 -24
  131. data/_sass/bootstrap/mixins/_panels.scss +0 -24
  132. data/_sass/bootstrap/mixins/_progress-bar.scss +0 -10
  133. data/_sass/bootstrap/mixins/_reset-filter.scss +0 -8
  134. data/_sass/bootstrap/mixins/_reset-text.scss +0 -18
  135. data/_sass/bootstrap/mixins/_resize.scss +0 -6
  136. data/_sass/bootstrap/mixins/_responsive-visibility.scss +0 -21
  137. data/_sass/bootstrap/mixins/_size.scss +0 -10
  138. data/_sass/bootstrap/mixins/_tab-focus.scss +0 -9
  139. data/_sass/bootstrap/mixins/_table-row.scss +0 -28
  140. data/_sass/bootstrap/mixins/_text-emphasis.scss +0 -12
  141. data/_sass/bootstrap/mixins/_text-overflow.scss +0 -8
  142. data/_sass/bootstrap/mixins/_vendor-prefixes.scss +0 -222
  143. data/_sass/core.scss +0 -12
  144. data/_sass/core/404.scss +0 -189
  145. data/_sass/core/animations.scss +0 -125
  146. data/_sass/core/blog.scss +0 -441
  147. data/_sass/core/breadcrumb.scss +0 -97
  148. data/_sass/core/carousel-styles.scss +0 -3
  149. data/_sass/core/carousel.scss +0 -318
  150. data/_sass/core/cookieconsent.scss +0 -42
  151. data/_sass/core/critical.scss +0 -0
  152. data/_sass/core/custom.scss +0 -3
  153. data/_sass/core/fa.scss +0 -2336
  154. data/_sass/core/flipclock.scss +0 -434
  155. data/_sass/core/font-awesome.min.scss +0 -4
  156. data/_sass/core/fonts.scss +0 -3
  157. data/_sass/core/footer.scss +0 -169
  158. data/_sass/core/forms.scss +0 -3
  159. data/_sass/core/homepage.scss +0 -106
  160. data/_sass/core/jumbotron.scss +0 -51
  161. data/_sass/core/lightbox.scss +0 -212
  162. data/_sass/core/nav.scss +0 -971
  163. data/_sass/core/owl.carousel.min.scss +0 -6
  164. data/_sass/core/owl.theme.default.min.scss +0 -6
  165. data/_sass/core/social-media-icons.scss +0 -67
  166. data/_sass/core/syntax.scss +0 -65
  167. data/_sass/core/tables.scss +0 -145
  168. data/_sass/core/theme.scss +0 -630
  169. data/_sass/core/twitter-feed.scss +0 -414
  170. data/_sass/core/universal-nav.scss +0 -154
  171. data/_sass/core/youtube.scss +0 -65
  172. data/_sass/home.scss +0 -6
  173. data/assets/css/main-404.scss +0 -18
  174. data/assets/css/main-blog.scss +0 -19
  175. data/assets/css/main-contact.scss +0 -23
  176. data/assets/css/main-home.scss +0 -22
  177. data/assets/css/main-lightbox.scss +0 -29
  178. data/assets/css/main-search.scss +0 -13
  179. data/assets/css/main.scss +0 -12
  180. data/assets/fonts/fontawesome-webfont.eot +0 -0
  181. data/assets/fonts/fontawesome-webfont.svg +0 -2671
  182. data/assets/fonts/fontawesome-webfont.ttf +0 -0
  183. data/assets/fonts/fontawesome-webfont.woff +0 -0
  184. data/assets/fonts/fontawesome-webfont.woff2 +0 -0
  185. data/assets/fonts/fontello.eot +0 -0
  186. data/assets/fonts/fontello.svg +0 -44
  187. data/assets/fonts/glyphicons-halflings-regular.ttf +0 -0
  188. data/assets/fonts/glyphicons-halflings-regular.woff +0 -0
  189. data/assets/fonts/glyphicons-halflings-regular.woff2 +0 -0
  190. data/assets/fonts/lato-regular/LICENSE.txt +0 -93
  191. data/assets/fonts/lato-regular/Lato-regular.eot +0 -0
  192. data/assets/fonts/lato-regular/Lato-regular.svg +0 -435
  193. data/assets/fonts/lato-regular/Lato-regular.ttf +0 -0
  194. data/assets/fonts/lato-regular/Lato-regular.woff +0 -0
  195. data/assets/fonts/lato-regular/Lato-regular.woff2 +0 -0
  196. data/assets/images/Linaro-Logo.svg +0 -1
  197. data/assets/images/Linaro-Logo_light.png +0 -0
  198. data/assets/images/Linaro-Logo_standard.svg +0 -1
  199. data/assets/images/Linaro-Sprinkle.png +0 -0
  200. data/assets/images/avatar-placeholder.png +0 -0
  201. data/assets/images/background-image.jpg +0 -0
  202. data/assets/images/banner.jpg +0 -0
  203. data/assets/images/breadcrumb-image.jpg +0 -0
  204. data/assets/images/close.png +0 -0
  205. data/assets/images/favicon.ico +0 -0
  206. data/assets/images/favicon.png +0 -0
  207. data/assets/images/loading.gif +0 -0
  208. data/assets/images/next.png +0 -0
  209. data/assets/images/owl.video.play.png +0 -0
  210. data/assets/images/placeholder.png +0 -0
  211. data/assets/images/prev.png +0 -0
  212. data/assets/images/social-media-image.png +0 -0
  213. data/assets/js/app/custom.js +0 -0
  214. data/assets/js/app/facebook.js +0 -8
  215. data/assets/js/app/fly.js +0 -45
  216. data/assets/js/app/home.js +0 -46
  217. data/assets/js/app/main.js +0 -143
  218. data/assets/js/app/scroll-to-anchors.js +0 -10
  219. data/assets/js/app/sticky-tab-bar.js +0 -72
  220. data/assets/js/app/tables.js +0 -35
  221. data/assets/js/package-blog.js +0 -10
  222. data/assets/js/package-extended.js +0 -14
  223. data/assets/js/package-home.js +0 -12
  224. data/assets/js/package-main.js +0 -10
  225. data/assets/js/package-search.js +0 -8
  226. data/assets/js/vendor/bootstrap.js +0 -2377
  227. data/assets/js/vendor/cognito.js +0 -11
  228. data/assets/js/vendor/cookieconsent.js +0 -1504
  229. data/assets/js/vendor/jquery.js +0 -10364
  230. data/assets/js/vendor/jquery.rss.js +0 -333
  231. data/assets/js/vendor/jquery.validate.js +0 -1601
  232. data/assets/js/vendor/lazysizes.js +0 -698
  233. data/assets/js/vendor/lightbox.js +0 -523
  234. data/assets/js/vendor/loadCSS.js +0 -35
  235. data/assets/js/vendor/ls.unveilhooks.js +0 -145
  236. data/assets/js/vendor/mc.js +0 -255
  237. data/assets/js/vendor/owl.carousel.js +0 -3475
  238. data/assets/js/vendor/picturefill.js +0 -1471
  239. data/assets/js/vendor/shuffle.js +0 -2004
@@ -1,11 +0,0 @@
1
- (function(){function r(){for(var t,i=arguments[0],n=1;n<arguments.length;n++)for(t in arguments[n])arguments[n].hasOwnProperty(t)&&(i[t]=arguments[n][t]);return i}var e,o,n,t,s,i,u,f;window.console=window.console||{log:function(){}};e=null;o=null;window.Cognito=window.Cognito||{};window.Cognito.deferredLoad=undefined;Cognito.sessionInit=function(){Cognito.deferredLoad&&Cognito.deferredLoad()};Cognito.config=r({},Cognito.config,{instanceId:636491919541478436,organizationCode:"Linaro1",sessionToken:"rUY5XaLmcsRUbGFmd3Dw+7R5tSE51S3tWLROcptdD2EmsW/mbwWmhfBHYvqb7YKr6yuTLSClwhuPcqzu4fv5TjXyFJw=",baseUrl:"https://services.cognitoforms.com/",mode:"public",maxClientErrors:15,cacheHash:"-322828110",key:"9850f42a-f689-4b76-ba93-a8063fbd758f",version:"0.01"});Cognito.resources=r({},Cognito.resources);n=document.getElementsByTagName("head")[0]||document.getElementsByTagName("body")[0];document.querySelectorAll("script[src*='include/req/']").length===0&&(window.Cognito.load=function(){var n=arguments;window.Cognito.deferredLoad=function(){Cognito.load.apply(Cognito,n)}},t=document.createElement("script"),t.type="text/javascript",t.async=!1,s=!1,n.insertBefore(t,n.firstChild),t.src="https://services.cognitoforms.com/include/req/-322828110");document.querySelectorAll("link[href*=requiredcss]").length===0&&(i=document.createElement("link"),i.type="text/css",i.rel="stylesheet",i.href="https://services.cognitoforms.com/include/requiredcss/-322828110",n.insertBefore(i,n.firstChild));u=window.addEventListener?"addEventListener":"attachEvent";f=window.addEventListener?"load":"onload";window[u](f,function(){if(window.ExoJQuery===undefined){var n=XMLHttpRequest?new XMLHttpRequest:new ActiveXObject("Microsoft.XMLHTTP");n.open("POST","https://services.cognitoforms.com/error",!0);n.setRequestHeader("Content-type","application/json");n.send(JSON.stringify({message:"Requred scripts not loaded ("+Cognito.config.organizationCode+")",type:"Error",url:document.location.href,refererUrl:document.referrer}))}})})()
2
-
3
-
4
-
5
- $(document).ready(function(){
6
- Cognito.load("forms", { id: "7", entry: {
7
- "PageUrl": "{{site.url}}{{page.url}}" ,
8
- "RedirectUrl" : "{{site.url}}/thank-you/?ref={{page.url}}"
9
- }});
10
-
11
- });
@@ -1,1504 +0,0 @@
1
- (function(cc) {
2
- // stop from running again, if accidently included more than once.
3
- if (cc.hasInitialised) return;
4
-
5
- var util = {
6
- // http://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex
7
- escapeRegExp: function(str) {
8
- return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
9
- },
10
-
11
- hasClass: function(element, selector) {
12
- var s = ' ';
13
- return element.nodeType === 1 &&
14
- (s + element.className + s).replace(/[\n\t]/g, s).indexOf(s + selector + s) >= 0;
15
- },
16
-
17
- addClass: function(element, className) {
18
- element.className += ' ' + className;
19
- },
20
-
21
- removeClass: function(element, className) {
22
- var regex = new RegExp('\\b' + this.escapeRegExp(className) + '\\b');
23
- element.className = element.className.replace(regex, '');
24
- },
25
-
26
- interpolateString: function(str, callback) {
27
- var marker = /{{([a-z][a-z0-9\-_]*)}}/ig;
28
- return str.replace(marker, function(matches) {
29
- return callback(arguments[1]) || '';
30
- })
31
- },
32
-
33
- getCookie: function(name) {
34
- var value = '; ' + document.cookie;
35
- var parts = value.split('; ' + name + '=');
36
- return parts.length != 2 ?
37
- undefined : parts.pop().split(';').shift();
38
- },
39
-
40
- setCookie: function(name, value, expiryDays, domain, path) {
41
- var exdate = new Date();
42
- exdate.setDate(exdate.getDate() + (expiryDays || 365));
43
-
44
- var cookie = [
45
- name + '=' + value,
46
- 'expires=' + exdate.toUTCString(),
47
- 'path=' + (path || '/')
48
- ];
49
-
50
- if (domain) {
51
- cookie.push('domain=' + domain);
52
- }
53
- document.cookie = cookie.join(';');
54
- },
55
-
56
- // only used for extending the initial options
57
- deepExtend: function(target, source) {
58
- for (var prop in source) {
59
- if (source.hasOwnProperty(prop)) {
60
- if (prop in target && this.isPlainObject(target[prop]) && this.isPlainObject(source[prop])) {
61
- this.deepExtend(target[prop], source[prop]);
62
- } else {
63
- target[prop] = source[prop];
64
- }
65
- }
66
- }
67
- return target;
68
- },
69
-
70
- // only used for throttling the 'mousemove' event (used for animating the revoke button when `animateRevokable` is true)
71
- throttle: function(callback, limit) {
72
- var wait = false;
73
- return function() {
74
- if (!wait) {
75
- callback.apply(this, arguments);
76
- wait = true;
77
- setTimeout(function() {
78
- wait = false;
79
- }, limit);
80
- }
81
- }
82
- },
83
-
84
- // only used for hashing json objects (used for hash mapping palette objects, used when custom colours are passed through JavaScript)
85
- hash: function(str) {
86
- var hash = 0,
87
- i, chr, len;
88
- if (str.length === 0) return hash;
89
- for (i = 0, len = str.length; i < len; ++i) {
90
- chr = str.charCodeAt(i);
91
- hash = ((hash << 5) - hash) + chr;
92
- hash |= 0;
93
- }
94
- return hash;
95
- },
96
-
97
- normaliseHex: function(hex) {
98
- if (hex[0] == '#') {
99
- hex = hex.substr(1);
100
- }
101
- if (hex.length == 3) {
102
- hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
103
- }
104
- return hex;
105
- },
106
-
107
- // used to get text colors if not set
108
- getContrast: function(hex) {
109
- hex = this.normaliseHex(hex);
110
- var r = parseInt(hex.substr(0, 2), 16);
111
- var g = parseInt(hex.substr(2, 2), 16);
112
- var b = parseInt(hex.substr(4, 2), 16);
113
- var yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;
114
- return (yiq >= 128) ? '#000' : '#fff';
115
- },
116
-
117
- // used to change color on highlight
118
- getLuminance: function(hex) {
119
- var num = parseInt(this.normaliseHex(hex), 16),
120
- amt = 38,
121
- R = (num >> 16) + amt,
122
- B = (num >> 8 & 0x00FF) + amt,
123
- G = (num & 0x0000FF) + amt;
124
- var newColour = (0x1000000 + (R<255?R<1?0:R:255)*0x10000 + (B<255?B<1?0:B:255)*0x100 + (G<255?G<1?0:G:255)).toString(16).slice(1);
125
- return '#'+newColour;
126
- },
127
-
128
- isMobile: function() {
129
- return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
130
- },
131
-
132
- isPlainObject: function(obj) {
133
- // The code "typeof obj === 'object' && obj !== null" allows Array objects
134
- return typeof obj === 'object' && obj !== null && obj.constructor == Object;
135
- },
136
- };
137
-
138
- // valid cookie values
139
- cc.status = {
140
- deny: 'deny',
141
- allow: 'allow',
142
- dismiss: 'dismiss'
143
- };
144
-
145
- // detects the `transitionend` event name
146
- cc.transitionEnd = (function() {
147
- var el = document.createElement('div');
148
- var trans = {
149
- t: "transitionend",
150
- OT: "oTransitionEnd",
151
- msT: "MSTransitionEnd",
152
- MozT: "transitionend",
153
- WebkitT: "webkitTransitionEnd",
154
- };
155
-
156
- for (var prefix in trans) {
157
- if (trans.hasOwnProperty(prefix) && typeof el.style[prefix + 'ransition'] != 'undefined') {
158
- return trans[prefix];
159
- }
160
- }
161
- return '';
162
- }());
163
-
164
- cc.hasTransition = !!cc.transitionEnd;
165
-
166
- // array of valid regexp escaped statuses
167
- var __allowedStatuses = Object.keys(cc.status).map(util.escapeRegExp);
168
-
169
- // contains references to the custom <style> tags
170
- cc.customStyles = {};
171
-
172
- cc.Popup = (function() {
173
-
174
- var defaultOptions = {
175
-
176
- // if false, this prevents the popup from showing (useful for giving to control to another piece of code)
177
- enabled: true,
178
-
179
- // optional (expecting a HTML element) if passed, the popup is appended to this element. default is `document.body`
180
- container: null,
181
-
182
- // defaults cookie options - it is RECOMMENDED to set these values to correspond with your server
183
- cookie: {
184
- // This is the name of this cookie - you can ignore this
185
- name: 'cookieconsent_status',
186
-
187
- // This is the url path that the cookie 'name' belongs to. The cookie can only be read at this location
188
- path: '/',
189
-
190
- // This is the domain that the cookie 'name' belongs to. The cookie can only be read on this domain.
191
- // - Guide to cookie domains - http://erik.io/blog/2014/03/04/definitive-guide-to-cookie-domains/
192
- domain: '',
193
-
194
- // The cookies expire date, specified in days (specify -1 for no expiry)
195
- expiryDays: 365,
196
- },
197
-
198
- // these callback hooks are called at certain points in the program execution
199
- onPopupOpen: function() {},
200
- onPopupClose: function() {},
201
- onInitialise: function(status) {},
202
- onStatusChange: function(status, chosenBefore) {},
203
- onRevokeChoice: function() {},
204
-
205
- // each item defines the inner text for the element that it references
206
- content: {
207
- header: 'Cookies used on the website!',
208
- message: 'This website uses cookies to ensure you get the best experience on our website.',
209
- dismiss: 'Got it!',
210
- allow: 'Allow cookies',
211
- deny: 'Decline',
212
- link: 'Learn more',
213
- href: 'http://cookiesandyou.com',
214
- close: '&#x274c;',
215
- },
216
-
217
- // This is the HTML for the elements above. The string {{header}} will be replaced with the equivalent text below.
218
- // You can remove "{{header}}" and write the content directly inside the HTML if you want.
219
- //
220
- // - ARIA rules suggest to ensure controls are tabbable (so the browser can find the first control),
221
- // and to set the focus to the first interactive control (http://w3c.github.io/aria-in-html/)
222
- elements: {
223
- header: '<span class="cc-header">{{header}}</span>&nbsp;',
224
- message: '<span id="cookieconsent:desc" class="cc-message">{{message}}</span>',
225
- messagelink: '<span id="cookieconsent:desc" class="cc-message">{{message}} <a aria-label="learn more about cookies" role=button tabindex="0" class="cc-link" href="{{href}}" rel="noopener noreferrer nofollow" target="_blank">{{link}}</a></span>',
226
- dismiss: '<a aria-label="dismiss cookie message" role=button tabindex="0" class="cc-btn cc-dismiss">{{dismiss}}</a>',
227
- allow: '<a aria-label="allow cookies" role=button tabindex="0" class="cc-btn cc-allow">{{allow}}</a>',
228
- deny: '<a aria-label="deny cookies" role=button tabindex="0" class="cc-btn cc-deny">{{deny}}</a>',
229
- link: '<a aria-label="learn more about cookies" role=button tabindex="0" class="cc-link" href="{{href}}" target="_blank">{{link}}</a>',
230
- close: '<span aria-label="dismiss cookie message" role=button tabindex="0" class="cc-close">{{close}}</span>',
231
-
232
- //compliance: compliance is also an element, but it is generated by the application, depending on `type` below
233
- },
234
-
235
- // The placeholders {{classes}} and {{children}} both get replaced during initialisation:
236
- // - {{classes}} is where additional classes get added
237
- // - {{children}} is where the HTML children are placed
238
- window: '<div role="dialog" aria-live="polite" aria-label="cookieconsent" aria-describedby="cookieconsent:desc" class="cc-window {{classes}}"><!--googleoff: all-->{{children}}<!--googleon: all--></div>',
239
-
240
- // This is the html for the revoke button. This only shows up after the user has selected their level of consent
241
- // It can be enabled of disabled using the `revokable` option
242
- revokeBtn: '<div class="cc-revoke {{classes}}">Cookie Policy</div>',
243
-
244
- // define types of 'compliance' here. '{{value}}' strings in here are linked to `elements`
245
- compliance: {
246
- 'info': '<div class="cc-compliance">{{dismiss}}</div>',
247
- 'opt-in': '<div class="cc-compliance cc-highlight">{{dismiss}}{{allow}}</div>',
248
- 'opt-out': '<div class="cc-compliance cc-highlight">{{deny}}{{dismiss}}</div>',
249
- },
250
-
251
- // select your type of popup here
252
- type: 'info', // refers to `compliance` (in other words, the buttons that are displayed)
253
-
254
- // define layout layouts here
255
- layouts: {
256
- // the 'block' layout tend to be for square floating popups
257
- 'basic': '{{messagelink}}{{compliance}}',
258
- 'basic-close': '{{messagelink}}{{compliance}}{{close}}',
259
- 'basic-header': '{{header}}{{message}}{{link}}{{compliance}}',
260
-
261
- // add a custom layout here, then add some new css with the class '.cc-layout-my-cool-layout'
262
- //'my-cool-layout': '<div class="my-special-layout">{{message}}{{compliance}}</div>{{close}}',
263
- },
264
-
265
- // default layout (see above)
266
- layout: 'basic',
267
-
268
- // this refers to the popup windows position. we currently support:
269
- // - banner positions: top, bottom
270
- // - floating positions: top-left, top-right, bottom-left, bottom-right
271
- //
272
- // adds a class `cc-floating` or `cc-banner` which helps when styling
273
- position: 'bottom', // default position is 'bottom'
274
-
275
- // Available styles
276
- // -block (default, no extra classes)
277
- // -edgeless
278
- // -classic
279
- // use your own style name and use `.cc-theme-STYLENAME` class in CSS to edit.
280
- // Note: style "wire" is used for the configurator, but has no CSS styles of its own, only palette is used.
281
- theme: 'block',
282
-
283
- // The popup is `fixed` by default, but if you want it to be static (inline with the page content), set this to false
284
- // Note: by default, we animate the height of the popup from 0 to full size
285
- static: false,
286
-
287
- // if you want custom colours, pass them in here. this object should look like this.
288
- // ideally, any custom colours/themes should be created in a separate style sheet, as this is more efficient.
289
- // {
290
- // popup: {background: '#000000', text: '#fff', link: '#fff'},
291
- // button: {background: 'transparent', border: '#f8e71c', text: '#f8e71c'},
292
- // highlight: {background: '#f8e71c', border: '#f8e71c', text: '#000000'},
293
- // }
294
- // `highlight` is optional and extends `button`. if it exists, it will apply to the first button
295
- // only background needs to be defined for every element. if not set, other colors can be calculated from it
296
- palette: null,
297
-
298
- // Some countries REQUIRE that a user can change their mind. You can configure this yourself.
299
- // Most of the time this should be false, but the `cookieconsent.law` can change this to `true` if it detects that it should
300
- revokable: false,
301
-
302
- // if true, the revokable button will tranlate in and out
303
- animateRevokable: true,
304
-
305
- // used to disable link on existing layouts
306
- // replaces element messagelink with message and removes content of link
307
- showLink: true,
308
-
309
- // set value as scroll range to enable
310
- dismissOnScroll: false,
311
-
312
- // set value as time in milliseconds to autodismiss after set time
313
- dismissOnTimeout: false,
314
-
315
- // The application automatically decide whether the popup should open.
316
- // Set this to false to prevent this from happening and to allow you to control the behaviour yourself
317
- autoOpen: true,
318
-
319
- // By default the created HTML is automatically appended to the container (which defaults to <body>). You can prevent this behaviour
320
- // by setting this to false, but if you do, you must attach the `element` yourself, which is a public property of the popup instance:
321
- //
322
- // var instance = cookieconsent.factory(options);
323
- // document.body.appendChild(instance.element);
324
- //
325
- autoAttach: true,
326
-
327
- // simple whitelist/blacklist for pages. specify page by:
328
- // - using a string : '/index.html' (matches '/index.html' exactly) OR
329
- // - using RegExp : /\/page_[\d]+\.html/ (matched '/page_1.html' and '/page_2.html' etc)
330
- whitelistPage: [],
331
- blacklistPage: [],
332
-
333
- // If this is defined, then it is used as the inner html instead of layout. This allows for ultimate customisation.
334
- // Be sure to use the classes `cc-btn` and `cc-allow`, `cc-deny` or `cc-dismiss`. They enable the app to register click
335
- // handlers. You can use other pre-existing classes too. See `src/styles` folder.
336
- overrideHTML: null,
337
- };
338
-
339
- function CookiePopup() {
340
- this.initialise.apply(this, arguments);
341
- }
342
-
343
- CookiePopup.prototype.initialise = function(options) {
344
- if (this.options) {
345
- this.destroy(); // already rendered
346
- }
347
-
348
- // set options back to default options
349
- util.deepExtend(this.options = {}, defaultOptions);
350
-
351
- // merge in user options
352
- if (util.isPlainObject(options)) {
353
- util.deepExtend(this.options, options);
354
- }
355
-
356
- // returns true if `onComplete` was called
357
- if (checkCallbackHooks.call(this)) {
358
- // user has already answered
359
- this.options.enabled = false;
360
- }
361
-
362
- // apply blacklist / whitelist
363
- if (arrayContainsMatches(this.options.blacklistPage, location.pathname)) {
364
- this.options.enabled = false;
365
- }
366
- if (arrayContainsMatches(this.options.whitelistPage, location.pathname)) {
367
- this.options.enabled = true;
368
- }
369
-
370
- // the full markup either contains the wrapper or it does not (for multiple instances)
371
- var cookiePopup = this.options.window
372
- .replace('{{classes}}', getPopupClasses.call(this).join(' '))
373
- .replace('{{children}}', getPopupInnerMarkup.call(this));
374
-
375
- // if user passes html, use it instead
376
- var customHTML = this.options.overrideHTML;
377
- if (typeof customHTML == 'string' && customHTML.length) {
378
- cookiePopup = customHTML;
379
- }
380
-
381
- // if static, we need to grow the element from 0 height so it doesn't jump the page
382
- // content. we wrap an element around it which will mask the hidden content
383
- if (this.options.static) {
384
- // `grower` is a wrapper div with a hidden overflow whose height is animated
385
- var wrapper = appendMarkup.call(this, '<div class="cc-grower">' + cookiePopup + '</div>');
386
-
387
- wrapper.style.display = ''; // set it to visible (because appendMarkup hides it)
388
- this.element = wrapper.firstChild; // get the `element` reference from the wrapper
389
- this.element.style.display = 'none';
390
- util.addClass(this.element, 'cc-invisible');
391
- } else {
392
- this.element = appendMarkup.call(this, cookiePopup);
393
- }
394
-
395
- applyAutoDismiss.call(this);
396
-
397
- applyRevokeButton.call(this);
398
-
399
- if (this.options.autoOpen) {
400
- this.autoOpen();
401
- }
402
- };
403
-
404
- CookiePopup.prototype.destroy = function() {
405
- if (this.onButtonClick && this.element) {
406
- this.element.removeEventListener('click', this.onButtonClick);
407
- this.onButtonClick = null;
408
- }
409
-
410
- if (this.dismissTimeout) {
411
- clearTimeout(this.dismissTimeout);
412
- this.dismissTimeout = null;
413
- }
414
-
415
- if (this.onWindowScroll) {
416
- window.removeEventListener('scroll', this.onWindowScroll);
417
- this.onWindowScroll = null;
418
- }
419
-
420
- if (this.onMouseMove) {
421
- window.removeEventListener('mousemove', this.onMouseMove);
422
- this.onMouseMove = null;
423
- }
424
-
425
- if (this.element && this.element.parentNode) {
426
- this.element.parentNode.removeChild(this.element);
427
- }
428
- this.element = null;
429
-
430
- if (this.revokeBtn && this.revokeBtn.parentNode) {
431
- this.revokeBtn.parentNode.removeChild(this.revokeBtn);
432
- }
433
- this.revokeBtn = null;
434
-
435
- removeCustomStyle(this.options.palette);
436
- this.options = null;
437
- };
438
-
439
- CookiePopup.prototype.open = function(callback) {
440
- if (!this.element) return;
441
-
442
- if (!this.isOpen()) {
443
- if (cc.hasTransition) {
444
- this.fadeIn();
445
- } else {
446
- this.element.style.display = '';
447
- }
448
-
449
- if (this.options.revokable) {
450
- this.toggleRevokeButton();
451
- }
452
- this.options.onPopupOpen.call(this);
453
- }
454
-
455
- return this;
456
- };
457
-
458
- CookiePopup.prototype.close = function(showRevoke) {
459
- if (!this.element) return;
460
-
461
- if (this.isOpen()) {
462
- if (cc.hasTransition) {
463
- this.fadeOut();
464
- } else {
465
- this.element.style.display = 'none';
466
- }
467
-
468
- if (showRevoke && this.options.revokable) {
469
- this.toggleRevokeButton(true);
470
- }
471
- this.options.onPopupClose.call(this);
472
- }
473
-
474
- return this;
475
- };
476
-
477
- CookiePopup.prototype.fadeIn = function() {
478
- var el = this.element;
479
-
480
- if (!cc.hasTransition || !el)
481
- return;
482
-
483
- // This should always be called AFTER fadeOut (which is governed by the 'transitionend' event).
484
- // 'transitionend' isn't all that reliable, so, if we try and fadeIn before 'transitionend' has
485
- // has a chance to run, then we run it ourselves
486
- if (this.afterTransition) {
487
- afterFadeOut.call(this, el)
488
- }
489
-
490
- if (util.hasClass(el, 'cc-invisible')) {
491
- el.style.display = '';
492
-
493
- if (this.options.static) {
494
- var height = this.element.clientHeight;
495
- this.element.parentNode.style.maxHeight = height + 'px';
496
- }
497
-
498
- var fadeInTimeout = 20; // (ms) DO NOT MAKE THIS VALUE SMALLER. See below
499
-
500
- // Although most browsers can handle values less than 20ms, it should remain above this value.
501
- // This is because we are waiting for a "browser redraw" before we remove the 'cc-invisible' class.
502
- // If the class is remvoed before a redraw could happen, then the fadeIn effect WILL NOT work, and
503
- // the popup will appear from nothing. Therefore we MUST allow enough time for the browser to do
504
- // its thing. The actually difference between using 0 and 20 in a set timeout is neglegible anyway
505
- this.openingTimeout = setTimeout(afterFadeIn.bind(this, el), fadeInTimeout);
506
- }
507
- };
508
-
509
- CookiePopup.prototype.fadeOut = function() {
510
- var el = this.element;
511
-
512
- if (!cc.hasTransition || !el)
513
- return;
514
-
515
- if (this.openingTimeout) {
516
- clearTimeout(this.openingTimeout);
517
- afterFadeIn.bind(this, el);
518
- }
519
-
520
- if (!util.hasClass(el, 'cc-invisible')) {
521
- if (this.options.static) {
522
- this.element.parentNode.style.maxHeight = '';
523
- }
524
-
525
- this.afterTransition = afterFadeOut.bind(this, el);
526
- el.addEventListener(cc.transitionEnd, this.afterTransition);
527
-
528
- util.addClass(el, 'cc-invisible');
529
- }
530
- };
531
-
532
- CookiePopup.prototype.isOpen = function() {
533
- return this.element && this.element.style.display == '' && (cc.hasTransition ? !util.hasClass(this.element, 'cc-invisible') : true);
534
- };
535
-
536
- CookiePopup.prototype.toggleRevokeButton = function(show) {
537
- if (this.revokeBtn) this.revokeBtn.style.display = show ? '' : 'none';
538
- };
539
-
540
- CookiePopup.prototype.revokeChoice = function(preventOpen) {
541
- this.options.enabled = true;
542
- this.clearStatus();
543
-
544
- this.options.onRevokeChoice.call(this);
545
-
546
- if (!preventOpen) {
547
- this.autoOpen();
548
- }
549
- };
550
-
551
- // returns true if the cookie has a valid value
552
- CookiePopup.prototype.hasAnswered = function(options) {
553
- return Object.keys(cc.status).indexOf(this.getStatus()) >= 0;
554
- };
555
-
556
- // returns true if the cookie indicates that consent has been given
557
- CookiePopup.prototype.hasConsented = function(options) {
558
- var val = this.getStatus();
559
- return val == cc.status.allow || val == cc.status.dismiss;
560
- };
561
-
562
- // opens the popup if no answer has been given
563
- CookiePopup.prototype.autoOpen = function(options) {
564
- !this.hasAnswered() && this.options.enabled && this.open();
565
- };
566
-
567
- CookiePopup.prototype.setStatus = function(status) {
568
- var c = this.options.cookie;
569
- var value = util.getCookie(c.name);
570
- var chosenBefore = Object.keys(cc.status).indexOf(value) >= 0;
571
-
572
- // if `status` is valid
573
- if (Object.keys(cc.status).indexOf(status) >= 0) {
574
- util.setCookie(c.name, status, c.expiryDays, c.domain, c.path);
575
-
576
- this.options.onStatusChange.call(this, status, chosenBefore);
577
- } else {
578
- this.clearStatus();
579
- }
580
- };
581
-
582
- CookiePopup.prototype.getStatus = function() {
583
- return util.getCookie(this.options.cookie.name);
584
- };
585
-
586
- CookiePopup.prototype.clearStatus = function() {
587
- var c = this.options.cookie;
588
- util.setCookie(c.name, '', -1, c.domain, c.path);
589
- };
590
-
591
- // This needs to be called after 'fadeIn'. This is the code that actually causes the fadeIn to work
592
- // There is a good reason why it's called in a timeout. Read 'fadeIn';
593
- function afterFadeIn(el) {
594
- this.openingTimeout = null;
595
- util.removeClass(el, 'cc-invisible');
596
- }
597
-
598
- // This is called on 'transitionend' (only on the transition of the fadeOut). That's because after we've faded out, we need to
599
- // set the display to 'none' (so there aren't annoying invisible popups all over the page). If for whenever reason this function
600
- // is not called (lack of support), the open/close mechanism will still work.
601
- function afterFadeOut(el) {
602
- el.style.display = 'none'; // after close and before open, the display should be none
603
- el.removeEventListener(cc.transitionEnd, this.afterTransition);
604
- this.afterTransition = null;
605
- }
606
-
607
- // this function calls the `onComplete` hook and returns true (if needed) and returns false otherwise
608
- function checkCallbackHooks() {
609
- var complete = this.options.onInitialise.bind(this);
610
-
611
- if (!window.navigator.cookieEnabled) {
612
- complete(cc.status.deny);
613
- return true;
614
- }
615
-
616
- if (window.CookiesOK || window.navigator.CookiesOK) {
617
- complete(cc.status.allow);
618
- return true;
619
- }
620
-
621
- var allowed = Object.keys(cc.status);
622
- var answer = this.getStatus();
623
- var match = allowed.indexOf(answer) >= 0;
624
-
625
- if (match) {
626
- complete(answer);
627
- }
628
- return match;
629
- }
630
-
631
- function getPositionClasses() {
632
- var positions = this.options.position.split('-'); // top, bottom, left, right
633
- var classes = [];
634
-
635
- // top, left, right, bottom
636
- positions.forEach(function(cur) {
637
- classes.push('cc-' + cur);
638
- });
639
-
640
- return classes;
641
- }
642
-
643
- function getPopupClasses() {
644
- var opts = this.options;
645
- var positionStyle = (opts.position == 'top' || opts.position == 'bottom') ? 'banner' : 'floating';
646
-
647
- if (util.isMobile()) {
648
- positionStyle = 'floating';
649
- }
650
-
651
- var classes = [
652
- 'cc-' + positionStyle, // floating or banner
653
- 'cc-type-' + opts.type, // add the compliance type
654
- 'cc-theme-' + opts.theme, // add the theme
655
- ];
656
-
657
- if (opts.static) {
658
- classes.push('cc-static');
659
- }
660
-
661
- classes.push.apply(classes, getPositionClasses.call(this));
662
-
663
- // we only add extra styles if `palette` has been set to a valid value
664
- var didAttach = attachCustomPalette.call(this, this.options.palette);
665
-
666
- // if we override the palette, add the class that enables this
667
- if (this.customStyleSelector) {
668
- classes.push(this.customStyleSelector);
669
- }
670
-
671
- return classes;
672
- }
673
-
674
- function getPopupInnerMarkup() {
675
- var interpolated = {};
676
- var opts = this.options;
677
-
678
- // removes link if showLink is false
679
- if (!opts.showLink) {
680
- opts.elements.link = '';
681
- opts.elements.messagelink = opts.elements.message;
682
- }
683
-
684
- Object.keys(opts.elements).forEach(function(prop) {
685
- interpolated[prop] = util.interpolateString(opts.elements[prop], function(name) {
686
- var str = opts.content[name];
687
- return (name && typeof str == 'string' && str.length) ? str : '';
688
- })
689
- });
690
-
691
- // checks if the type is valid and defaults to info if it's not
692
- var complianceType = opts.compliance[opts.type];
693
- if (!complianceType) {
694
- complianceType = opts.compliance.info;
695
- }
696
-
697
- // build the compliance types from the already interpolated `elements`
698
- interpolated.compliance = util.interpolateString(complianceType, function(name) {
699
- return interpolated[name];
700
- });
701
-
702
- // checks if the layout is valid and defaults to basic if it's not
703
- var layout = opts.layouts[opts.layout];
704
- if (!layout) {
705
- layout = opts.layouts.basic;
706
- }
707
-
708
- return util.interpolateString(layout, function(match) {
709
- return interpolated[match];
710
- });
711
- }
712
-
713
- function appendMarkup(markup) {
714
- var opts = this.options;
715
- var div = document.createElement('div');
716
- var cont = (opts.container && opts.container.nodeType === 1) ? opts.container : document.body;
717
-
718
- div.innerHTML = markup;
719
-
720
- var el = div.children[0];
721
-
722
- el.style.display = 'none';
723
-
724
- if (util.hasClass(el, 'cc-window') && cc.hasTransition) {
725
- util.addClass(el, 'cc-invisible');
726
- }
727
-
728
- // save ref to the function handle so we can unbind it later
729
- this.onButtonClick = handleButtonClick.bind(this);
730
-
731
- el.addEventListener('click', this.onButtonClick);
732
-
733
- if (opts.autoAttach) {
734
- if (!cont.firstChild) {
735
- cont.appendChild(el);
736
- } else {
737
- cont.insertBefore(el, cont.firstChild)
738
- }
739
- }
740
-
741
- return el;
742
- }
743
-
744
- function handleButtonClick(event) {
745
- var targ = event.target;
746
- if (util.hasClass(targ, 'cc-btn')) {
747
-
748
- var matches = targ.className.match(new RegExp("\\bcc-(" + __allowedStatuses.join('|') + ")\\b"));
749
- var match = (matches && matches[1]) || false;
750
-
751
- if (match) {
752
- this.setStatus(match);
753
- this.close(true);
754
- }
755
- }
756
- if (util.hasClass(targ, 'cc-close')) {
757
- this.setStatus(cc.status.dismiss);
758
- this.close(true);
759
- }
760
- if (util.hasClass(targ, 'cc-revoke')) {
761
- this.revokeChoice();
762
- }
763
- }
764
-
765
- // I might change this function to use inline styles. I originally chose a stylesheet because I could select many elements with a
766
- // single rule (something that happened a lot), the apps has changed slightly now though, so inline styles might be more applicable.
767
- function attachCustomPalette(palette) {
768
- var hash = util.hash(JSON.stringify(palette));
769
- var selector = 'cc-color-override-' + hash;
770
- var isValid = util.isPlainObject(palette);
771
-
772
- this.customStyleSelector = isValid ? selector : null;
773
-
774
- if (isValid) {
775
- addCustomStyle(hash, palette, '.' + selector);
776
- }
777
- return isValid;
778
- }
779
-
780
- function addCustomStyle(hash, palette, prefix) {
781
-
782
- // only add this if a style like it doesn't exist
783
- if (cc.customStyles[hash]) {
784
- // custom style already exists, so increment the reference count
785
- ++cc.customStyles[hash].references;
786
- return;
787
- }
788
-
789
- var colorStyles = {};
790
- var popup = palette.popup;
791
- var button = palette.button;
792
- var highlight = palette.highlight;
793
-
794
- // needs background colour, text and link will be set to black/white if not specified
795
- if (popup) {
796
- // assumes popup.background is set
797
- popup.text = popup.text ? popup.text : util.getContrast(popup.background);
798
- popup.link = popup.link ? popup.link : popup.text;
799
- colorStyles[prefix + '.cc-window'] = [
800
- 'color: ' + popup.text,
801
- 'background-color: ' + popup.background
802
- ];
803
- colorStyles[prefix + '.cc-revoke'] = [
804
- 'color: ' + popup.text,
805
- 'background-color: ' + popup.background
806
- ];
807
- colorStyles[prefix + ' .cc-link,' + prefix + ' .cc-link:active,' + prefix + ' .cc-link:visited'] = [
808
- 'color: ' + popup.link
809
- ];
810
-
811
- if (button) {
812
- // assumes button.background is set
813
- button.text = button.text ? button.text : util.getContrast(button.background);
814
- button.border = button.border ? button.border : 'transparent';
815
- colorStyles[prefix + ' .cc-btn'] = [
816
- 'color: ' + button.text,
817
- 'border-color: ' + button.border,
818
- 'background-color: ' + button.background
819
- ];
820
-
821
- if(button.background != 'transparent')
822
- colorStyles[prefix + ' .cc-btn:hover, ' + prefix + ' .cc-btn:focus'] = [
823
- 'background-color: ' + getHoverColour(button.background)
824
- ];
825
-
826
- if (highlight) {
827
- //assumes highlight.background is set
828
- highlight.text = highlight.text ? highlight.text : util.getContrast(highlight.background);
829
- highlight.border = highlight.border ? highlight.border : 'transparent';
830
- colorStyles[prefix + ' .cc-highlight .cc-btn:first-child'] = [
831
- 'color: ' + highlight.text,
832
- 'border-color: ' + highlight.border,
833
- 'background-color: ' + highlight.background
834
- ];
835
- } else {
836
- // sets highlight text color to popup text. background and border are transparent by default.
837
- colorStyles[prefix + ' .cc-highlight .cc-btn:first-child'] = [
838
- 'color: ' + popup.text
839
- ];
840
- }
841
- }
842
-
843
- }
844
-
845
- // this will be interpretted as CSS. the key is the selector, and each array element is a rule
846
- var style = document.createElement('style');
847
- document.head.appendChild(style);
848
-
849
- // custom style doesn't exist, so we create it
850
- cc.customStyles[hash] = {
851
- references: 1,
852
- element: style.sheet
853
- };
854
-
855
- var ruleIndex = -1;
856
- for (var prop in colorStyles) {
857
- if (colorStyles.hasOwnProperty(prop)) {
858
- style.sheet.insertRule(prop + '{' + colorStyles[prop].join(';') + '}', ++ruleIndex);
859
- }
860
- }
861
- }
862
-
863
- function getHoverColour(hex) {
864
- hex = util.normaliseHex(hex);
865
- // for black buttons
866
- if (hex == '000000') {
867
- return '#222';
868
- }
869
- return util.getLuminance(hex);
870
- }
871
-
872
- function removeCustomStyle(palette) {
873
- if (util.isPlainObject(palette)) {
874
- var hash = util.hash(JSON.stringify(palette));
875
- var customStyle = cc.customStyles[hash];
876
- if (customStyle && !--customStyle.references) {
877
- var styleNode = customStyle.element.ownerNode;
878
- if (styleNode && styleNode.parentNode) {
879
- styleNode.parentNode.removeChild(styleNode);
880
- }
881
- cc.customStyles[hash] = null;
882
- }
883
- }
884
- }
885
-
886
- function arrayContainsMatches(array, search) {
887
- for (var i = 0, l = array.length; i < l; ++i) {
888
- var str = array[i];
889
- // if regex matches or string is equal, return true
890
- if ((str instanceof RegExp && str.test(search)) ||
891
- (typeof str == 'string' && str.length && str === search)) {
892
- return true;
893
- }
894
- }
895
- return false;
896
- }
897
-
898
- function applyAutoDismiss() {
899
- var setStatus = this.setStatus.bind(this);
900
-
901
- var delay = this.options.dismissOnTimeout;
902
- if (typeof delay == 'number' && delay >= 0) {
903
- this.dismissTimeout = window.setTimeout(function() {
904
- setStatus(cc.status.dismiss);
905
- }, Math.floor(delay));
906
- }
907
-
908
- var scrollRange = this.options.dismissOnScroll;
909
- if (typeof scrollRange == 'number' && scrollRange >= 0) {
910
- var onWindowScroll = function(evt) {
911
- if (window.pageYOffset > Math.floor(scrollRange)) {
912
- setStatus(cc.status.dismiss);
913
-
914
- window.removeEventListener('scroll', onWindowScroll);
915
- this.onWindowScroll = null;
916
- }
917
- };
918
-
919
- this.onWindowScroll = onWindowScroll;
920
- window.addEventListener('scroll', onWindowScroll);
921
- }
922
- }
923
-
924
- function applyRevokeButton() {
925
- // revokable is true if advanced compliance is selected
926
- if (this.options.type != 'info') this.options.revokable = true;
927
- // animateRevokable false for mobile devices
928
- if (util.isMobile()) this.options.animateRevokable = false;
929
-
930
- if (this.options.revokable) {
931
- var classes = getPositionClasses.call(this);
932
- if (this.options.animateRevokable) {
933
- classes.push('cc-animate');
934
- }
935
- if (this.customStyleSelector) {
936
- classes.push(this.customStyleSelector)
937
- }
938
- var revokeBtn = this.options.revokeBtn.replace('{{classes}}', classes.join(' '));
939
- this.revokeBtn = appendMarkup.call(this, revokeBtn);
940
-
941
- var btn = this.revokeBtn;
942
- if (this.options.animateRevokable) {
943
- var wait = false;
944
- var onMouseMove = util.throttle(function(evt) {
945
- var active = false;
946
- var minY = 20;
947
- var maxY = (window.innerHeight - 20);
948
-
949
- if (util.hasClass(btn, 'cc-top') && evt.clientY < minY) active = true;
950
- if (util.hasClass(btn, 'cc-bottom') && evt.clientY > maxY) active = true;
951
-
952
- if (active) {
953
- if (!util.hasClass(btn, 'cc-active')) {
954
- util.addClass(btn, 'cc-active');
955
- }
956
- } else {
957
- if (util.hasClass(btn, 'cc-active')) {
958
- util.removeClass(btn, 'cc-active');
959
- }
960
- }
961
- }, 200);
962
-
963
- this.onMouseMove = onMouseMove;
964
- window.addEventListener('mousemove', onMouseMove);
965
- }
966
- }
967
- }
968
-
969
- return CookiePopup
970
- }());
971
-
972
- cc.Location = (function() {
973
-
974
- // An object containing all the location services we have already set up.
975
- // When using a service, it could either return a data structure in plain text (like a JSON object) or an executable script
976
- // When the response needs to be executed by the browser, then `isScript` must be set to true, otherwise it won't work.
977
-
978
- // When the service uses a script, the chances are that you'll have to use the script to make additional requests. In these
979
- // cases, the services `callback` property is called with a `done` function. When performing async operations, this must be called
980
- // with the data (or Error), and `cookieconsent.locate` will take care of the rest
981
- var defaultOptions = {
982
-
983
- // The default timeout is 5 seconds. This is mainly needed to catch JSONP requests that error.
984
- // Otherwise there is no easy way to catch JSONP errors. That means that if a JSONP fails, the
985
- // app will take `timeout` milliseconds to react to a JSONP network error.
986
- timeout: 5000,
987
-
988
- // the order that services will be attempted in
989
- services: [
990
- 'freegeoip',
991
- 'ipinfo',
992
- 'maxmind'
993
-
994
- /*
995
-
996
- // 'ipinfodb' requires some options, so we define it using an object
997
- // this object will be passed to the function that defines the service
998
-
999
- {
1000
- name: 'ipinfodb',
1001
- interpolateUrl: {
1002
- // obviously, this is a fake key
1003
- api_key: 'vOgI3748dnIytIrsJcxS7qsDf6kbJkE9lN4yEDrXAqXcKUNvjjZPox3ekXqmMMld'
1004
- },
1005
- },
1006
-
1007
- // as well as defining an object, you can define a function that returns an object
1008
-
1009
- function () {
1010
- return {name: 'ipinfodb'};
1011
- },
1012
-
1013
- */
1014
- ],
1015
-
1016
- serviceDefinitions: {
1017
-
1018
- freegeoip: function() {
1019
- return {
1020
- // This service responds with JSON, but they do not have CORS set, so we must use JSONP and provide a callback
1021
- // The `{callback}` is automatically rewritten by the tool
1022
- url: '//freegeoip.net/json/?callback={callback}',
1023
- isScript: true, // this is JSONP, therefore we must set it to run as a script
1024
- callback: function(done, response) {
1025
- try{
1026
- var json = JSON.parse(response);
1027
- return json.error ? toError(json) : {
1028
- code: json.country_code
1029
- };
1030
- } catch (err) {
1031
- return toError({error: 'Invalid response ('+err+')'});
1032
- }
1033
- }
1034
- }
1035
- },
1036
-
1037
- ipinfo: function() {
1038
- return {
1039
- // This service responds with JSON, so we simply need to parse it and return the country code
1040
- url: '//ipinfo.io',
1041
- headers: ['Accept: application/json'],
1042
- callback: function(done, response) {
1043
- try{
1044
- var json = JSON.parse(response);
1045
- return json.error ? toError(json) : {
1046
- code: json.country
1047
- };
1048
- } catch (err) {
1049
- return toError({error: 'Invalid response ('+err+')'});
1050
- }
1051
- }
1052
- }
1053
- },
1054
-
1055
- // This service requires an option to define `key`. Options are proived using objects or functions
1056
- ipinfodb: function(options) {
1057
- return {
1058
- // This service responds with JSON, so we simply need to parse it and return the country code
1059
- url: '//api.ipinfodb.com/v3/ip-country/?key={api_key}&format=json&callback={callback}',
1060
- isScript: true, // this is JSONP, therefore we must set it to run as a script
1061
- callback: function(done, response) {
1062
- try{
1063
- var json = JSON.parse(response);
1064
- return json.statusCode == 'ERROR' ? toError({error: json.statusMessage}) : {
1065
- code: json.countryCode
1066
- };
1067
- } catch (err) {
1068
- return toError({error: 'Invalid response ('+err+')'});
1069
- }
1070
- }
1071
- }
1072
- },
1073
-
1074
- maxmind: function() {
1075
- return {
1076
- // This service responds with a JavaScript file which defines additional functionality. Once loaded, we must
1077
- // make an additional AJAX call. Therefore we provide a `done` callback that can be called asynchronously
1078
- url: '//js.maxmind.com/js/apis/geoip2/v2.1/geoip2.js',
1079
- isScript: true, // this service responds with a JavaScript file, so it must be run as a script
1080
- callback: function(done) {
1081
- // if everything went okay then `geoip2` WILL be defined
1082
- if (!window.geoip2) {
1083
- done(new Error('Unexpected response format. The downloaded script should have exported `geoip2` to the global scope'));
1084
- return;
1085
- }
1086
-
1087
- geoip2.country(function(location) {
1088
- try {
1089
- done({
1090
- code: location.country.iso_code
1091
- });
1092
- } catch (err) {
1093
- done(toError(err));
1094
- }
1095
- }, function(err) {
1096
- done(toError(err));
1097
- });
1098
-
1099
- // We can't return anything, because we need to wait for the second AJAX call to return.
1100
- // Then we can 'complete' the service by passing data or an error to the `done` callback.
1101
- }
1102
- }
1103
- },
1104
- },
1105
- };
1106
-
1107
- function Location(options) {
1108
- // Set up options
1109
- util.deepExtend(this.options = {}, defaultOptions);
1110
-
1111
- if (util.isPlainObject(options)) {
1112
- util.deepExtend(this.options, options);
1113
- }
1114
-
1115
- this.currentServiceIndex = -1; // the index (in options) of the service we're currently using
1116
- }
1117
-
1118
- Location.prototype.getNextService = function() {
1119
- var service;
1120
-
1121
- do {
1122
- service = this.getServiceByIdx(++this.currentServiceIndex);
1123
- } while (this.currentServiceIndex < this.options.services.length && !service);
1124
-
1125
- return service;
1126
- };
1127
-
1128
- Location.prototype.getServiceByIdx = function(idx) {
1129
- // This can either be the name of a default locationService, or a function.
1130
- var serviceOption = this.options.services[idx];
1131
-
1132
- // If it's a string, use one of the location services.
1133
- if (typeof serviceOption === 'function') {
1134
- var dynamicOpts = serviceOption();
1135
- if (dynamicOpts.name) {
1136
- util.deepExtend(dynamicOpts, this.options.serviceDefinitions[dynamicOpts.name](dynamicOpts));
1137
- }
1138
- return dynamicOpts;
1139
- }
1140
-
1141
- // If it's a string, use one of the location services.
1142
- if (typeof serviceOption === 'string') {
1143
- return this.options.serviceDefinitions[serviceOption]();
1144
- }
1145
-
1146
- // If it's an object, assume {name: 'ipinfo', ...otherOptions}
1147
- // Allows user to pass in API keys etc.
1148
- if (util.isPlainObject(serviceOption)) {
1149
- return this.options.serviceDefinitions[serviceOption.name](serviceOption);
1150
- }
1151
-
1152
- return null;
1153
- };
1154
-
1155
- // This runs the service located at index `currentServiceIndex`.
1156
- // If the service fails, `runNextServiceOnError` will continue trying each service until all fail, or one completes successfully
1157
- Location.prototype.locate = function(complete, error) {
1158
- var service = this.getNextService();
1159
-
1160
- if (!service) {
1161
- error(new Error('No services to run'));
1162
- return;
1163
- }
1164
-
1165
- this.callbackComplete = complete;
1166
- this.callbackError = error;
1167
-
1168
- this.runService(service, this.runNextServiceOnError.bind(this));
1169
- };
1170
-
1171
- // Potentially adds a callback to a url for jsonp.
1172
- Location.prototype.setupUrl = function(service) {
1173
- var serviceOpts = this.getCurrentServiceOpts();
1174
- return service.url.replace(/\{(.*?)\}/g, function(_, param) {
1175
- if (param === 'callback') {
1176
- var tempName = 'callback' + Date.now();
1177
- window[tempName] = function(res) {
1178
- service.__JSONP_DATA = JSON.stringify(res);
1179
- }
1180
- return tempName;
1181
- }
1182
- if (param in serviceOpts.interpolateUrl) {
1183
- return serviceOpts.interpolateUrl[param];
1184
- }
1185
- });
1186
- };
1187
-
1188
- // requires a `service` object that defines at least a `url` and `callback`
1189
- Location.prototype.runService = function(service, complete) {
1190
- var self = this;
1191
-
1192
- // basic check to ensure it resembles a `service`
1193
- if (!service || !service.url || !service.callback) {
1194
- return;
1195
- }
1196
-
1197
- // we call either `getScript` or `makeAsyncRequest` depending on the type of resource
1198
- var requestFunction = service.isScript ? getScript : makeAsyncRequest;
1199
-
1200
- var url = this.setupUrl(service);
1201
-
1202
- // both functions have similar signatures so we can pass the same arguments to both
1203
- requestFunction(url, function(xhr) {
1204
- // if `!xhr`, then `getScript` function was used, so there is no response text
1205
- var responseText = xhr ? xhr.responseText : '';
1206
-
1207
- // if the resource is a script, then this function is called after the script has been run.
1208
- // if the script is JSONP, then a time defined function `callback_{Date.now}` has already
1209
- // been called (as the JSONP callback). This callback sets the __JSONP_DATA property
1210
- if (service.__JSONP_DATA) {
1211
- responseText = service.__JSONP_DATA;
1212
- delete service.__JSONP_DATA;
1213
- }
1214
-
1215
- // call the service callback with the response text (so it can parse the response)
1216
- self.runServiceCallback.call(self, complete, service, responseText);
1217
-
1218
- }, this.options.timeout, service.data, service.headers);
1219
-
1220
- // `service.data` and `service.headers` are optional (they only count if `!service.isScript` anyway)
1221
- };
1222
-
1223
- // The service request has run (and possibly has a `responseText`) [no `responseText` if `isScript`]
1224
- // We need to run its callback which determines if its successful or not
1225
- // `complete` is called on success or failure
1226
- Location.prototype.runServiceCallback = function(complete, service, responseText) {
1227
- var self = this;
1228
- // this is the function that is called if the service uses the async callback in its handler method
1229
- var serviceResultHandler = function (asyncResult) {
1230
- // if `result` is a valid value, then this function shouldn't really run
1231
- // even if it is called by `service.callback`
1232
- if (!result) {
1233
- self.onServiceResult.call(self, complete, asyncResult)
1234
- }
1235
- };
1236
-
1237
- // the function `service.callback` will either extract a country code from `responseText` and return it (in `result`)
1238
- // or (if it has to make additional requests) it will call a `done` callback with the country code when it is ready
1239
- var result = service.callback(serviceResultHandler, responseText);
1240
-
1241
- if (result) {
1242
- this.onServiceResult.call(this, complete, result);
1243
- }
1244
- };
1245
-
1246
- // This is called with the `result` from `service.callback` regardless of how it provided that result (sync or async).
1247
- // `result` will be whatever is returned from `service.callback`. A service callback should provide an object with data
1248
- Location.prototype.onServiceResult = function(complete, result) {
1249
- // convert result to nodejs style async callback
1250
- if (result instanceof Error || (result && result.error)) {
1251
- complete.call(this, result, null);
1252
- } else {
1253
- complete.call(this, null, result);
1254
- }
1255
- };
1256
-
1257
- // if `err` is set, the next service handler is called
1258
- // if `err` is null, the `onComplete` handler is called with `data`
1259
- Location.prototype.runNextServiceOnError = function(err, data) {
1260
- if (err) {
1261
- this.logError(err);
1262
-
1263
- var nextService = this.getNextService();
1264
-
1265
- if (nextService) {
1266
- this.runService(nextService, this.runNextServiceOnError.bind(this));
1267
- } else {
1268
- this.completeService.call(this, this.callbackError, new Error('All services failed'));
1269
- }
1270
- } else {
1271
- this.completeService.call(this, this.callbackComplete, data);
1272
- }
1273
- };
1274
-
1275
- Location.prototype.getCurrentServiceOpts = function() {
1276
- var val = this.options.services[this.currentServiceIndex];
1277
-
1278
- if (typeof val == 'string') {
1279
- return {name: val};
1280
- }
1281
-
1282
- if (typeof val == 'function') {
1283
- return val();
1284
- }
1285
-
1286
- if (util.isPlainObject(val)) {
1287
- return val;
1288
- }
1289
-
1290
- return {};
1291
- };
1292
-
1293
- // calls the `onComplete` callback after resetting the `currentServiceIndex`
1294
- Location.prototype.completeService = function(fn, data) {
1295
- this.currentServiceIndex = -1;
1296
-
1297
- fn && fn(data);
1298
- };
1299
-
1300
- Location.prototype.logError = function (err) {
1301
- var idx = this.currentServiceIndex;
1302
- var service = this.getServiceByIdx(idx);
1303
-
1304
- console.error('The service[' + idx + '] (' + service.url + ') responded with the following error', err);
1305
- };
1306
-
1307
- function getScript(url, callback, timeout) {
1308
- var timeoutIdx, s = document.createElement('script');
1309
-
1310
- s.type = 'text/' + (url.type || 'javascript');
1311
- s.src = url.src || url;
1312
- s.async = false;
1313
-
1314
- s.onreadystatechange = s.onload = function() {
1315
- // this code handles two scenarios, whether called by onload or onreadystatechange
1316
- var state = s.readyState;
1317
-
1318
- clearTimeout(timeoutIdx);
1319
-
1320
- if (!callback.done && (!state || /loaded|complete/.test(state))) {
1321
- callback.done = true;
1322
- callback();
1323
- s.onreadystatechange = s.onload = null;
1324
- }
1325
- };
1326
-
1327
- document.body.appendChild(s);
1328
-
1329
- // You can't catch JSONP Errors, because it's handled by the script tag
1330
- // one way is to use a timeout
1331
- timeoutIdx = setTimeout(function () {
1332
- callback.done = true;
1333
- callback();
1334
- s.onreadystatechange = s.onload = null;
1335
- }, timeout);
1336
- }
1337
-
1338
- function makeAsyncRequest(url, onComplete, timeout, postData, requestHeaders) {
1339
- var xhr = new(window.XMLHttpRequest || window.ActiveXObject)('MSXML2.XMLHTTP.3.0');
1340
-
1341
- xhr.open(postData ? 'POST' : 'GET', url, 1);
1342
-
1343
- xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
1344
- xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
1345
-
1346
- if (Array.isArray(requestHeaders)) {
1347
- for (var i = 0, l = requestHeaders.length; i < l; ++i) {
1348
- var split = requestHeaders[i].split(':', 2)
1349
- xhr.setRequestHeader(split[0].replace(/^\s+|\s+$/g, ''), split[1].replace(/^\s+|\s+$/g, ''));
1350
- }
1351
- }
1352
-
1353
- if (typeof onComplete == 'function') {
1354
- xhr.onreadystatechange = function() {
1355
- if (xhr.readyState > 3) {
1356
- onComplete(xhr);
1357
- }
1358
- };
1359
- }
1360
-
1361
- xhr.send(postData);
1362
- }
1363
-
1364
- function toError(obj) {
1365
- return new Error('Error [' + (obj.code || 'UNKNOWN') + ']: ' + obj.error);
1366
- }
1367
-
1368
- return Location;
1369
- }());
1370
-
1371
- cc.Law = (function() {
1372
-
1373
- var defaultOptions = {
1374
- // Make this false if you want to disable all regional overrides for settings.
1375
- // If true, options can differ by country, depending on their cookie law.
1376
- // It does not affect hiding the popup for countries that do not have cookie law.
1377
- regionalLaw: true,
1378
-
1379
- // countries that enforce some version of a cookie law
1380
- hasLaw: ['AT', 'BE', 'BG', 'HR', 'CZ', 'CY', 'DK', 'EE', 'FI', 'FR', 'DE', 'EL', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU', 'MT', 'NL', 'PL', 'PT', 'SK', 'SI', 'ES', 'SE', 'GB', 'UK'],
1381
-
1382
- // countries that say that all cookie consent choices must be revokable (a user must be able too change their mind)
1383
- revokable: ['HR', 'CY', 'DK', 'EE', 'FR', 'DE', 'LV', 'LT', 'NL', 'PT', 'ES'],
1384
-
1385
- // countries that say that a person can only "consent" if the explicitly click on "I agree".
1386
- // in these countries, consent cannot be implied via a timeout or by scrolling down the page
1387
- explicitAction: ['HR', 'IT', 'ES'],
1388
- };
1389
-
1390
- function Law(options) {
1391
- this.initialise.apply(this, arguments);
1392
- }
1393
-
1394
- Law.prototype.initialise = function(options) {
1395
- // set options back to default options
1396
- util.deepExtend(this.options = {}, defaultOptions);
1397
-
1398
- // merge in user options
1399
- if (util.isPlainObject(options)) {
1400
- util.deepExtend(this.options, options);
1401
- }
1402
- };
1403
-
1404
- Law.prototype.get = function(countryCode) {
1405
- var opts = this.options;
1406
- return {
1407
- hasLaw: opts.hasLaw.indexOf(countryCode) >= 0,
1408
- revokable: opts.revokable.indexOf(countryCode) >= 0,
1409
- explicitAction: opts.explicitAction.indexOf(countryCode) >= 0,
1410
- };
1411
- };
1412
-
1413
- Law.prototype.applyLaw = function(options, countryCode) {
1414
- var country = this.get(countryCode);
1415
-
1416
- if (!country.hasLaw) {
1417
- // The country has no cookie law
1418
- options.enabled = false;
1419
- }
1420
-
1421
- if (this.options.regionalLaw) {
1422
- if (country.revokable) {
1423
- // We must provide an option to revoke consent at a later time
1424
- options.revokable = true;
1425
- }
1426
-
1427
- if (country.explicitAction) {
1428
- // The user must explicitly click the consent button
1429
- options.dismissOnScroll = false;
1430
- options.dismissOnTimeout = false;
1431
- }
1432
- }
1433
- return options;
1434
- };
1435
-
1436
- return Law;
1437
- }());
1438
-
1439
- // This function initialises the app by combining the use of the Popup, Locator and Law modules
1440
- // You can string together these three modules yourself however you want, by writing a new function.
1441
- cc.initialise = function(options, complete, error) {
1442
- var law = new cc.Law(options.law);
1443
-
1444
- if (!complete) complete = function() {};
1445
- if (!error) error = function() {};
1446
-
1447
- cc.getCountryCode(options, function(result) {
1448
- // don't need the law or location options anymore
1449
- delete options.law;
1450
- delete options.location;
1451
-
1452
- if (result.code) {
1453
- options = law.applyLaw(options, result.code);
1454
- }
1455
-
1456
- complete(new cc.Popup(options));
1457
- }, function(err) {
1458
- // don't need the law or location options anymore
1459
- delete options.law;
1460
- delete options.location;
1461
-
1462
- error(err, new cc.Popup(options));
1463
- });
1464
- };
1465
-
1466
- // This function tries to find your current location. It either grabs it from a hardcoded option in
1467
- // `options.law.countryCode`, or attempts to make a location service request. This function accepts
1468
- // options (which can configure the `law` and `location` modules) and fires a callback with which
1469
- // passes an object `{code: countryCode}` as the first argument (which can have undefined properties)
1470
- cc.getCountryCode = function(options, complete, error) {
1471
- if (options.law && options.law.countryCode) {
1472
- complete({
1473
- code: options.law.countryCode
1474
- });
1475
- return;
1476
- }
1477
- if (options.location) {
1478
- var locator = new cc.Location(options.location);
1479
- locator.locate(function(serviceResult) {
1480
- complete(serviceResult || {});
1481
- }, error);
1482
- return;
1483
- }
1484
- complete({});
1485
- };
1486
-
1487
- // export utils (no point in hiding them, so we may as well expose them)
1488
- cc.utils = util;
1489
-
1490
- // prevent this code from being run twice
1491
- cc.hasInitialised = true;
1492
-
1493
- window.cookieconsent = cc;
1494
-
1495
- }(window.cookieconsent || {}));
1496
-
1497
-
1498
- window.addEventListener("load", function(){
1499
- window.cookieconsent.initialise({
1500
- "palette": {
1501
- },
1502
- "theme": "classic",
1503
- "position": "bottom-right"
1504
- })});