Browse Source

Merge branch 'master' into feature/visiblee

Amauri CHAMPEAUX 3 năm trước cách đây
mục cha
commit
83d30f2000
4 tập tin đã thay đổi với 270 bổ sung24 xóa
  1. 84 0
      lang/tarteaucitron.lt.js
  2. 1 0
      package.json
  3. 62 23
      tarteaucitron.js
  4. 123 1
      tarteaucitron.services.js

+ 84 - 0
lang/tarteaucitron.lt.js

@@ -0,0 +1,84 @@
+/*global tarteaucitron */
+tarteaucitron.lang = {
+    "middleBarHead": "☝ 🍪",
+    "adblock": "Sveiki! Ši svetainė veikia skaidriai ir leidžia pasirinkti trečiosios šalies paslaugas, kurias norite leisti.",
+    "adblock_call": "Norėdami pradėti taikyti, išjunkite ,Adblocker",
+    "reload": "Atnaujinkite puslapį",
+    
+    "alertBigScroll": "Tęsiant slankiojimą",
+    "alertBigClick": "Jei ir toliau naršote šioje svetainėje,",
+    "alertBig": "leidžiate naudotis visomis trečiųjų šalių paslaugomis",
+    
+    "alertBigPrivacy": "Ši svetainė naudoja slapukus ir suteikia jums galimybę valdyti, ką norite suaktyvinti",
+    "alertSmall": "Tvarkykite paslaugas",
+    "personalize": "Suasmeninkite",
+    "acceptAll": "Gerai, priimu visus",
+    "close": "Uždaryti",
+
+    "privacyUrl": "Privatumo politika",
+
+    "all": "Pirmenybė visoms paslaugoms",
+
+    "info": "Jūsų privatumo apsauga",
+    "disclaimer": "Leisdami šias trečiųjų šalių paslaugas, jūs sutinkate su jų slapukais ir sekimo technologijų naudojimu, reikalingu jų tinkamam veikimui.",
+    "allow": "Leisti",
+    "deny": "Atsisakyti",
+    "noCookie": "Ši paslauga nenaudoja slapukų.",
+    "useCookie": "Ši paslauga gali būti įdiegta",
+    "useCookieCurrent": "Ši paslauga įdiegta",
+    "useNoCookie": "Ši paslauga neįdiegė jokių slapukų.",
+    "more": "Skaityti daugiau",
+    "source": "Peržiūrėkite oficialią svetainę",
+    "credit": "Slapukų tvarkyklė, kurią pateikė tarteaucitron.js",
+    "noServices": "Šioje svetainėje nenaudojami jokie slapukai, kuriems reikalingas jūsų sutikimas.",
+
+    "toggleInfoBox": "Rodyti / slėpti informaciją apie slapukų saugojimą",
+    "title": "Slapukų valdymo skydelis",
+    "cookieDetail": "Išsami slapuko informacija",
+    "ourSite": "mūsų svetainėje",
+    "newWindow": "(naujas langas)",
+    "allowAll": "Leisti visus slapukus",
+    "denyAll": "Atsisakyti visų slapukų",
+
+    "icon": "Cookies",
+
+    "fallback": "yra išjungtas.",
+    "allowed": "leidžiama",
+    "disallowed": "neleidžiama",
+
+    "ads": {
+        "title": "Reklamos tinklas",
+        "details": "Reklamos tinklai gali gauti pajamų, parduodami reklamos vietą svetainėje."
+    },
+    "analytic": {
+        "title": "Auditorijos matavimas",
+        "details": "Naudotos auditorijos vertinimo paslaugos generuoti naudingą statistinį lankomumą svetainės veiklos patobulinimui."
+    },
+    "social": {
+        "title": "Socialiniai tinklai",
+        "details": "Socialiniai tinklai gali pagerinti svetainės naudojimą ir padėti ją reklamuoti per akcijas."
+    },
+    "video": {
+        "title": "Vaizdo įrašai",
+        "details": "Vaizdo įrašų bendrinimo paslaugos padeda pritraukti gausesnę media į svetainę ir padidinti jos matomumą."
+    },
+    "comment": {
+        "title": "Komentarai",
+        "details": "Komentarų valdytojai palengvina komentarų sisteminimą ir kovoja su šlamštu."
+    },
+    "support": {
+        "title": "Pagalba",
+        "details": "Pagalbos paslaugos leidžia jums susisiekti su svetainės komanda ir padėti ją tobulinti."
+    },
+    "api": {
+        "title": "APIs (Aplikacijų programavimo sąsajos)",
+        "details": "API naudojamos tekstams įkelti: geografinė padėtis, paieškos sistemos, vertimai, ..."
+    },
+    "other": {
+        "title": "Kita",
+        "details": "Paslaugos, rodančios svetainės turinį."
+    },
+    
+    "mandatoryTitle": "Privalomi slapukai",
+    "mandatoryText": "Ši svetainė naudoja slapukus, reikalingus tinkamam jos veikimui, kurių negalima išjungti."
+};

+ 1 - 0
package.json

@@ -1,6 +1,7 @@
 {
   "name": "tarteaucitronjs",
   "version": "1.9.1",
+  "main": "tarteaucitron.js",
   "description": "Comply to the European cookie law",
   "dependencies": {},
   "devDependencies": {},

+ 62 - 23
tarteaucitron.js

@@ -293,7 +293,7 @@ var tarteaucitron = {
                     }
                     document.getElementsByTagName('head')[0].appendChild(customThemePopup);
                 }
-                
+
                 var body = document.body,
                     div = document.createElement('div'),
                     html = '',
@@ -311,7 +311,7 @@ var tarteaucitron = {
                 // Step 3: prepare the html
                 html += '<div id="tarteaucitronPremium"></div>';
                 html += '<button type="button" id="tarteaucitronBack" aria-label="' + tarteaucitron.lang.close + '"></button>';
-                html += '<div id="tarteaucitron" role="dialog" aria-labelledby="dialogTitle">';
+                html += '<div id="tarteaucitron" role="dialog" aria-modal="true" aria-describedby="tarteaucitronInfo" aria-labelledby="dialogTitle" tabindex="-1">';
                 html += '   <button type="button" id="tarteaucitronClosePanel">';
                 html += '       ' + tarteaucitron.lang.close;
                 html += '   </button>';
@@ -622,15 +622,15 @@ var tarteaucitron = {
                             var html = '';
                             html += '<li  class="tarteaucitronLine">';
                             html += '   <div class="tarteaucitronName">';
-                            html += '       <span class="tarteaucitronH3" role="heading" aria-level="3">'+tarteaucitron.lang[cat].title+'</span>';
+                            html += '       <span class="tarteaucitronH3" role="heading" aria-level="2">'+tarteaucitron.lang[cat].title+'</span>';
                             html += '       <span>'+tarteaucitron.lang[cat].details+'</span>';
-                            html += '   <button type="button" class="tarteaucitron-toggle-group" id="tarteaucitron-toggle-group-'+cat+'">'+tarteaucitron.lang.alertSmall+' ('+document.getElementById("tarteaucitronServices_"+cat).childElementCount+')</button>';
+                            html += '   <button type="button" aria-expanded="false" class="tarteaucitron-toggle-group" id="tarteaucitron-toggle-group-'+cat+'">'+tarteaucitron.lang.alertSmall+' ('+document.getElementById("tarteaucitronServices_"+cat).childElementCount+')</button>';
                             html += '   </div>';
                             html += '   <div class="tarteaucitronAsk" id="tarteaucitron-group-'+cat+'">';
-                            html += '       <button type="button"  class="tarteaucitronAllow" id="tarteaucitron-accept-group-'+cat+'">';
+                            html += '       <button type="button" aria-label="' + tarteaucitron.lang.allow + ' ' + tarteaucitron.lang[cat].title + '" class="tarteaucitronAllow" id="tarteaucitron-accept-group-'+cat+'">';
                             html += '           <span class="tarteaucitronCheck"></span> ' + tarteaucitron.lang.allow;
                             html += '       </button> ';
-                            html += '       <button type="button"  class="tarteaucitronDeny" id="tarteaucitron-reject-group-'+cat+'">';
+                            html += '       <button type="button" aria-label="' + tarteaucitron.lang.deny + ' ' + tarteaucitron.lang[cat].title + '" class="tarteaucitronDeny" id="tarteaucitron-reject-group-'+cat+'">';
                             html += '           <span class="tarteaucitronCross"></span> ' + tarteaucitron.lang.deny;
                             html += '       </button>';
                             html += '   </div>';
@@ -643,8 +643,10 @@ var tarteaucitron = {
                                 tarteaucitron.userInterface.toggle('tarteaucitronServices_' + cat);
                                if (document.getElementById('tarteaucitronServices_' + cat).style.display == 'block') {
                                     tarteaucitron.userInterface.addClass('tarteaucitronServicesTitle_' + cat, 'tarteaucitronIsExpanded');
+                                    document.getElementById('tarteaucitron-toggle-group-'+cat).setAttribute('aria-expanded', 'true');
                                 } else {
                                     tarteaucitron.userInterface.removeClass('tarteaucitronServicesTitle_' + cat, 'tarteaucitronIsExpanded');
+                                    document.getElementById('tarteaucitron-toggle-group-'+cat).setAttribute('aria-expanded', 'false');
                                 }
                             });
                             tarteaucitron.addClickEventToId("tarteaucitron-accept-group-" + cat, function () {
@@ -660,7 +662,7 @@ var tarteaucitron = {
 
                 // add a little timeout to be sure everything is accessible
                 setTimeout(function () {
-                    
+
                     // Setup events
                     tarteaucitron.addClickEventToId("tarteaucitronCloseCross", function () {
                         tarteaucitron.userInterface.closeAlert();
@@ -735,7 +737,7 @@ var tarteaucitron = {
                         tarteaucitron.events.load();
                     }
                 }, 500);
-                
+
             });
         });
     },
@@ -778,17 +780,17 @@ var tarteaucitron = {
                 html += '           ' + tarteaucitron.lang.more;
                 html += '       </a>';
                 html += '       <span class="tarteaucitronReadmoreSeparator"> - </span>';
-                html += '       <a href="' + service.uri + '" target="_blank" rel="noreferrer noopener" title="' + service.name + ' ' + tarteaucitron.lang.newWindow + '" class="tarteaucitronReadmoreOfficial">';
+                html += '       <a href="' + service.uri + '" target="_blank" rel="noreferrer noopener" title="' + tarteaucitron.lang.source + ' ' + service.name + ' ' + tarteaucitron.lang.newWindow + '" class="tarteaucitronReadmoreOfficial">';
                 html += '           ' + tarteaucitron.lang.source;
                 html += '       </a>';
             }
 
             html += '   </div>';
             html += '   <div class="tarteaucitronAsk">';
-            html += '       <button type="button" id="' + service.key + 'Allowed" class="tarteaucitronAllow">';
+            html += '       <button type="button" aria-label="' + tarteaucitron.lang.allow + ' ' + service.name + '" id="' + service.key + 'Allowed" class="tarteaucitronAllow">';
             html += '           <span class="tarteaucitronCheck"></span> ' + tarteaucitron.lang.allow;
             html += '       </button> ';
-            html += '       <button type="button" id="' + service.key + 'Denied" class="tarteaucitronDeny">';
+            html += '       <button type="button" aria-label="' + tarteaucitron.lang.deny + ' ' + service.name + '" id="' + service.key + 'Denied" class="tarteaucitronDeny">';
             html += '           <span class="tarteaucitronCross"></span> ' + tarteaucitron.lang.deny;
             html += '       </button>';
             html += '   </div>';
@@ -909,12 +911,12 @@ var tarteaucitron = {
                 } else {
 
                     document.getElementById(id).style[property] = value;
-                    
+
                     if (property == "display" && value == "block" && (id == "tarteaucitron" || id == "tarteaucitronAlertBig")) {
                         document.getElementById(id).style["opacity"] = "0";
                         setTimeout(function() {document.getElementById(id).style["opacity"] = "1";}, 1);
                     }
-                    
+
                     if (property == "display" && value == "block" && id == "tarteaucitronBack") {
                         document.getElementById(id).style["opacity"] = "0";
                         setTimeout(function() {document.getElementById(id).style["opacity"] = "0.7";}, 1);
@@ -1031,9 +1033,16 @@ var tarteaucitron = {
             if (status === true) {
                 tarteaucitron.userInterface.addClass(key + 'Line', 'tarteaucitronIsAllowed');
                 tarteaucitron.userInterface.removeClass(key + 'Line', 'tarteaucitronIsDenied');
+                document.getElementById(key + 'Allowed').setAttribute('aria-pressed', 'true');
+                document.getElementById(key + 'Denied').setAttribute('aria-pressed', 'false');
             } else if (status === false) {
                 tarteaucitron.userInterface.removeClass(key + 'Line', 'tarteaucitronIsAllowed');
                 tarteaucitron.userInterface.addClass(key + 'Line', 'tarteaucitronIsDenied');
+                document.getElementById(key + 'Allowed').setAttribute('aria-pressed', 'false');
+                document.getElementById(key + 'Denied').setAttribute('aria-pressed', 'true');
+            } else {
+                document.getElementById(key + 'Allowed').setAttribute('aria-pressed', 'false');
+                document.getElementById(key + 'Denied').setAttribute('aria-pressed', 'false');
             }
 
             // check if all services are allowed
@@ -1065,18 +1074,29 @@ var tarteaucitron = {
 
                 tarteaucitron.userInterface.addClass(c + 'MainLineOffset', c + 'IsAllowed');
                 tarteaucitron.userInterface.removeClass(c + 'MainLineOffset', c + 'IsDenied');
+
+                document.getElementById(c + 'AllDenied').setAttribute('aria-pressed', 'false');
+                document.getElementById(c + 'AllAllowed').setAttribute('aria-pressed', 'true');
+
             } else if (nbAllowed === 0 && nbPending === 0) {
                 tarteaucitron.userInterface.removeClass(c + 'AllAllowed', c + 'IsSelected');
                 tarteaucitron.userInterface.addClass(c + 'AllDenied', c + 'IsSelected');
 
                 tarteaucitron.userInterface.removeClass(c + 'MainLineOffset', c + 'IsAllowed');
                 tarteaucitron.userInterface.addClass(c + 'MainLineOffset', c + 'IsDenied');
+
+                document.getElementById(c + 'AllDenied').setAttribute('aria-pressed', 'true');
+                document.getElementById(c + 'AllAllowed').setAttribute('aria-pressed', 'false');
+
             } else {
                 tarteaucitron.userInterface.removeClass(c + 'AllAllowed', c + 'IsSelected');
                 tarteaucitron.userInterface.removeClass(c + 'AllDenied', c + 'IsSelected');
 
                 tarteaucitron.userInterface.removeClass(c + 'MainLineOffset', c + 'IsAllowed');
                 tarteaucitron.userInterface.removeClass(c + 'MainLineOffset', c + 'IsDenied');
+
+                document.getElementById(c + 'AllDenied').setAttribute('aria-pressed', 'false');
+                document.getElementById(c + 'AllAllowed').setAttribute('aria-pressed', 'false');
             }
 
             // close the alert if all service have been reviewed
@@ -1111,26 +1131,41 @@ var tarteaucitron = {
                     groupallowed = 0;
                 for (var ii = 0; ii < doc.children.length; ii++) {
                     if (doc.children[ii].className == "tarteaucitronLine tarteaucitronIsDenied") {
-                        groupdenied++;                        
+                        groupdenied++;
                     }
                     if (doc.children[ii].className == "tarteaucitronLine tarteaucitronIsAllowed") {
-                        groupallowed++;                        
+                        groupallowed++;
                     }
                 }
                 if (total === groupallowed) {
                     tarteaucitron.userInterface.removeClass('tarteaucitron-group-'+cat, 'tarteaucitronIsDenied');
                     tarteaucitron.userInterface.addClass('tarteaucitron-group-'+cat, 'tarteaucitronIsAllowed');
+
+                    if (document.getElementById('tarteaucitron-reject-group-'+cat)) {
+                        document.getElementById('tarteaucitron-reject-group-'+cat).setAttribute('aria-pressed', 'false');
+                        document.getElementById('tarteaucitron-accept-group-'+cat).setAttribute('aria-pressed', 'true');
+                    }
                 }
                 if (total === groupdenied) {
                     tarteaucitron.userInterface.addClass('tarteaucitron-group-'+cat, 'tarteaucitronIsDenied');
                     tarteaucitron.userInterface.removeClass('tarteaucitron-group-'+cat, 'tarteaucitronIsAllowed');
+
+                    if (document.getElementById('tarteaucitron-reject-group-'+cat)) {
+                        document.getElementById('tarteaucitron-reject-group-'+cat).setAttribute('aria-pressed', 'true');
+                        document.getElementById('tarteaucitron-accept-group-'+cat).setAttribute('aria-pressed', 'false');
+                    }
                 }
                 if (total !== groupdenied && total !== groupallowed) {
                     tarteaucitron.userInterface.removeClass('tarteaucitron-group-'+cat, 'tarteaucitronIsDenied');
                     tarteaucitron.userInterface.removeClass('tarteaucitron-group-'+cat, 'tarteaucitronIsAllowed');
+
+                    if (document.getElementById('tarteaucitron-reject-group-'+cat)) {
+                        document.getElementById('tarteaucitron-reject-group-'+cat).setAttribute('aria-pressed', 'false');
+                        document.getElementById('tarteaucitron-accept-group-'+cat).setAttribute('aria-pressed', 'false');
+                    }
                 }
-                groupdenied = 0;   
-                groupallowed = 0; 
+                groupdenied = 0;
+                groupallowed = 0;
             });
 
         },
@@ -1534,9 +1569,13 @@ var tarteaucitron = {
             var i;
 
             for (i = 0; i < arr.length; i += 1) {
-                document.cookie = arr[i] + '=; expires=Thu, 01 Jan 2000 00:00:00 GMT; path=/;';
-                document.cookie = arr[i] + '=; expires=Thu, 01 Jan 2000 00:00:00 GMT; path=/; domain=.' + location.hostname + ';';
-                document.cookie = arr[i] + '=; expires=Thu, 01 Jan 2000 00:00:00 GMT; path=/; domain=.' + location.hostname.split('.').slice(-2).join('.') + ';';
+
+                var rgxpCookie = new RegExp("^(.*;)?\\s*" + arr[i] + "\\s*=\\s*[^;]+(.*)?$");
+                if (document.cookie.match(rgxpCookie)) {
+                    document.cookie = arr[i] + '=; expires=Thu, 01 Jan 2000 00:00:00 GMT; path=/;';
+                    document.cookie = arr[i] + '=; expires=Thu, 01 Jan 2000 00:00:00 GMT; path=/; domain=.' + location.hostname + ';';
+                    document.cookie = arr[i] + '=; expires=Thu, 01 Jan 2000 00:00:00 GMT; path=/; domain=.' + location.hostname.split('.').slice(-2).join('.') + ';';
+                }
             }
         },
         "checkCount": function (key) {
@@ -1690,7 +1729,7 @@ var tarteaucitron = {
     "getLanguage": function () {
         "use strict";
 
-        var availableLanguages = 'bg,ca,cn,cs,da,de,el,en,es,fi,fr,hu,it,ja,lv,nl,no,oc,pl,pt,ro,ru,se,sk,sv,tr,vi,zh',
+        var availableLanguages = 'bg,ca,cn,cs,da,de,el,en,es,fi,fr,hu,it,ja,lt,lv,nl,no,oc,pl,pt,ro,ru,se,sk,sv,tr,vi,zh',
             defaultLanguage = 'en';
 
         if (tarteaucitronForceLanguage !== '') {
@@ -1911,7 +1950,7 @@ var tarteaucitron = {
     },
     "proPing": function () {
         "use strict";
-        if (tarteaucitron.uuid !== '' && tarteaucitron.uuid !== undefined && tarteaucitron.proTemp !== '') {
+        if (tarteaucitron.uuid !== '' && tarteaucitron.uuid !== undefined && tarteaucitron.proTemp !== '' && tarteaucitronStatsEnabled) {
             var div = document.getElementById('tarteaucitronPremium'),
                 timestamp = new Date().getTime(),
                 url = 'https://tarteaucitron.io/log/?';
@@ -1936,7 +1975,7 @@ var tarteaucitron = {
         /**
          Utility function to Add or update the fields of obj1 with the ones in obj2
          */
-        for(key in custom){
+        for(var key in custom){
             if(custom[key] instanceof Object){
                 source[key] = tarteaucitron.AddOrUpdate(source[key], custom[key]);
             }else{

+ 123 - 1
tarteaucitron.services.js

@@ -1838,6 +1838,71 @@ tarteaucitron.services.gtag = {
     }
 };
 
+tarteaucitron.services.firebase = {
+    "key": "firebase",
+    "type": "analytic",
+    "name": "Firebase",
+    "uri": "https://firebase.google.com/support/privacy",
+    "needConsent": true,
+    "cookies": [],
+    "js": function () {
+        "use strict";
+
+        if (tarteaucitron.user.firebaseApiKey === undefined) {
+            return;
+        }
+
+        tarteaucitron.addScript('https://www.gstatic.com/firebasejs/8.6.2/firebase-app.js', '', function() {
+            tarteaucitron.addScript('https://www.gstatic.com/firebasejs/8.6.2/firebase-analytics.js', '', function() {
+
+                var firebaseConfig = {
+                  apiKey: tarteaucitron.user.firebaseApiKey,
+                  authDomain: tarteaucitron.user.firebaseAuthDomain,
+                  databaseURL: tarteaucitron.user.firebaseDatabaseUrl,
+                  projectId: tarteaucitron.user.firebaseProjectId,
+                  storageBucket: tarteaucitron.user.firebaseStorageBucket,
+                  appId: tarteaucitron.user.firebaseAppId,
+                  measurementId: tarteaucitron.user.firebaseMeasurementId,
+                };
+                firebase.initializeApp(firebaseConfig);
+                firebase.analytics();
+            });
+        });
+    }
+};
+
+// genially
+tarteaucitron.services.genially = {
+    "key": "genially",
+    "type": "api",
+    "name": "genially",
+    "uri": "https://www.genial.ly/cookies",
+    "needConsent": true,
+    "cookies": ['_gat', '_ga', '_gid'],
+    "js": function () {
+        "use strict";
+
+        tarteaucitron.fallback(['tac_genially'], function (x) {
+            var frame_title = tarteaucitron.fixSelfXSS(x.getAttribute("title") || 'genially iframe'),
+                width = x.getAttribute("width"),
+                height = x.getAttribute("height"),
+                geniallyid = x.getAttribute("geniallyid"),
+                allowfullscreen= x.getAttribute("allowfullscreen");
+
+            return '<div style="position: relative; padding-bottom: 109.00%; padding-top: 0; height: 0;"><iframe style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;" title="' + frame_title + '" src="https://view.genial.ly/' + geniallyid + '" width="' + width + '" height="' + height + '" scrolling="auto" allowtransparency ' + (allowfullscreen == '0' ? '' : ' webkitallowfullscreen mozallowfullscreen allowfullscreen') + '></iframe></div>';
+        });
+    },
+    "fallback": function () {
+        "use strict";
+        var id = 'genially';
+        tarteaucitron.fallback(['tac_genially'], function (elem) {
+            elem.style.width = elem.getAttribute('width') + 'px';
+            elem.style.height = elem.getAttribute('height') + 'px';
+            return tarteaucitron.engage(id);
+        });
+    }
+};
+
 // google maps
 tarteaucitron.services.googlemaps = {
     "key": "googlemaps",
@@ -1872,6 +1937,7 @@ tarteaucitron.services.googlemaps = {
                 return '<div id="' + uniqId + '" zoom="' + x.getAttribute('zoom') + '" latitude="' + x.getAttribute('latitude') + '" longitude="' + x.getAttribute('longitude') + '" style="width:' + x.offsetWidth + 'px;height:' + x.offsetHeight + 'px"></div>';
             });
 
+            var i;
             for (i = 0; i < uniqIds.length; i += 1) {
                 mapOptions = {
                     zoom: parseInt(document.getElementById(uniqIds[i]).getAttribute('zoom'), 10),
@@ -2847,6 +2913,7 @@ tarteaucitron.services.twitterembed = {
         });
 
         tarteaucitron.addScript('//platform.twitter.com/widgets.js', 'twitter-wjs', function () {
+            var i;
             for (i = 0; i < uniqIds.length; i += 1) {
                 e = document.getElementById(uniqIds[i]);
                 twttr.widgets.createTweet(
@@ -4061,7 +4128,7 @@ tarteaucitron.services.youtubeapi = {
     "key": "youtubeapi",
     "type": "video",
     "name": "Youtube (Js API)",
-    "uri": "https://policies.google.com/privacy/",
+    "uri": "https://policies.google.com/privacy",
     "needConsent": true,
     "cookies": [],
     "js": function () {
@@ -4209,3 +4276,58 @@ tarteaucitron.services.visiblee = {
         tarteaucitron.addScript('//www.link-page.info/tracking_'+tarteaucitron.user.visibleeclientid+'.js', 'visiblee');
     }
 };
+
+// bandcamp
+tarteaucitron.services.bandcamp = {
+    key: "bandcamp",
+    type: "video",
+    name: "Bandcamp",
+    uri: "https://bandcamp.com",
+    readmoreLink: "https://bandcamp.com/privacy",
+    needConsent: true,
+    cookies: ['client_id', 'BACKENDID', '_comm_playlist'],
+    js: function () {
+        "use strict";
+        tarteaucitron.fallback(['bandcamp_player'], function (x) {
+            var frame_title = tarteaucitron.fixSelfXSS(x.getAttribute("title") || 'Bandcamp iframe'),
+                album_id        = x.getAttribute("albumID"),
+                bandcamp_width  = x.getAttribute("width"),
+                frame_width     = 'width=',
+                bandcamp_height = x.getAttribute("height"),
+                frame_height    = 'height=',
+                attrs = ["size", "bgcol", "linkcol", "artwork", "minimal", "tracklist", "package", "transparent"],
+                params = attrs.filter(function (a) {
+                    return x.getAttribute(a) !== null;
+                }).map(function (a) {
+                    if (a && a.length > 0) return a + "=" + x.getAttribute(a);
+                }).join("/");
+
+                if (album_id === null) {
+                    return "";
+                }
+
+                if (bandcamp_width !== null || bandcamp_width !== "") {
+                    frame_width += '"' + bandcamp_width + '" ';
+                } else {
+                    frame_width += '"" ';
+                }
+                if (bandcamp_height !== null || bandcamp_height !== "") {
+                    frame_height += '"' + bandcamp_height + '" ';
+                } else {
+                    frame_height += '"" ';
+                }
+
+                var src = 'https://bandcamp.com/EmbeddedPlayer/album=' + album_id + '/' + params;
+
+                return '<iframe title="' + frame_title + '"' + frame_width + frame_height + 'src="' + src + '" frameborder="0" allowfullscreen seamless></iframe>';
+        });
+    },
+    fallback: function () {
+        "use strict";
+        tarteaucitron.fallback(['bandcamp_player'], function (elem) {
+            elem.style.width = elem.getAttribute('width');
+            elem.style.height = elem.getAttribute('height');
+            return tarteaucitron.engage('bandcamp');
+        });
+    }
+};