Advertisement
qiTsuk

;___;

Feb 29th, 2016
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*global window:false, setTimeout:true, console:true */
  2. /*
  3. Copyright (C) 2013-2015 Good Code and Cookie Banner contributors
  4.  
  5. Permission is hereby granted, free of charge, to any person obtaining a copy
  6. of this software and associated documentation files (the "Software"), to deal
  7. in the Software without restriction, including without limitation the rights
  8. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. copies of the Software, and to permit persons to whom the Software is
  10. furnished to do so, subject to the following conditions:
  11.  
  12. The above copyright notice and this permission notice shall be included in
  13. all copies or substantial portions of the Software.
  14.  
  15. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. THE SOFTWARE.
  22. */
  23.  
  24. (function(context) {
  25.     'use strict';
  26.  
  27.     var win = context, doc = win.document;
  28.  
  29.     var global_instance_name = 'cbinstance';
  30.  
  31.     /*!
  32.      * contentloaded.js
  33.      *
  34.      * Author: Diego Perini (diego.perini at gmail.com)
  35.      * Summary: cross-browser wrapper for DOMContentLoaded
  36.      * Updated: 20101020
  37.      * License: MIT
  38.      * Version: 1.2
  39.      *
  40.      * URL:
  41.      * http://javascript.nwbox.com/ContentLoaded/
  42.      * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE
  43.      *
  44.      */
  45.     // @win window reference
  46.     // @fn function reference
  47.     function contentLoaded(win, fn) {
  48.         var done = false, top = true,
  49.         doc = win.document, root = doc.documentElement,
  50.  
  51.         add = doc.addEventListener ? 'addEventListener' : 'attachEvent',
  52.         rem = doc.addEventListener ? 'removeEventListener' : 'detachEvent',
  53.         pre = doc.addEventListener ? '' : 'on',
  54.  
  55.         init = function(e) {
  56.             if (e.type == 'readystatechange' && doc.readyState != 'complete') return;
  57.             (e.type == 'load' ? win : doc)[rem](pre + e.type, init, false);
  58.             if (!done && (done = true)) fn.call(win, e.type || e);
  59.         },
  60.  
  61.         poll = function() {
  62.             try { root.doScroll('left'); } catch(e) { setTimeout(poll, 50); return; }
  63.             init('poll');
  64.         };
  65.  
  66.         if (doc.readyState == 'complete') fn.call(win, 'lazy');
  67.         else {
  68.             if (doc.createEventObject && root.doScroll) {
  69.                 try { top = !win.frameElement; } catch(e) { }
  70.                 if (top) poll();
  71.             }
  72.             doc[add](pre + 'DOMContentLoaded', init, false);
  73.             doc[add](pre + 'readystatechange', init, false);
  74.             win[add](pre + 'load', init, false);
  75.         }
  76.     }
  77.  
  78.     var Cookies = {
  79.         get: function (key) {
  80.             return decodeURIComponent(doc.cookie.replace(new RegExp('(?:(?:^|.*;)\\s*' + encodeURIComponent(key).replace(/[\-\.\+\*]/g, '\\$&') + '\\s*\\=\\s*([^;]*).*$)|^.*$'), '$1')) || null;
  81.         },
  82.         set: function (key, val, end, path, domain, secure) {
  83.             if (!key || /^(?:expires|max\-age|path|domain|secure)$/i.test(key)) {
  84.                 return false;
  85.             }
  86.             var expires = '';
  87.             if (end) {
  88.                 switch (end.constructor) {
  89.                     case Number:
  90.                         expires = end === Infinity ? '; expires=Fri, 31 Dec 9999 23:59:59 GMT' : '; max-age=' + end;
  91.                         break;
  92.                     case String:
  93.                         expires = '; expires=' + end;
  94.                     break;
  95.                     case Date:
  96.                         expires = '; expires=' + end.toUTCString();
  97.                     break;
  98.                 }
  99.             }
  100.             doc.cookie = encodeURIComponent(key) + '=' + encodeURIComponent(val) + expires + (domain ? '; domain=' + domain : '') + (path ? '; path=' + path : '') + (secure ? '; secure' : '');
  101.             return true;
  102.         },
  103.         has: function (key) {
  104.             return (new RegExp('(?:^|;\\s*)' + encodeURIComponent(key).replace(/[\-\.\+\*]/g, '\\$&') + '\\s*\\=')).test(doc.cookie);
  105.         },
  106.         remove: function (key, path, domain) {
  107.             if (!key || !this.has(key)) { return false; }
  108.             doc.cookie = encodeURIComponent(key) + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT' + ( domain ? '; domain=' + domain : '') + ( path ? '; path=' + path : '');
  109.             return true;
  110.         }
  111.     };
  112.  
  113.     var Utils = {
  114.  
  115.         // merge objects and whatnot
  116.         merge: function(){
  117.             var obj = {},
  118.                 i = 0,
  119.                 al = arguments.length,
  120.                 key;
  121.             if (0 === al) {
  122.                 return obj;
  123.             }
  124.             for (; i < al; i++) {
  125.                 for (key in arguments[i]) {
  126.                     if (Object.prototype.hasOwnProperty.call(arguments[i], key)) {
  127.                         obj[key] = arguments[i][key];
  128.                     }
  129.                 }
  130.             }
  131.             return obj;
  132.         },
  133.  
  134.         str2bool: function(str) {
  135.             str = '' + str;
  136.             switch (str.toLowerCase()) {
  137.                 case 'false':
  138.                 case 'no':
  139.                 case '0':
  140.                 case '':
  141.                     return false;
  142.                 default:
  143.                     return true;
  144.                 }
  145.         },
  146.  
  147.         fade_in: function(el) {
  148.             if (el.style.opacity < 1) {
  149.                 el.style.opacity = (parseFloat(el.style.opacity) + 0.05).toFixed(2);
  150.                 win.setTimeout(function(){
  151.                     Utils.fade_in(el);
  152.                 }, 50);
  153.             }
  154.         },
  155.  
  156.         get_data_attribs: function(script) {
  157.             var data = {};
  158.             if (Object.prototype.hasOwnProperty.call(script, 'dataset')) {
  159.                 data = script.dataset;
  160.             } else {
  161.                 var attribs = script.attributes;
  162.                 var key;
  163.                 for (key in attribs) {
  164.                     if (Object.prototype.hasOwnProperty.call(attribs, key)) {
  165.                         var attr = attribs[key];
  166.                         if (/^data-/.test(attr.name)) {
  167.                             var camelized = Utils.camelize(attr.name.substr(5));
  168.                             data[camelized] = attr.value;
  169.                         }
  170.                     }
  171.                 }
  172.             }
  173.             return data;
  174.         },
  175.  
  176.         /**
  177.         * "Standardizes" the options keys by converting and removing
  178.         * any potential "dashed-property-name" into "dashedPropertyName".
  179.         * In case both are present, the dashedPropertyName wins.
  180.         */
  181.         normalize_keys: function(options_object) {
  182.             var camelized = {};
  183.             for (var key in options_object) {
  184.                 if (Object.prototype.hasOwnProperty.call(options_object, key)) {
  185.                     var camelized_key = Utils.camelize(key);
  186.                     // TODO: could this break for "falsy" values within options_object?
  187.                     // avoiding "dashed-property-name" overriding a potentially existing "dashedPropertyName"
  188.                     camelized[camelized_key] = options_object[camelized_key] ? options_object[camelized_key] : options_object[key];
  189.                 }
  190.             }
  191.             return camelized;
  192.         },
  193.  
  194.         camelize: function(str) {
  195.             var separator = '-',
  196.                 match = str.indexOf(separator);
  197.             while (match != -1) {
  198.                 var last = (match === (str.length - 1)),
  199.                     next = last ? '' : str[match + 1],
  200.                     upnext = next.toUpperCase(),
  201.                     sep_substr =  last ? separator : separator + next;
  202.                 str = str.replace(sep_substr, upnext);
  203.                 match = str.indexOf(separator);
  204.             }
  205.             return str;
  206.         },
  207.  
  208.         find_script_by_id: function(id) {
  209.             var scripts = doc.getElementsByTagName('script');
  210.             for (var i = 0, l = scripts.length; i < l; i++) {
  211.                 if (id === scripts[i].id) {
  212.                     return scripts[i];
  213.                 }
  214.             }
  215.             return null;
  216.         }
  217.  
  218.     };
  219.  
  220.     var script_el_invoker = Utils.find_script_by_id('cookiebanner');
  221.  
  222.     var Cookiebanner = context.Cookiebanner = function(opts) {
  223.         this.init(opts);
  224.     };
  225.  
  226.     Cookiebanner.prototype = {
  227.  
  228.         // for testing stuff from the outside mostly
  229.         cookiejar: Cookies,
  230.  
  231.         init: function(opts) {
  232.  
  233.             this.inserted = false;
  234.             this.closed = false;
  235.             this.test_mode = false; // TODO: implement
  236.  
  237.             var default_text = 'Cookies er nødvendige for at få hjemmesiden til at fungere, ' +
  238.             'men de giver også info om hvordan du bruger vores hjemmeside, så vi kan forbedre den både for dig og for andre.' +
  239.             ' Cookies på denne hjemmeside bruges primært til login håndtering trafikmåling og optimering af sidens indhold.'
  240.             var default_link = '<br>Læs mere om vores coookie politik her';
  241.  
  242.             this.default_options = {
  243.                 // autorun: true,
  244.                 cookie: 'cookiebanner-accepted',
  245.                 closeText: '&#10006;',
  246.                 cookiePath: '/',
  247.                 debug: false,
  248.                 expires: Infinity,
  249.                 zindex: 255,
  250.                 mask: false,
  251.                 maskOpacity: 0.5,
  252.                 maskBackground: '#000',
  253.                 height: 'auto',
  254.                 minHeight: '21px',
  255.                 bg: '#000',
  256.                 fg: '#ddd',
  257.                 link: '#aaa',
  258.                 position: 'bottom',
  259.                 message: default_text,
  260.                 linkmsg: default_link,
  261.                 moreinfo: 'https://dkwebcam.dk/faq/user/64',
  262.                 effect: null,
  263.                 fontSize: '14px',
  264.                 fontFamily: 'arial, sans-serif',
  265.                 instance: global_instance_name,
  266.                 textAlign: 'center',
  267.                 acceptOnScroll: false,
  268.                 acceptOnClick: true
  269.             };
  270.  
  271.             this.options = this.default_options;
  272.             this.script_el = script_el_invoker;
  273.  
  274.             if (this.script_el) {
  275.                 var data_options = Utils.get_data_attribs(this.script_el);
  276.                 this.options = Utils.merge(this.options, data_options);
  277.             }
  278.  
  279.             // allowing opts passed to the ctor to override everything
  280.             if (opts) {
  281.                 // mimics the "data-option-name" HTML attribute becoming
  282.                 // this.options.optionName
  283.                 opts = Utils.normalize_keys(opts);
  284.                 this.options = Utils.merge(this.options, opts);
  285.             }
  286.  
  287.             // allows customizing the global instance name via options too
  288.             global_instance_name = this.options.instance;
  289.  
  290.             // TODO: parse/validate other options that can benefit
  291.             this.options.zindex = parseInt(this.options.zindex, 10);
  292.             this.options.mask = Utils.str2bool(this.options.mask);
  293.  
  294.             // check for a possible global callback specified as a string
  295.             if ('string' === typeof this.options.expires) {
  296.                 if ('function' === typeof context[this.options.expires]) {
  297.                     this.options.expires = context[this.options.expires];
  298.                 }
  299.             }
  300.  
  301.             // check if expires is a callback
  302.             if ('function' === typeof this.options.expires) {
  303.                 // TODO: this might not always be as simple as this
  304.                 this.options.expires = this.options.expires();
  305.             }
  306.  
  307.             // Proceed with our plans only if we're invoked via a <script> element
  308.             // that has the required id attribute.
  309.             // For manually created instances one must call run() explicitly.
  310.             if (this.script_el) {
  311.                 this.run();
  312.             }
  313.         },
  314.  
  315.         log: function(){
  316.             if ('undefined' !== typeof console) {
  317.                 console.log.apply(console, arguments);
  318.             }
  319.         },
  320.  
  321.         run: function() {
  322.             if (!this.agreed()) {
  323.                 var self = this;
  324.                 contentLoaded(win, function(){
  325.                     self.insert();
  326.                 });
  327.             }
  328.         },
  329.  
  330.         build_viewport_mask: function() {
  331.             var mask = null;
  332.             if (true === this.options.mask) {
  333.                 var mask_opacity = this.options.maskOpacity;
  334.                 var bg = this.options.maskBackground;
  335.                 var mask_markup = '<div id="cookiebanner-mask" style="' +
  336.                     'position:fixed;top:0;left:0;width:100%;height:100%;' +
  337.                     'background:' + bg + ';zoom:1;filter:alpha(opacity=' +
  338.                     (mask_opacity * 100) +');opacity:' + mask_opacity +';' +
  339.                     'z-index:' + this.options.zindex +';"></div>';
  340.                 var el = doc.createElement('div');
  341.                 el.innerHTML = mask_markup;
  342.                 mask = el.firstChild;
  343.             }
  344.             return mask;
  345.         },
  346.  
  347.         agree: function() {
  348.             this.cookiejar.set(this.options.cookie, 1, this.options.expires, this.options.cookiePath);
  349.             return true;
  350.         },
  351.  
  352.         agreed: function(){
  353.             return this.cookiejar.has(this.options.cookie);
  354.         },
  355.  
  356.         close: function() {
  357.             if (this.inserted) {
  358.                 if (!this.closed) {
  359.                     if (this.element) {
  360.                         this.element.parentNode.removeChild(this.element);
  361.                     }
  362.                     if (this.element_mask) {
  363.                         this.element_mask.parentNode.removeChild(this.element_mask);
  364.                     }
  365.                     this.closed = true;
  366.                 }
  367.             }/* else {
  368.                 throw new Error("Not inserted but closing?!");
  369.             }*/
  370.             return this.closed;
  371.         },
  372.  
  373.         agree_and_close:function() {
  374.             this.agree();
  375.             return this.close();
  376.         },
  377.  
  378.         // close and remove every trace of ourselves completely
  379.         cleanup: function() {
  380.             this.close();
  381.             return this.unload();
  382.         },
  383.  
  384.         unload: function() {
  385.             if (this.script_el) {
  386.                 this.script_el.parentNode.removeChild(this.script_el);
  387.             }
  388.             context[global_instance_name] = undefined;
  389.             // delete context[global_instance_name];
  390.             return true;
  391.         },
  392.  
  393.         insert: function() {
  394.             this.element_mask = this.build_viewport_mask();
  395.  
  396.             var zidx = this.options.zindex;
  397.  
  398.             if (this.element_mask) {
  399.                 // bump notice element's zindex so it's above the mask
  400.                 zidx += 1;
  401.             }
  402.  
  403.             var el = doc.createElement('div');
  404.             el.className = 'cookiebanner';
  405.             el.style.position = 'fixed';
  406.             el.style.left = 0;
  407.             el.style.right = 0;
  408.             el.style.height = this.options.height;
  409.             el.style.minHeight = this.options.minHeight;
  410.             el.style.zIndex = zidx;
  411.             el.style.background = this.options.bg;
  412.             el.style.color = this.options.fg;
  413.             el.style.lineHeight = el.style.minHeight;
  414.  
  415.             el.style.padding = '5px 16px';
  416.  
  417.             el.style.fontFamily = this.options.fontFamily;
  418.             el.style.fontSize = this.options.fontSize;
  419.             el.style.textAlign = this.options.textAlign;
  420.  
  421.             if ('top' === this.options.position) {
  422.                 el.style.top = 0;
  423.             } else {
  424.                 el.style.bottom = 0;
  425.             }
  426.  
  427.             el.innerHTML = '<div class="cookiebanner-close" style="float:right;padding-left:5px;">' +
  428.                 this.options.closeText + '</div>' +
  429.                 '<span>' + this.options.message + ' <a>' + this.options.linkmsg + '</a></span>';
  430.  
  431.             this.element = el;
  432.  
  433.             var el_a = el.getElementsByTagName('a')[0];
  434.             el_a.href = this.options.moreinfo;
  435.             el_a.target = '_blank';
  436.             el_a.style.textDecoration = 'none';
  437.             el_a.style.color = this.options.link;
  438.  
  439.             var el_x = el.getElementsByTagName('div')[0];
  440.             el_x.style.cursor = 'pointer';
  441.  
  442.             function on(el, ev, fn) {
  443.                 var add = el.addEventListener ? 'addEventListener' : 'attachEvent',
  444.                     pre = el.addEventListener ? '' : 'on';
  445.                 el[add](pre + ev, fn, false);
  446.             }
  447.  
  448.             var self = this;
  449.             on(el_x, 'click', function(){
  450.                 self.agree_and_close();
  451.             });
  452.  
  453.             if (this.element_mask) {
  454.                 on(this.element_mask, 'click', function(){
  455.                     self.agree_and_close();
  456.                 });
  457.                 doc.body.appendChild(this.element_mask);
  458.             }
  459.  
  460.             // Agree and close banner on window scroll if `acceptOnScroll` option is set `true`
  461.             if (this.options.acceptOnScroll) {
  462.               on(window, 'scroll', function(){
  463.                 self.agree_and_close();
  464.               });
  465.             }
  466.            
  467.             // Agree and close banner on click (no matter where) if `acceptOnClick` option is set `true`
  468.             if (this.options.acceptOnClick) {
  469.               on(window, 'click', function(){
  470.                 self.agree_and_close();
  471.               });
  472.             }
  473.            
  474.             doc.body.appendChild(this.element);
  475.             this.inserted = true;
  476.  
  477.             if ('fade' === this.options.effect) {
  478.                 this.element.style.opacity = 0;
  479.                 Utils.fade_in(this.element);
  480.             } else {
  481.                 this.element.style.opacity = 1;
  482.             }
  483.         }
  484.  
  485.     };
  486.  
  487.     if (script_el_invoker) {
  488.         if (!context[global_instance_name]) {
  489.             context[global_instance_name] = new Cookiebanner();
  490.         }
  491.     }
  492.  
  493. })(window);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement