1(function () { 2 // Stop from running again, if accidently included more than once. 3 if (window.hasCookieConsent) return; 4 window.hasCookieConsent = true; 5 6 /* 7 Constants 8 */ 9 10 // Client variable which may be present containing options to override with 11 var OPTIONS_VARIABLE = 'cookieconsent_options'; 12 13 // Change cookie consent options on the fly. 14 var OPTIONS_UPDATER = 'update_cookieconsent_options'; 15 16 // Name of cookie to be set when dismissed 17 var DISMISSED_COOKIE = 'cookieconsent_dismissed'; 18 19 // The path to style 20 var THEME_BUCKET_PATH = '/js/cookieconsent/'; 21 22 // No point going further if they've already dismissed. 23 if (document.cookie.indexOf(DISMISSED_COOKIE) > -1) { 24 return; 25 } 26 27 // IE8... 28 if(typeof String.prototype.trim !== 'function') { 29 String.prototype.trim = function() { 30 return this.replace(/^\s+|\s+$/g, ''); 31 }; 32 } 33 34 /* 35 Helper methods 36 */ 37 var Util = { 38 isArray: function (obj) { 39 var proto = Object.prototype.toString.call(obj); 40 return proto == '[object Array]'; 41 }, 42 43 isObject: function (obj) { 44 return Object.prototype.toString.call(obj) == '[object Object]'; 45 }, 46 47 each: function (arr, callback, /* optional: */context, force) { 48 if (Util.isObject(arr) && !force) { 49 for (var key in arr) { 50 if (arr.hasOwnProperty(key)) { 51 callback.call(context, arr[key], key, arr); 52 } 53 } 54 } else { 55 for (var i = 0, ii = arr.length; i < ii; i++) { 56 callback.call(context, arr[i], i, arr); 57 } 58 } 59 }, 60 61 merge: function (obj1, obj2) { 62 if (!obj1) return; 63 Util.each(obj2, function (val, key) { 64 if (Util.isObject(val) && Util.isObject(obj1[key])) { 65 Util.merge(obj1[key], val); 66 } else { 67 obj1[key] = val; 68 } 69 }) 70 }, 71 72 bind: function (func, context) { 73 return function () { 74 return func.apply(context, arguments); 75 }; 76 }, 77 78 /* 79 find a property based on a . separated path. 80 i.e. queryObject({details: {name: 'Adam'}}, 'details.name') // -> 'Adam' 81 returns null if not found 82 */ 83 queryObject: function (object, query) { 84 var queryPart; 85 var i = 0; 86 var head = object; 87 query = query.split('.'); 88 while ( (queryPart = query[i++]) && head.hasOwnProperty(queryPart) && (head = head[queryPart]) ) { 89 if (i === query.length) return head; 90 } 91 return null; 92 }, 93 94 setCookie: function (name, value, expiryDays, domain, path) { 95 expiryDays = expiryDays || 365; 96 97 var exdate = new Date(); 98 exdate.setDate(exdate.getDate() + expiryDays); 99 100 var cookie = [ 101 name + '=' + value, 102 'expires=' + exdate.toUTCString(), 103 'path=' + path || '/' 104 ]; 105 106 if (domain) { 107 cookie.push( 108 'domain=' + domain 109 ); 110 } 111 112 document.cookie = cookie.join(';'); 113 }, 114 115 addEventListener: function (el, event, eventListener) { 116 if (el.addEventListener) { 117 el.addEventListener(event, eventListener); 118 } else { 119 el.attachEvent('on' + event, eventListener); 120 } 121 } 122 }; 123 124 var DomBuilder = (function () { 125 /* 126 The attribute we store events in. 127 */ 128 var eventAttribute = 'data-cc-event'; 129 var conditionAttribute = 'data-cc-if'; 130 131 /* 132 Shim to make addEventListener work correctly with IE. 133 */ 134 var addEventListener = function (el, event, eventListener) { 135 // Add multiple event listeners at once if array is passed. 136 if (Util.isArray(event)) { 137 return Util.each(event, function (ev) { 138 addEventListener(el, ev, eventListener); 139 }); 140 } 141 142 if (el.addEventListener) { 143 el.addEventListener(event, eventListener); 144 } else { 145 el.attachEvent('on' + event, eventListener); 146 } 147 }; 148 149 /* 150 Replace with it's property on the scope 151 */ 152 var insertReplacements = function (htmlStr, scope) { 153 return htmlStr.replace(/\{\{(.*?)\}\}/g, function (_match, sub) { 154 var tokens = sub.split('||'); 155 var value; 156 while (token = tokens.shift()) { 157 token = token.trim(); 158
159 // If string 160 if (token[0] === '"') return token.slice(1, token.length - 1); 161 162 // If query matches 163 value = Util.queryObject(scope, token); 164 165 if (value) return value; 166 } 167 168 return ''; 169 }); 170 }; 171 172 /* 173 Turn a string of html into DOM 174 */ 175 var buildDom = function (htmlStr) { 176 var container = document.createElement('div'); 177 container.innerHTML = htmlStr; 178 return container.children[0]; 179 }; 180 181 var applyToElementsWithAttribute = function (dom, attribute, func) { 182 var els = dom.parentNode.querySelectorAll('[' + attribute + ']'); 183 Util.each(els, function (element) { 184 var attributeVal = element.getAttribute(attribute); 185 func(element, attributeVal); 186 }, window, true); 187 }; 188 189 /* 190 Parse event attributes in dom and set listeners to their matching scope methods 191 */ 192 var applyEvents = function (dom, scope) { 193 applyToElementsWithAttribute(dom, eventAttribute, function (element, attributeVal) { 194 var parts = attributeVal.split(':'); 195 var listener = Util.queryObject(scope, parts[1]); 196 addEventListener(element, parts[0], Util.bind(listener, scope)); 197 }); 198 }; 199 200 var applyConditionals = function (dom, scope) { 201 applyToElementsWithAttribute(dom, conditionAttribute, function (element, attributeVal) { 202 var value = Util.queryObject(scope, attributeVal); 203 if (!value) { 204 element.parentNode.removeChild(element); 205 } 206 }); 207 }; 208 209 return { 210 build: function (htmlStr, scope) { 211 if (Util.isArray(htmlStr)) htmlStr = htmlStr.join(''); 212 213 htmlStr = insertReplacements(htmlStr, scope); 214 var dom = buildDom(htmlStr); 215 applyEvents(dom, scope); 216 applyConditionals(dom, scope); 217 218 return dom; 219 } 220 }; 221 })(); 222 223 224 /* 225 Plugin 226 */ 227 var cookieconsent = { 228 options: { 229 message: 'This website uses cookies to ensure you get the best experience on our website. ',
230 dismiss: 'OK', 231 learnMore: 'More info', 232 link: null, 233 container: null, // selector 234 theme: 'light-floating', 235 domain: null, // default to current domain. 236 path: '/', 237 expiryDays: 365, 238 markup: [ 239 '<div class="cc_banner-wrapper ">', 240 '<div class="cc_banner cc_container cc_container--open">', 241 '<a href="#ok" data-cc-event="click:dismiss" target="_blank" class="cc_btn cc_btn_accept_all">OK</a>', 242 '<p class="cc_message">We use cookies to ensure you get the best experience on our website. <br><br>Please read our <a href="/en/privacy">privacy policy</a> to find out more.</p>', 243 '</div>', 244 '</div>' 245 ] 246 }, 247 248 init: function () { 249 var options = window[OPTIONS_VARIABLE]; 250 if (options) this.setOptions(options); 251 252 this.setContainer(); 253 254 // Calls render when theme is loaded. 255 if (this.options.theme) { 256 this.loadTheme(this.render); 257 } else { 258 this.render(); 259 } 260 }, 261 262 setOptionsOnTheFly: function (options) { 263 this.setOptions(options); 264 this.render(); 265 }, 266 267 setOptions: function (options) { 268 Util.merge(this.options, options); 269 }, 270 271 setContainer: function () { 272 if (this.options.container) { 273 this.container = document.querySelector(this.options.container); 274 } else { 275 this.container = document.body; 276 } 277 278 // Add class to container classes so we can specify css for IE8 only. 279 this.containerClasses = ''; 280 if (navigator.appVersion.indexOf('MSIE 8') > -1) { 281 this.containerClasses += ' cc_ie8' 282 } 283 }, 284 285 loadTheme: function (callback) { 286 var theme = this.options.theme; 287 288 // If theme is specified by name 289 if (theme.indexOf('.css') === -1) { 290 theme = THEME_BUCKET_PATH + theme + '.css'; 291 } 292 293 var link = document.createElement('link'); 294 link.rel = 'stylesheet'; 295 link.type = 'text/css'; 296 link.href = theme; 297 298 var loaded = false; 299 link.onload = Util.bind(function () { 300 if (!loaded && callback) { 301 callback.call(this); 302 loaded = true; 303 } 304 }, this); 305 306 document.getElementsByTagName("head")[0].appendChild(link); 307 }, 308 309 render: function () { 310 // remove current element (if we've already rendered) 311 if (this.element && this.element.parentNode) { 312 this.element.parentNode.removeChild(this.element); 313 delete this.element; 314 } 315 316 this.element = DomBuilder.build(this.options.markup, this); 317 if (!this.container.firstChild) { 318 this.container.appendChild(this.element); 319 } else { 320 this.container.insertBefore(this.element, this.container.firstChild); 321 } 322 }, 323 324 dismiss: function (evt) { 325 evt.preventDefault && evt.preventDefault(); 326 evt.returnValue = false; 327 this.setDismissedCookie(); 328 this.container.removeChild(this.element); 329 }, 330 331 setDismissedCookie: function () { 332 Util.setCookie(DISMISSED_COOKIE, 'yes', this.options.expiryDays, this.options.domain, this.options.path); 333 } 334 }; 335 336 var init; 337 var initialized = false; 338 (init = function () { 339 if (!initialized && document.readyState == 'complete') { 340 cookieconsent.init(); 341 initialized = true; 342 window[OPTIONS_UPDATER] = Util.bind(cookieconsent.setOptionsOnTheFly, cookieconsent); 343 } 344 })(); 345 346 Util.addEventListener(document, 'readystatechange', init); 347 348})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.