Amauri CHAMPEAUX 10 lat temu
rodzic
commit
23dc01d047

+ 38 - 0
README.md

@@ -1,2 +1,40 @@
 tarteaucitron.js
 ================
+Comply to the european cookie law is simple with the french *tarte au citron*.
+
+# What is this script?
+The european cookie law regulates the management of cookies and you should ask your visitors their consent before exposing them to third party services.
+
+Clearly this script will:
+- Disable all services by default,
+- Display a banner on the first page view and a small one on other pages,
+- Display a panel to allow or deny each services one by one,
+- Activate services on the second page view if not denied,
+- Store the consent in a cookie for 365 days.
+
+Bonus:
+- Load service when user click on Allow (without reload of the page),
+- Incorporate a fallback system (display a link instead of social button and a static banner instead of advertising).
+
+## Supported services
+- Facebook
+- FERank
+- Google Adsense
+- Google Analytics
+- Google+
+- Linkedin
+- Pinterest
+- Twitter
+
+## Visitors outside the EU
+In PHP for example, you can bypass all the script by setting this var `tarteaucitron.user.bypass = true;` if the visitor is not in the EU.
+
+## Tested on
+- IE 6+
+- FF 3+
+- Safari 4+
+- Chrome 14+
+- Opera 10+
+
+# Installation guide
+[Visit opt-out.ferank.eu](https://opt-out.ferank.eu/)

+ 284 - 0
css/tarteaucitron.css

@@ -0,0 +1,284 @@
+/***
+ * Responsive layout for the control panel
+ */
+@media screen and (max-width:650px) {
+    #tarteaucitron .tarteaucitronLine .tarteaucitronName {
+        width: 90% !important;
+    }
+    
+    #tarteaucitron .tarteaucitronLine .tarteaucitronAsk {
+        float: left !important;
+        margin: 10px 15px 5px;
+    }
+}
+
+@media screen and (max-width:1020px) {
+    #tarteaucitron {
+        top: 0;
+    }
+    
+    #tarteaucitron #tarteaucitronDisclaimer {
+        font-size: 14px;
+    }
+}
+
+/***
+ * Common value
+ */
+#tarteaucitron * {
+    zoom: 1;
+}
+
+#tarteaucitron .clear {
+    clear: both;
+}
+
+#tarteaucitron a {
+    color: #000;
+    text-decoration: underline;
+}
+
+#tarteaucitronAlertBig a, #tarteaucitronAlertSmall a {
+    color: #fff;
+}
+
+#tarteaucitron b {
+    font-size: 18px;
+    font-weight: 700;
+}
+
+#tarteaucitron em {
+    cursor: pointer;
+    text-decoration: underline;
+    font-size: 12px;
+    font-style: italic;
+}
+
+#tarteaucitron .tarteaucitronMore em {
+    cursor: text;
+    font-size: 14px;
+    text-decoration: none;
+}
+
+/***
+ * Root div added just before </body>
+ */
+#tarteaucitronRoot {
+    left: 0;
+    position: absolute;
+    right: 0;
+    top: 0;
+    width: 100%;
+}
+
+#tarteaucitronRoot * {
+    color: #333;
+    font-family: verdana;
+    font-size: 14px;
+}
+
+/***
+ * Control panel
+ */
+#tarteaucitronBack {
+    background: rgba(255, 255, 255, 0.7);
+    display: none;
+    height: 100%;
+    left: 0;
+    position: fixed;
+    top: 0;
+    width: 100%;
+    z-index: 2147483646;
+}
+
+#tarteaucitron {
+    background: #333;
+    border: 0;
+    border-bottom: 50px solid;
+    display: none;
+    left: 0;
+    margin: 0 auto;
+    max-width: 1020px;
+    position: relative;
+    right: 0;
+    top: 0;
+    z-index: 2147483647;
+}
+
+#tarteaucitron #tarteaucitronClosePanel {
+    color: #FFF;
+    cursor: pointer;
+    display: block;
+    text-decoration: underline;
+    font-family: verdana;
+    margin: 0px 15px 15px 0;
+    padding-top: 10px;
+    text-align: right;
+}
+
+#tarteaucitron #tarteaucitronDisclaimer {
+    color: #fff;
+    font-size: 16px;
+    margin: 0 auto 30px;
+    max-width: 800px;
+    padding: 0 15px;
+    text-align: center;
+}
+
+#tarteaucitron .tarteaucitronTitle {
+    background: rgb(81, 81, 81);
+    color: #FFF;
+    font-size: 16px;
+    padding: 5px 0px 5px 22px;
+    margin-top: 15px;
+}
+
+#tarteaucitron .tarteaucitronLine {
+    background: #f5f5f5;
+    border-bottom: 1px solid #fff;
+    border-top: 1px solid #fff;
+    height: auto;
+    min-height: 100%;
+    overflow: hidden;
+    padding: 5px;
+}
+
+#tarteaucitron .tarteaucitronLine .tarteaucitronName {
+    display: inline-block;
+    float: left;
+    margin-left: 15px;
+    width: 50%;
+}
+
+#tarteaucitron .tarteaucitronLine .tarteaucitronAsk {
+    display: inline-block;
+    float: right;
+    margin: 7px 15px 0;
+    text-align: right;
+}
+
+#tarteaucitron .tarteaucitronLine .tarteaucitronAsk .tarteaucitronAllow,
+#tarteaucitron .tarteaucitronLine .tarteaucitronAsk .tarteaucitronDeny {
+    background: gray;
+    color: #fff;
+    cursor: pointer;
+    display: inline-block;
+    padding: 5px 10px;
+    text-align: center;
+    text-decoration: none;
+    width: auto;
+}
+
+#tarteaucitron .tarteaucitronLine .tarteaucitronMore {
+    display: none;
+}
+
+
+/***
+ * Big alert
+ */
+#tarteaucitronAlertBig {
+    background: #333;
+    color: #fff !important;
+    display: none;
+    font-size: 15px !important;
+    left: 0;
+    padding: 5px 5%;
+    position: fixed;
+    text-align: center;
+    top: 0;
+    width: 90%;
+    box-sizing: content-box;
+    z-index: 2147483645;
+}
+
+#tarteaucitronAlertBig #tarteaucitronDisclaimerAlert {
+    font: 15px verdana;
+    color: #fff;
+}
+
+#tarteaucitronAlertBig #tarteaucitronPersonalize {
+    background: #008300;
+    color: #fff;
+    cursor: pointer;
+    display: inline-block;
+    font-size: 16px;
+    padding: 5px 10px;
+    text-decoration: none;
+    margin-left: 7px;
+}
+
+#tarteaucitronAlertBig #tarteaucitronCloseAlert {
+    font-size: 11px;
+    margin-left: 7px;
+    cursor: pointer;
+    color: #fff;
+}
+
+/***
+ * Small alert
+ */
+#tarteaucitronAlertSmall {
+    background: #333;
+    bottom: 0;
+    color: #fff !important;
+    cursor: pointer;
+    display: none;
+    font-size: 11px !important;
+    padding: 3px;
+    padding-right: 5px;
+    position: fixed;
+    right: 0;
+    z-index: 2147483645;
+}
+
+#tarteaucitronAlertSmall #tarteaucitronDot {
+    background-color: #E63737;
+    border-radius: 10px;
+    display: inline-block;
+    height: 10px;
+    margin: 0px 5px 2px 5px;
+    vertical-align: middle;
+    width: 10px;
+}
+
+/***
+ * Fallback links for social networks
+ */
+.tac_share {
+    display: inline-block;
+    margin: 0;
+    padding: 3px 10px;
+    text-decoration: none;
+    font-size: 13px;
+    color: #fff !important;
+    text-align: center;
+}
+
+.tac_share_twitter {
+    background-color: #4099ff;
+}
+
+.tac_share_facebook {
+    background-color: #3b5998;
+}
+
+.tac_share_googlep {
+    background-color: #D34836;
+}
+
+.tac_share_linkedin {
+    background-color: #3399cc;
+}
+
+.tac_share_pinterest {
+    background-color: #cb2027;
+}
+
+.tac_share_digg {
+    background-color: #0093CC;
+}
+
+.tac_share_reddit {
+    background-color: #2E81D5;
+}

+ 17 - 0
lang/tarteaucitron.de.js

@@ -0,0 +1,17 @@
+/*global tarteaucitron */
+tarteaucitron.lang = {
+    "alertBig": "",
+    "alertSmall": "",
+    "personalize": "",
+    "close": "",
+
+    "disclaimer": "",
+    "allow": "",
+    "deny": "",
+    "more": "",
+    "source": "",
+
+    "ads": "",
+    "analytics": "",
+    "social": ""
+};

+ 17 - 0
lang/tarteaucitron.en.js

@@ -0,0 +1,17 @@
+/*global tarteaucitron */
+tarteaucitron.lang = {
+    "alertBig": "If you continue to browse this website, you are allowing all third-party services",
+    "alertSmall": "Manage Cookies",
+    "personalize": "Personalize",
+    "close": "Close",
+
+    "disclaimer": "By allowing these third party services, you accept theirs cookies and the use of tracking technologies necessary for their proper functioning.",
+    "allow": "Allow",
+    "deny": "Deny",
+    "more": "Read more",
+    "source": "View the official website",
+
+    "ads": "Advertising network",
+    "analytics": "Audience measurement",
+    "social": "Social networks"
+};

+ 17 - 0
lang/tarteaucitron.es.js

@@ -0,0 +1,17 @@
+/*global tarteaucitron */
+tarteaucitron.lang = {
+    "alertBig": "",
+    "alertSmall": "",
+    "personalize": "",
+    "close": "",
+
+    "disclaimer": "",
+    "allow": "",
+    "deny": "",
+    "more": "",
+    "source": "",
+
+    "ads": "",
+    "analytics": "",
+    "social": ""
+};

+ 17 - 0
lang/tarteaucitron.fr.js

@@ -0,0 +1,17 @@
+/*global tarteaucitron */
+tarteaucitron.lang = {
+    "alertBig": "En poursuivant votre navigation, vous acceptez l'utilisation de services tiers pouvant installer des cookies",
+    "alertSmall": "Gestion des cookies",
+    "personalize": "Personnaliser",
+    "close": "Fermer",
+
+    "disclaimer": "En autorisant ces services tiers, vous acceptez le d&eacute;p&ocirc;t et la lecture de cookies et l'utilisation de technologies de suivi n&eacute;cessaires &agrave; leur bon fonctionnement.",
+    "allow": "Autoriser",
+    "deny": "Interdire",
+    "more": "En savoir plus",
+    "source": "Voir le site officiel",
+
+    "ads": "R&eacute;gies publicitaires",
+    "analytics": "Mesure d'audience",
+    "social": "R&eacute;seaux sociaux"
+};

+ 17 - 0
lang/tarteaucitron.it.js

@@ -0,0 +1,17 @@
+/*global tarteaucitron */
+tarteaucitron.lang = {
+    "alertBig": "",
+    "alertSmall": "",
+    "personalize": "",
+    "close": "",
+
+    "disclaimer": "",
+    "allow": "",
+    "deny": "",
+    "more": "",
+    "source": "",
+
+    "ads": "",
+    "analytics": "",
+    "social": ""
+};

+ 445 - 0
tarteaucitron.js

@@ -0,0 +1,445 @@
+/*jslint browser: true */
+var tarteaucitron = {
+    "cdn": "",
+    "user": {},
+    "lang": {},
+    "services": {},
+    "state": [],
+    "launch": [],
+    "init": function () {
+        "use strict";
+        var cdn = tarteaucitron.cdn,
+            language = tarteaucitron.getLanguage(),
+            pathToLang = cdn + 'lang/tarteaucitron.' + language + '.js',
+            pathToServices = cdn + 'tarteaucitron.services.js',
+            linkElement = document.createElement('link');
+        
+        // Step 1: load css
+        linkElement.rel = 'stylesheet';
+        linkElement.type = 'text/css';
+        linkElement.href = cdn + 'css/tarteaucitron.css';
+        document.getElementsByTagName('head')[0].appendChild(linkElement);
+
+        // Step 2: load language and services
+        tarteaucitron.addScript(pathToLang, '', function () {
+            tarteaucitron.addScript(pathToServices, '', function () {
+
+                var body = document.body,
+                    div = document.createElement('div'),
+                    hostname = document.location.hostname,
+                    hostRef = document.referrer.split('/')[2],
+                    isNavigating = (hostRef === hostname) ? true : false,
+                    isAutostart,
+                    isDenied,
+                    isAllowed,
+                    isResponded,
+                    cookie = tarteaucitron.cookie.read(),
+                    s = tarteaucitron.services,
+                    service,
+                    html = '',
+                    lastTitle,
+                    phrases,
+                    textIntro,
+                    textMore,
+                    alert = false,
+                    index;
+
+                // dedup, clean and sort job[]
+                function cleanArray(arr) {
+                    var i,
+                        len = arr.length,
+                        out = [],
+                        obj = {};
+ 
+                    for (i = 0; i < len; i += 1) {
+                        if (!obj[arr[i]]) {
+                            obj[arr[i]] = {};
+                            if (tarteaucitron.services[arr[i]] !== undefined) {
+                                out.push(arr[i]);
+                            }
+                        }
+                    }
+                    return out;
+                }
+                tarteaucitron.job = cleanArray(tarteaucitron.job);
+                tarteaucitron.job = tarteaucitron.job.sort(function (a, b) {
+                    if (s[a].type + s[a].key > s[b].type + s[b].key) { return 1; }
+                    if (s[a].type + s[a].key < s[b].type + s[b].key) { return -1; }
+                    return 0;
+                });
+
+                // if bypass: load all services and exit
+                // for example, set tarteaucitron.user.bypass = true;
+                // if the user is not in europa
+                if (tarteaucitron.user.bypass === true) {
+                    for (index = 0; index < tarteaucitron.job.length; index += 1) {
+                        service = s[tarteaucitron.job[index]];
+                        service.js();
+                    }
+                    return;
+                }
+
+                // Step 3: prepare the html
+                html += '<div id="tarteaucitronBack"></div>';
+                html += '<div id="tarteaucitron">';
+                html += '   <div id="tarteaucitronClosePanel" onclick="tarteaucitron.userInterface.closePanel();">';
+                html += '       ' + tarteaucitron.lang.close;
+                html += '   </div>';
+                html += '   <div id="tarteaucitronDisclaimer">';
+                html += '       ' + tarteaucitron.lang.disclaimer;
+                html += '   </div>';
+                html += '   <div id="tarteaucitronServices">';
+
+                for (index = 0; index < tarteaucitron.job.length; index += 1) {
+                    service = s[tarteaucitron.job[index]];
+                    textIntro = service.lang[language].split(".").splice(0, 1).join(".");
+                    phrases = service.lang[language].split(".");
+                    phrases.splice(0, 1);
+                    textMore = phrases.join(".");
+
+                    if (lastTitle !== service.type) {
+                        html += '<div class="tarteaucitronTitle">';
+                        html += '   ' + tarteaucitron.lang[service.type];
+                        html += '</div>';
+
+                        lastTitle = service.type;
+                    }
+
+                    html += '<div id="' + service.key + 'Line" class="tarteaucitronLine">';
+                    html += '   <div class="tarteaucitronName">';
+                    html += '       <b>' + service.name + '</b><br/>';
+                    html += '       ' + textIntro + '. ';
+                    html += '       <em id="' + service.key + 'More" onclick="tarteaucitron.userInterface.showMore(this);">';
+                    html += '           ' + tarteaucitron.lang.more;
+                    html += '       </em>';
+                    html += '       <div id="' + service.key + 'MoreText" class="tarteaucitronMore">';
+                    html += '           ' +  textMore;
+                    html += '           <a href="' + service.uri + '" target="_blank">';
+                    html += '               ' + tarteaucitron.lang.source;
+                    html += '           </a>';
+                    html += '       </div>';
+                    html += '   </div>';
+                    html += '   <div class="tarteaucitronAsk">';
+                    html += '       <div id="' + service.key + 'Allowed" class="tarteaucitronAllow" onclick="tarteaucitron.userInterface.respond(this, true);">';
+                    html += '           ' + tarteaucitron.lang.allow;
+                    html += '       </div> ';
+                    html += '       <div id="' + service.key + 'Denied" class="tarteaucitronDeny" onclick="tarteaucitron.userInterface.respond(this, false);">';
+                    html += '           ' + tarteaucitron.lang.deny;
+                    html += '       </div>';
+                    html += '   </div>';
+                    html += '</div>';
+                    html += '<div class="clear"></div>';
+                }
+
+                html += '   </div>';
+                html += '</div>';
+                html += '<div id="tarteaucitronAlertBig">';
+                html += '   <span id="tarteaucitronDisclaimerAlert">';
+                html += '       ' + tarteaucitron.lang.alertBig;
+                html += '   </span>';
+                html += '   <span id="tarteaucitronPersonalize" onclick="tarteaucitron.userInterface.openPanel();">';
+                html += '       ' + tarteaucitron.lang.personalize;
+                html += '   </span>';
+                html += '   <span id="tarteaucitronCloseAlert" onclick="tarteaucitron.userInterface.closeAlert();">';
+                html += '       ' + tarteaucitron.lang.close;
+                html += '   </span>';
+                html += '</div>';
+                html += '<div id="tarteaucitronAlertSmall" onclick="tarteaucitron.userInterface.openPanel();">';
+                html += '   <span id="tarteaucitronDot"></span>';
+                html += '   ' + tarteaucitron.lang.alertSmall;
+                html += '</div>';
+
+                div.id = 'tarteaucitronRoot';
+                body.appendChild(div, body);
+                div.innerHTML = html;
+
+                // Step 4: load services
+                for (index = 0; index < tarteaucitron.job.length; index += 1) {
+                    service = s[tarteaucitron.job[index]];
+                    isAutostart = (!service.needConsent) ? true : false;
+                    isDenied = (cookie.indexOf(service.key + '=false') >= 0) ? true : false;
+                    isAllowed = (cookie.indexOf(service.key + '=true') >= 0) ? true : false;
+                    isResponded = (cookie.indexOf(service.key) >= 0) ? true : false;
+
+                    if ((!isResponded && (isAutostart || isNavigating)) || isAllowed) {
+                        if (!isAllowed) {
+                            tarteaucitron.cookie.create(service.key, true);
+                        }
+                        if (tarteaucitron.launch[service.key] !== true) {
+                            tarteaucitron.launch[service.key] = true;
+                            service.js();
+                        }
+                        tarteaucitron.state[service.key] = true;
+                        tarteaucitron.userInterface.color(service.key, true);
+                    } else if (isDenied) {
+                        if (typeof service.fallback === 'function') {
+                            service.fallback();
+                        }
+                        tarteaucitron.state[service.key] = false;
+                        tarteaucitron.userInterface.color(service.key, false);
+                    } else if (!isResponded) {
+                        if (typeof service.fallback === 'function') {
+                            service.fallback();
+                        }
+                    }
+
+                    if (tarteaucitron.state[service.key] === undefined && !alert) {
+                        alert = true;
+                    }
+                }
+
+                // Step 5: display the alert
+                if (alert) {
+                    tarteaucitron.userInterface.openAlert();
+                } else {
+                    tarteaucitron.userInterface.closeAlert();
+                }
+                if (document.location.hash === '#tarteaucitron') {
+                    tarteaucitron.userInterface.openPanel();
+                }
+            });
+        });
+    },
+    "userInterface": {
+        "css": function (id, property, value) {
+            "use strict";
+            document.getElementById(id).style[property] = value;
+        },
+        "showMore": function (el) {
+            "use strict";
+            var key = el.id.replace(/More/, '');
+            tarteaucitron.userInterface.css(key + 'MoreText', 'display', 'inline');
+            el.style.display = 'none';
+        },
+        "respond": function (el, status) {
+            "use strict";
+            var key = el.id.replace(new RegExp("(Allow|Deni)ed", "g"), '');
+        
+            // return if same state
+            if (tarteaucitron.state[key] === status) {
+                return;
+            }
+        
+            // if not already launched... launch the service
+            if (status === true) {
+                if (tarteaucitron.launch[key] !== true) {
+                    tarteaucitron.launch[key] = true;
+                    tarteaucitron.services[key].js();
+                }
+            }
+            tarteaucitron.state[key] = status;
+            tarteaucitron.cookie.create(key, status);
+            tarteaucitron.userInterface.color(key, status);
+        },
+        "color": function (key, status) {
+            "use strict";
+            var gray = '#808080',
+                greenDark = '#1B870B',
+                greenLight = '#E6FFE2',
+                redDark = '#9C1A1A',
+                redLight = '#FFE2E2',
+                c = 'tarteaucitron',
+                allAllowed = true,
+                index;
+
+            if (status === true) {
+                tarteaucitron.userInterface.css(key + 'Line', 'backgroundColor', greenLight);
+                tarteaucitron.userInterface.css(key + 'Allowed', 'backgroundColor', greenDark);
+                tarteaucitron.userInterface.css(key + 'Denied', 'backgroundColor', gray);
+            } else if (status === false) {
+                tarteaucitron.userInterface.css(key + 'Line', 'backgroundColor', redLight);
+                tarteaucitron.userInterface.css(key + 'Allowed', 'backgroundColor', gray);
+                tarteaucitron.userInterface.css(key + 'Denied', 'backgroundColor', redDark);
+            }
+        
+            // check if all services are allowed
+            for (index = 0; index < tarteaucitron.job.length; index += 1) {
+                if (tarteaucitron.state[tarteaucitron.job[index]] === false) {
+                    allAllowed = false;
+                    break;
+                }
+            }
+        
+            if (allAllowed) {
+                tarteaucitron.userInterface.css(c + 'Dot', 'backgroundColor', greenDark);
+            } else {
+                tarteaucitron.userInterface.css(c + 'Dot', 'backgroundColor', redDark);
+            }
+        },
+        "openPanel": function () {
+            "use strict";
+            tarteaucitron.userInterface.css('tarteaucitron', 'display', 'block');
+            tarteaucitron.userInterface.css('tarteaucitronBack', 'display', 'block');
+            tarteaucitron.userInterface.closeAlert();
+
+            // setting hash tag
+            document.location.hash = 'tarteaucitron';
+        },
+        "closePanel": function () {
+            "use strict";
+            tarteaucitron.userInterface.css('tarteaucitron', 'display', 'none');
+            tarteaucitron.userInterface.css('tarteaucitronBack', 'display', 'none');
+        },
+        "openAlert": function () {
+            "use strict";
+            var c = 'tarteaucitron';
+            tarteaucitron.userInterface.css(c + 'AlertSmall', 'display', 'none');
+            tarteaucitron.userInterface.css(c + 'AlertBig',   'display', 'block');
+        },
+        "closeAlert": function () {
+            "use strict";
+            var c = 'tarteaucitron';
+            tarteaucitron.userInterface.css(c + 'AlertSmall', 'display', 'block');
+            tarteaucitron.userInterface.css(c + 'AlertBig',   'display', 'none');
+        }
+    },
+    "cookie": {
+        "create": function (key, status) {
+            "use strict";
+            var d = new Date(),
+                time = d.getTime(),
+                expireTime = time + 31536000000, // 365 days
+                regex = new RegExp("!" + key + "=(true|false)", "g"),
+                cookie = tarteaucitron.cookie.read().replace(regex, ""),
+                value = 'tarteaucitron=' + cookie + '!' + key + '=' + status;
+
+            d.setTime(expireTime);
+            document.cookie = value + '; expires=' + d.toGMTString() + '; path=/;';
+        },
+        "read": function () {
+            "use strict";
+            var nameEQ = "tarteaucitron=",
+                ca = document.cookie.split(';'),
+                i,
+                c;
+
+            for (i = 0; i < ca.length; i += 1) {
+                c = ca[i];
+                while (c.charAt(0) === ' ') {
+                    c = c.substring(1, c.length);
+                }
+                if (c.indexOf(nameEQ) === 0) {
+                    return c.substring(nameEQ.length, c.length);
+                }
+            }
+            return '';
+        }
+    },
+    "getLanguage": function () {
+        "use strict";
+        if (!navigator) { return 'en'; }
+        
+        var availableLanguages = 'en,fr',
+            defaultLanguage = 'en',
+            lang = navigator.language || navigator.browserLanguage ||
+                navigator.systemLanguage || navigator.userLang || null,
+            userLanguage = lang.substr(0, 2);
+        
+        if (availableLanguages.indexOf(userLanguage) === -1) {
+            return defaultLanguage;
+        }
+        return userLanguage;
+    },
+    "addScript": function (url, id, callback) {
+        "use strict";
+        var script = document.createElement('script'),
+            done = false;
+        
+        script.type = 'text/javascript';
+        script.id = (id !== undefined) ? id : '';
+        script.async = true;
+        script.src = url;
+
+        if (typeof callback === 'function') {
+            script.onreadystatechange = script.onload = function () {
+                var state = script.readyState;
+                if (!done && (!state || /loaded|complete/.test(state))) {
+                    done = true;
+                    callback();
+                }
+            };
+        }
+        document.getElementsByTagName('head')[0].appendChild(script);
+    },
+    "fallback": function (matchClass, content) {
+        "use strict";
+        var elems = document.getElementsByTagName('*'),
+            i,
+            index = 0;
+
+        for (i in elems) {
+            if (elems[i] !== undefined) {
+                for (index = 0; index < matchClass.length; index += 1) {
+                    if ((' ' + elems[i].className + ' ')
+                            .indexOf(' ' + matchClass[index] + ' ') > -1) {
+                        if (typeof content === 'function') {
+                            elems[i].innerHTML = content(elems[i]);
+                        } else {
+                            elems[i].innerHTML = content;
+                        }
+                    }
+                }
+            }
+        }
+    },
+    
+    /***
+     * Fallback function for advertising services
+     * 
+     * Currently, a banner to promote tarteaucitron.js is displayed,
+     * fell free to change this by your own ads.
+     *
+     * Because eval() id devil, you can't pass <script>,
+     * only html like <a><img /></a>
+     */
+    "promoteMe": function (el) {
+        "use strict";
+        var l = tarteaucitron.getLanguage(),
+            w = el.offsetWidth,
+            h = el.offsetHeight,
+            s = '',
+            r = '';
+
+        if (w > 0 && h === 0) {
+            h = 60;
+        }
+        if (w >= 728 && h <= 60) {
+            h = 90;
+        }
+        if (w >= 970 && h >= 250) {
+            s = '970250';
+        } else if (w >= 970 && h >= 90) {
+            s = '97090';
+        } else if (w >= 728 && h >= 90) {
+            s = '72890';
+        } else if (w >= 468 && h >= 60) {
+            s = '46860';
+        } else if (w >= 336 && h >= 280) {
+            s = '336280';
+        } else if (w >= 300 && h >= 600) {
+            s = '300600';
+        } else if (w >= 300 && h >= 250) {
+            s = '300250';
+        } else if (w >= 250 && h >= 250) {
+            s = '250250';
+        } else if (w >= 200 && h >= 200) {
+            s = '200200';
+        } else if (w >= 160 && h >= 600) {
+            s = '160600';
+        } else if (w >= 120 && h >= 600) {
+            s = '120600';
+        } else if (w >= 120 && h >= 300) {
+            s = '120300';
+        } else if (w >= 120 && h >= 240) {
+            s = '120240';
+        } else {
+            s = '8080';
+        }
+
+        r += '<a href="//opt-out.ferank.eu/" target="_blank" rel="nofollow">';
+        r += '  <img src="//opt-out.ferank.eu/b/' + l + '/' + s + '.gif" border="0" />';
+        r += '</a>';
+
+        return r;
+    }
+};

+ 201 - 0
tarteaucitron.services.js

@@ -0,0 +1,201 @@
+/*global tarteaucitron, ga*/
+
+// ferank
+tarteaucitron.services.ferank = {
+    "key": "ferank",
+    "type": "analytics",
+    "name": "FERank",
+    "uri": "https://www.ferank.fr/respect-vie-privee/#mesureaudience",
+    "needConsent": false,
+    "js": function () {
+        "use strict";
+        tarteaucitron.addScript('//static.ferank.fr/pixel.js', '', function () {
+            if (typeof tarteaucitron.user.ferankMore === 'function') {
+                tarteaucitron.user.ferankMore();
+            }
+        });
+    },
+    "lang": {
+        "en": "FERank uses a beacon to generate traffic statistics. During your visits, information about your browsing and your equipment are transmitted to FERank. The collected data is immediately anonymized, personal information that identifies you is never stored, not even your IP address, and the statistics are not cross-checked with other sites or files.<br/><br/><em>FERank meets the criteria to be exempted from prior consent.</em>",
+        "fr": "FERank utilise un pixel invisible pour g&eacute;n&eacute;rer des statistiques de fr&eacute;quentation. Lors de vos visites, des informations sur votre navigation et votre mat&eacute;riel sont transmises &agrave; FERank.<br/><br/>Les donn&eacute;es collect&eacute;es sont imm&eacute;diatement anonymis&eacute;es, aucune information personnelle ou permettant de vous identifier n'est stock&eacute;e, pas m&ecirc;me votre adresse IP, et les statistiques ne sont pas recoup&eacute;es avec d'autres sites ou fichiers.<br/><br/><em>FERank r&eacute;pond aux crit&egrave;res pour &ecirc;tre dispens&eacute; de consentement pr&eacute;alable.</em>",
+        "de": "",
+        "es": "",
+        "it": ""
+    }
+};
+
+// facebook
+tarteaucitron.services.facebook = {
+    "key": "facebook",
+    "type": "social",
+    "name": "Facebook",
+    "uri": "https://www.facebook.com/help/cookies/",
+    "needConsent": true,
+    "js": function () {
+        "use strict";
+        tarteaucitron.fallback(['fb-like'], '');
+        tarteaucitron.addScript('//connect.facebook.net/fr_FR/sdk.js#xfbml=1&version=v2.0', 'facebook-jssdk');
+    },
+    "fallback": function () {
+        "use strict";
+        tarteaucitron.fallback(['fb-post', 'fb-follow', 'fb-comments', 'fb-activity', 'fb-like-box', 'fb-send', 'fb-share-button', 'fb-like'], '<a href="https://www.facebook.com/sharer/sharer.php?u=' + encodeURIComponent(document.location) + '" target="_blank" class="tac_share tac_share_facebook">Facebook</a>');
+    },
+    "lang": {
+        "en": "Facebook, its subsidiaries and partners uses technology such as cookies, tracking pixels and local storage. These technologies are used for security purposes and to provide products, services and advertisements.<br/><br/><em> Facebook provide a policy about the use of tracking technologies and cookies.</em>",
+        "fr": "Facebook, ses filiales et autres partenaires utilisent des technologies telles que les cookies, les pixels de suivi et le stockage local. Ces technologies sont utilis&eacute;es &agrave; des fins de s&eacute;curit&eacute; et pour fournir des produits, des services et des publicit&eacute;s.<br/><br/><em>Facebook met &agrave; disposition une politique sur l'utilisation de ses syst&egrave;mes de suivi et l'utilisation des cookies.</em>",
+        "de": "",
+        "es": "",
+        "it": ""
+    }
+};
+
+// google adsense
+tarteaucitron.services.adsense = {
+    "key": "adsense",
+    "type": "ads",
+    "name": "Adsense (Google)",
+    "uri": "http://www.google.com/ads/preferences/",
+    "needConsent": true,
+    "js": function () {
+        "use strict";
+        tarteaucitron.addScript('//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js');
+    },
+    "fallback": function () {
+        "use strict";
+        tarteaucitron.fallback(['adsbygoogle'], tarteaucitron.promoteMe);
+    },
+    "lang": {
+        "en": "Google uses cookies to serve ads based on your previous visits. Google and its partners adjust ads based on your visit to this site and / or other web sites using the DoubleClick cookie.<br/><br/><em>You can disable the DoubleClick cookie used for ad serving via Google Advertising Solutions settings.</em>",
+        "fr": "Google utilise des cookies pour diffuser des annonces en fonction de vos visites ant&eacute;rieures. Google et ses partenaires adaptent les annonces diffus&eacute;es en fonction de votre navigation sur ce site et/ou d'autres sites web en utilisant le cookie DoubleClick.<br/><br/><em>Vous pouvez d&eacute;sactiver le cookie DoubleClick utilis&eacute; pour la diffusion d'annonces par centres d'int&eacute;r&ecirc;t via les param&egrave;tres Google Solutions publicitaires.</em>",
+        "de": "",
+        "es": "",
+        "it": ""
+    }
+};
+
+// google analytics
+tarteaucitron.services.analytics = {
+    "key": "analytics",
+    "type": "analytics",
+    "name": "Analytics (Google)",
+    "uri": "https://support.google.com/analytics/answer/6004245",
+    "needConsent": true,
+    "js": function () {
+        "use strict";
+        window.GoogleAnalyticsObject = 'ga';
+        window.ga = window.ga || function () {
+            window.ga.q = window.ga.q || [];
+            window.ga.q.push(arguments);
+        };
+        window.ga.l = new Date();
+        
+        tarteaucitron.addScript('//www.google-analytics.com/analytics.js', '', function () {
+            ga('create', tarteaucitron.user.analyticsUA, 'auto');
+            ga('send', 'pageview');
+            if (typeof tarteaucitron.user.analyticsMore === 'function') {
+                tarteaucitron.user.analyticsMore();
+            }
+        });
+    },
+    "lang": {
+        "en": "Google Analytics uses cookies to generate internal reports about your interactions on this website. These cookies are used to store information that does not identify you personally. First-party cookies are stored on your browser and are not valid from one domain to another.<br/><br/><em> Google provide a policy about the use of tracking technologies and cookies.</em>",
+        "fr": "Google Analytics utilise des cookies internes permettant de g&eacute;n&eacute;rer des rapports sur vos interactions sur ce site web. Ces cookies sont utilis&eacute;s pour stocker des informations ne permettant pas de vous identifier personnellement. Les cookies internes stock&eacute;s sur votre navigateur ne sont pas valables d'un domaine &agrave; l'autre.<br/><br/><em>Google met &agrave; disposition une politique sur l'utilisation de ses syst&egrave;mes de suivi et l'utilisation des cookies.</em>",
+        "de": "",
+        "es": "",
+        "it": ""
+    }
+};
+
+// google+
+tarteaucitron.services.gplus = {
+    "key": "gplus",
+    "type": "social",
+    "name": "Google+",
+    "uri": "http://www.google.fr/intl/policies/privacy/",
+    "needConsent": true,
+    "js": function () {
+        "use strict";
+        tarteaucitron.addScript('https://apis.google.com/js/platform.js');
+    },
+    "fallback": function () {
+        "use strict";
+        tarteaucitron.fallback(['g-page', 'g-plus', 'g-plusone'], '<a href="https://plus.google.com/share?url=' + encodeURIComponent(document.location) + '" target="_blank" class="tac_share tac_share_googlep">Google+</a>');
+    },
+    "lang": {
+        "en": "Google collects information used to improve services to the public. It may be basic information, such as the language you use, or more complex, such as ads that you find most useful or the people who interest you most on the web.<br/><br/><em> Google provide a policy about the use of tracking technologies and cookies.</em>",
+        "fr": "Google collecte des informations servent &agrave; am&eacute;liorer ses services accessibles au public. Il peut s'agir d'informations de base, telles que la langue que vous utilisez, ou plus complexes, par exemple les annonces que vous trouvez les plus utiles ou les personnes qui vous int&eacute;ressent le plus sur le web.<br/><br/><em>Google met &agrave; disposition une politique sur l'utilisation de ses syst&egrave;mes de suivi et l'utilisation des cookies.</em>",
+        "de": "",
+        "es": "",
+        "it": ""
+    }
+};
+
+// linkedin
+tarteaucitron.services.linkedin = {
+    "key": "linkedin",
+    "type": "social",
+    "name": "Linkedin",
+    "uri": "https://www.linkedin.com/legal/cookie_policy",
+    "needConsent": true,
+    "js": function () {
+        "use strict";
+        tarteaucitron.fallback(['tacLinkedin'], '');
+        tarteaucitron.addScript('//platform.linkedin.com/in.js');
+    },
+    "fallback": function () {
+        "use strict";
+        tarteaucitron.fallback(['tacLinkedin'], '<a href="http://www.linkedin.com/shareArticle?mini=true&url=' + encodeURIComponent(document.location) + '" target="_blank" class="tac_share tac_share_linkedin">Linkedin</a>');
+    },
+    "lang": {
+        "en": "Linkedin and its partners may set cookies to improve and secure their services, offer you relevant ads or customize your user experience.<br/><br/><em>Linkedin provided a policy about the use of tracking technologies and cookies.</em>",
+        "fr": "Linkedin et ses partenaires peuvent installer des cookies afin d'am&eacute;liorer et s&eacute;curiser leurs services, vous proposer des publicit&eacute;s pertinentes ou encore personnaliser votre exp&eacute;rience utilisateur.<br/><br/><em>Linkedin met &grave; disposition une politique sur l'utilisation de ses syst&egrave;mes de suivi et l'utilisation des cookies.</em>",
+        "de": "",
+        "es": "",
+        "it": ""
+    }
+};
+
+// pinterest
+tarteaucitron.services.pinterest = {
+    "key": "pinterest",
+    "type": "social",
+    "name": "Pinterest",
+    "uri": "https://about.pinterest.com/privacy-policy",
+    "needConsent": true,
+    "js": function () {
+        "use strict";
+        tarteaucitron.addScript('//assets.pinterest.com/js/pinit.js');
+    },
+    "lang": {
+        "en": "Pinterest collect technical information and the type of equipment you use through his widget on this site. These informations can be stored in log files or cookies, and are used to improve Pinterest services and develop new ones.<br/><br/><em> Pinterest provide a policy about the use of tracking technologies and cookies.</em>",
+        "fr": "Pinterest collecte des informations techniques et le type de mat&eacute;riel que vous utilisez via le widget pr&eacute;sent sur ce site. Ces informations peuvent &ecirc;tre stock&eacute;es dans des fichiers logs ou des cookies et sont utilis&eacute;es pour am&eacute;liorer les services de Pinterest et en d&eacute;velopper de nouveaux.<br/><br/><em>Pinterest met &agrave; disposition une politique sur l'utilisation de ses syst&egrave;mes de suivi et l'utilisation des cookies.</em>",
+        "de": "",
+        "es": "",
+        "it": ""
+    }
+};
+
+// twitter
+tarteaucitron.services.twitter = {
+    "key": "twitter",
+    "type": "social",
+    "name": "Twitter",
+    "uri": "https://support.twitter.com/articles/20170514",
+    "needConsent": true,
+    "js": function () {
+        "use strict";
+        tarteaucitron.fallback(['tacTwitter'], '');
+        tarteaucitron.addScript('//platform.twitter.com/widgets.js', 'twitter-wjs');
+    },
+    "fallback": function () {
+        "use strict";
+        tarteaucitron.fallback(['tacTwitter'], '<a href="https://twitter.com/intent/tweet?text=' + encodeURIComponent(document.title) + '%20' + encodeURIComponent(document.location) + '" target="_blank" class="tac_share tac_share_twitter">Twitter</a>');
+    },
+    "lang": {
+        "en": "Twitter collects and uses information to deliver services and to measure and improve service over time. Twitter can tailor content for you based on your visits to other websites via cookies.<br/><br/><em>Twitter provide a policy about the use of tracking technologies and cookies.</em>",
+        "fr": "Twitter collecte et utilise des informations pour fournir ses services, ainsi que pour mesurer et am&eacute;liorer ses services au fil du temps. Twitter peux adapter le contenu qui vous est destin&eacute; en fonction de vos visites sur des sites tiers via des cookies.<br/><br/><em>Twitter met &agrave; disposition une politique sur l'utilisation de ses syst&egrave;mes de suivi et l'utilisation des cookies.</em>",
+        "de": "",
+        "es": "",
+        "it": ""
+    }
+};