/*global window:false, setTimeout:true, console:true */ (function(context) { 'use strict'; var win = context, doc = win.document; var global_instance_name = 'cbinstance'; /*! * contentloaded.js * * Author: Diego Perini (diego.perini at gmail.com) * Summary: cross-browser wrapper for DOMContentLoaded * Updated: 20101020 * License: MIT * Version: 1.2 * * URL: * http://javascript.nwbox.com/ContentLoaded/ * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE * */ // @win window reference // @fn function reference function contentLoaded(win, fn) { var done = false, top = true, doc = win.document, root = doc.documentElement, add = doc.addEventListener ? 'addEventListener' : 'attachEvent', rem = doc.addEventListener ? 'removeEventListener' : 'detachEvent', pre = doc.addEventListener ? '' : 'on', init = function(e) { if (e.type == 'readystatechange' && doc.readyState != 'complete') return; (e.type == 'load' ? win : doc)[rem](pre + e.type, init, false); if (!done && (done = true)) fn.call(win, e.type || e); }, poll = function() { try { root.doScroll('left'); } catch(e) { setTimeout(poll, 50); return; } init('poll'); }; if (doc.readyState == 'complete') fn.call(win, 'lazy'); else { if (doc.createEventObject && root.doScroll) { try { top = !win.frameElement; } catch(e) { } if (top) poll(); } doc[add](pre + 'DOMContentLoaded', init, false); doc[add](pre + 'readystatechange', init, false); win[add](pre + 'load', init, false); } } var Cookies = { get: function (key) { return decodeURIComponent(doc.cookie.replace(new RegExp('(?:(?:^|.*;)\\s*' + encodeURIComponent(key).replace(/[\-\.\+\*]/g, '\\$&') + '\\s*\\=\\s*([^;]*).*$)|^.*$'), '$1')) || null; }, set: function (key, val, end, path, domain, secure) { if (!key || /^(?:expires|max\-age|path|domain|secure)$/i.test(key)) { return false; } var expires = ''; if (end) { switch (end.constructor) { case Number: expires = end === Infinity ? '; expires=Fri, 31 Dec 9999 23:59:59 GMT' : '; max-age=' + end; break; case String: expires = '; expires=' + end; break; case Date: expires = '; expires=' + end.toUTCString(); break; } } doc.cookie = encodeURIComponent(key) + '=' + encodeURIComponent(val) + expires + (domain ? '; domain=' + domain : '') + (path ? '; path=' + path : '') + (secure ? '; secure' : ''); return true; }, has: function (key) { return (new RegExp('(?:^|;\\s*)' + encodeURIComponent(key).replace(/[\-\.\+\*]/g, '\\$&') + '\\s*\\=')).test(doc.cookie); }, remove: function (key, path, domain) { if (!key || !this.has(key)) { return false; } doc.cookie = encodeURIComponent(key) + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT' + ( domain ? '; domain=' + domain : '') + ( path ? '; path=' + path : ''); return true; } }; var Utils = { // merge objects and whatnot merge: function(){ var obj = {}, i = 0, al = arguments.length, key; if (0 === al) { return obj; } for (; i < al; i++) { for (key in arguments[i]) { if (Object.prototype.hasOwnProperty.call(arguments[i], key)) { obj[key] = arguments[i][key]; } } } return obj; }, str2bool: function(str) { str = '' + str; switch (str.toLowerCase()) { case 'false': case 'no': case '0': case '': return false; default: return true; } }, fade_in: function(el) { if (el.style.opacity < 1) { el.style.opacity = (parseFloat(el.style.opacity) + 0.05).toFixed(2); win.setTimeout(function(){ Utils.fade_in(el); }, 50); } }, get_data_attribs: function(script) { var data = {}; if (Object.prototype.hasOwnProperty.call(script, 'dataset')) { data = script.dataset; } else { var attribs = script.attributes; var key; for (key in attribs) { if (Object.prototype.hasOwnProperty.call(attribs, key)) { var attr = attribs[key]; if (/^data-/.test(attr.name)) { var camelized = Utils.camelize(attr.name.substr(5)); data[camelized] = attr.value; } } } } return data; }, /** * "Standardizes" the options keys by converting and removing * any potential "dashed-property-name" into "dashedPropertyName". * In case both are present, the dashedPropertyName wins. */ normalize_keys: function(options_object) { var camelized = {}; for (var key in options_object) { if (Object.prototype.hasOwnProperty.call(options_object, key)) { var camelized_key = Utils.camelize(key); // TODO: could this break for "falsy" values within options_object? // avoiding "dashed-property-name" overriding a potentially existing "dashedPropertyName" camelized[camelized_key] = options_object[camelized_key] ? options_object[camelized_key] : options_object[key]; } } return camelized; }, camelize: function(str) { var separator = '-', match = str.indexOf(separator); while (match != -1) { var last = (match === (str.length - 1)), next = last ? '' : str[match + 1], upnext = next.toUpperCase(), sep_substr = last ? separator : separator + next; str = str.replace(sep_substr, upnext); match = str.indexOf(separator); } return str; }, find_script_by_id: function(id) { var scripts = doc.getElementsByTagName('script'); for (var i = 0, l = scripts.length; i < l; i++) { if (id === scripts[i].id) { return scripts[i]; } } return null; } }; var script_el_invoker = Utils.find_script_by_id('cookiebanner'); var Cookiebanner = context.Cookiebanner = function(opts) { this.init(opts); }; Cookiebanner.prototype = { // for testing stuff from the outside mostly cookiejar: Cookies, init: function(opts) { this.inserted = false; this.closed = false; this.test_mode = false; // TODO: implement var default_text = 'We use cookies to enhance your experience. ' + 'By continuing to visit this site you agree to our use of cookies.'; var default_link = 'Learn more'; this.default_options = { // autorun: true, cookie: 'cookiebanner-accepted', closeText: '✖', cookiePath: '/', debug: false, expires: Infinity, zindex: 255, mask: false, maskOpacity: 0.5, maskBackground: '#000', height: 'auto', minHeight: '21px', bg: '#000', fg: '#ddd', link: '#aaa', position: 'bottom', message: default_text, linkmsg: default_link, moreinfo: 'http://aboutcookies.org', effect: null, fontSize: '14px', fontFamily: 'arial, sans-serif', instance: global_instance_name, textAlign: 'center' }; this.options = this.default_options; this.script_el = script_el_invoker; if (this.script_el) { var data_options = Utils.get_data_attribs(this.script_el); this.options = Utils.merge(this.options, data_options); } // allowing opts passed to the ctor to override everything if (opts) { // mimics the "data-option-name" HTML attribute becoming // this.options.optionName opts = Utils.normalize_keys(opts); this.options = Utils.merge(this.options, opts); } // allows customizing the global instance name via options too global_instance_name = this.options.instance; // TODO: parse/validate other options that can benefit this.options.zindex = parseInt(this.options.zindex, 10); this.options.mask = Utils.str2bool(this.options.mask); // check for a possible global callback specified as a string if ('string' === typeof this.options.expires) { if ('function' === typeof context[this.options.expires]) { this.options.expires = context[this.options.expires]; } } // check if expires is a callback if ('function' === typeof this.options.expires) { // TODO: this might not always be as simple as this this.options.expires = this.options.expires(); } // Proceed with our plans only if we're invoked via a