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