-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathcookie-consent.html
347 lines (331 loc) · 11.7 KB
/
cookie-consent.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../iron-ajax/iron-ajax.html">
<link rel="import" href="../paper-toast/paper-toast.html">
<link rel="import" href="../paper-button/paper-button.html">
<link rel="import" href="../iron-flex-layout/iron-flex-layout-classes.html">
<!--
`cookie-consent`
A great, simple and fully customizable material design cookie consent that automatically
shows up only to the users subject to the cookie law (EU users).
_[Take a look at the component overview for more info](https://www.webcomponents.org/element/Dabolus/cookie-consent)_
@demo demo/index.html
-->
<dom-module id="cookie-consent">
<template>
<style>
:host {
@apply(--cookie-consent);
}
#consentToast {
@apply(--cookie-consent-toast);
--paper-toast-color: var(--cookie-consent-text-color, #f1f1f1);
--paper-toast-background-color: var(--cookie-consent-background-color, #323232);
}
#consentToast .text {
@apply(--cookie-consent-text);
color: var(--cookie-consent-text-color, #f1f1f1);
}
.policy-link {
@apply(--cookie-consent-policy-link);
color: var(--cookie-consent-policy-link-color, var(--light-accent-color));
text-decoration: none;
}
.policy-link:hover {
text-decoration: underline;
}
paper-button {
@apply(--cookie-consent-buttons);
margin: 0;
padding: 3px 0;
text-align: center;
}
paper-button.keyboard-focus {
font-weight: normal !important;
}
.horizontal {
@apply(--layout-horizontal);
padding-top: 10px;
}
.flex {
@apply(--layout-flex);
}
#rejectButton {
@apply(--cookie-consent-reject-button);
color: var(--cookie-consent-reject-text-color, var(--disabled-text-color));
background: var(--cookie-consent-reject-background, transparent);
--paper-button-ink-color: var(--cookie-consent-reject-ink-color, var(--disabled-text-color));
}
#acceptButton {
@apply(--cookie-consent-accept-button);
color: var(--cookie-consent-accept-text-color, var(--accent-color));
background: var(--cookie-consent-accept-background, transparent);
--paper-button-ink-color: var(--cookie-consent-accept-ink-color, var(--accent-color));
}
</style>
<iron-ajax id="checkCountry"
url="[[geoIpUrl]]"
handle-as="json"
on-response="_checkCountryCode"></iron-ajax>
<paper-toast id="consentToast" class="fit-bottom" duration="0">
<div class="horizontal">
<div>
<span class="text">[[text]]</span>
<template is="dom-if" if="[[policyLink]]">
<a href$="[[policyLink]]" target$="[[policyTarget]]" class="policy-link">[[policyText]]</a>
</template>
<content select="span.text"></content>
<content select="a.policy-link"></content>
</div>
<div class="flex"></div>
<div>
<template is="dom-if" if="[[rejectable]]">
<paper-button id="rejectButton" on-tap="_respond" data-response="reject">[[rejectText]]</paper-button>
</template>
<paper-button id="acceptButton" on-tap="_respond" data-response="accept">[[acceptText]]</paper-button>
</div>
</div>
</paper-toast>
</template>
<script>
Polymer({
is: 'cookie-consent',
properties: {
/**
* The url of the API to use to retrieve the user location information.
*
* You can change it if for some reason the 15,000 queries per hour offered
* by [freegeoip.net](https://freegeoip.net/) are not enough for you, or
* if you prefer to use your own private api.
*
* You can also pass an empty string if you want to show the cookie consent
* to any visitor, regardless of their location.
*/
geoIpUrl: {
type: String,
value: 'https://freegeoip.net/json/',
},
/**
* The param that contains the country code of the user
* in the result returned from the API.
*/
geoIpParam: {
type: String,
value: 'country_code',
},
/**
* The current status of the consent.
* It can be:
* - `pending`: if the user hasn't given the consent yet
* - `accepted`: if the user has accepted the consent
* - `rejected`: if the user has rejected the consent
*/
cookiesStatus: {
type: String,
value: 'pending',
readOnly: true,
notify: true,
reflectToAttribute: true,
},
/**
* Use the local storage instead of saving user cookie consent to a cookie.
*/
useLocalStorage: Boolean,
/**
* Use the session storage instead of saving user cookie consent to a cookie.
*
* This can be useful to test out the cookie consent toast, as the user choice
* will be deleted when he closes the browser tab.
*/
useSessionStorage: Boolean,
/**
* The text displayed on the consent.
*/
text: {
type: String,
value: 'This website uses cookies to give you the best possible experience.',
},
/**
* The link to the cookie policy used by your website (if there is one).
*/
policyLink: String,
/**
* The target for the cookie policy link used by your website (if there is one).
*/
policyTarget: {
type: String,
value: '_self'
},
/**
* The text to display on the link to the cookie policy.
*/
policyText: {
type: String,
value: 'Learn more',
},
/**
* The text to display on the button to accept the cookie policy.
*/
acceptText: {
type: String,
value: 'Got it!',
},
/**
* The text to display on the button to reject the cookie policy.
*
* Visible only if the cookie consent is also `rejectable`.
*/
rejectText: {
type: String,
value: 'No, thanks',
},
/**
* Enable this property if you want the cookie consent to be rejected.
*/
rejectable: Boolean,
/**
* Seconds to wait before making the toast appear.
*/
secondsBeforeAppearing: {
type: Number,
value: 0,
},
_countryCodes: {
type: Array,
readOnly: true,
value: function() {
return [
'AT',
'BE',
'BG',
'HR',
'CY',
'CZ',
'DK',
'EE',
'FI',
'FR',
'DE',
'GR',
'HU',
'IE',
'IT',
'LV',
'LT',
'LU',
'MT',
'NL',
'PL',
'PT',
'RO',
'SK',
'SI',
'ES',
'SE',
'GB',
];
},
},
},
_respond: function(e) {
var response = e.target.dataset.response;
// We got an invalid response
if ((response !== "accept") &&
(response !== "reject") &&
(response !== "true") &&
(response !== "false")) {
console.error('Error: invalid response!');
return;
}
var answer = (response === "accept") || (response === "true");
// Priority goes first to the session storage...
if (this.useSessionStorage)
sessionStorage.setItem('acceptCookies', answer);
// ...then to the local storage...
else if (this.useLocalStorage)
localStorage.setItem('acceptCookies', answer);
// ...and in the end, to the cookie
else
document.cookie = 'acceptCookies=' + answer + '; expires=Fri, 31 Dec 9999 23:59:59 GMT; path=/';
// Update the cookie consent status
this._setCookiesStatus(answer ? 'accepted' : 'rejected');
// Close the toast
this.$.consentToast.close();
},
_cookieVal: function() {
return document.cookie.replace(/(?:(?:^|.*;\s*)acceptCookies\s*\=\s*([^;]*).*$)|^.*$/, '$1');
},
_checkCountryCode: function(e) {
var response = e.detail.response;
// Flag to check if an error happened. In that case, we will use the default URL.
var error = false;
// The final country code we're going to use
var countryCode = '';
// The response is only a string.
// Just check if it corresponds to a country code, otherwise fallback to the default URL.
if (typeof response === 'string') {
countryCode = response;
} else if (typeof response === 'object') {
// Let's check if the object has the key defined by the user.
// If we have it, we have most probably found the user location.
if (this.geoIpParam in response)
countryCode = response[this.geoIpParam];
// Argh! The user tried to troll us or we had an error with the user defined API.
// Fallback to our beloved and (probably) reliable service
else
error = true;
// Is this even possible?
} else
error = true;
var _this = this;
if (error) {
// That would mean that our reliable service isn't working!
// Quit everything to avoid an infinite loop, and show the
// user the consent dialog anyways to avoid privacy problems.
if (this.geoIpUrl === 'https://freegeoip.net/json/') {
setTimeout(function() {
_this.$.consentToast.open();
}, this.secondsBeforeAppearing * 1000);
// User defined service is not working,
// set the default params and try again.
} else {
this.geoIpUrl = 'https://freegeoip.net/json/';
this.geoIpParam = 'country_code';
this.$.checkCountry.generateRequest();
}
// We SHOULD be safe here.
} else {
// User country is NOT subject to the cookie law,
// so we consider it as a consent.
if (this._countryCodes.indexOf(countryCode) < 0)
this._accept();
// User country IS subject to the cookie law.
// Display the consent.
else {
setTimeout(function() {
_this.$.consentToast.open();
}, this.secondsBeforeAppearing * 1000);
}
}
},
attached: function() {
var cookie = this._cookieVal();
// If the cookie exists
if (cookie.length > 0)
// Set the correct status
this._setCookiesStatus((cookie === 'true') ? 'accepted' : 'rejected');
// If there is no cookie, look in the local storage
else if (localStorage.acceptCookies)
// Set the correct status
this._setCookiesStatus((localStorage.getItem('acceptCookies') === 'true') ? 'accepted' : 'rejected');
// Last but not least, check in the session storage, even though we should not find it here
else if (sessionStorage.acceptCookies)
// Set the correct status
this._setCookiesStatus((sessionStorage.getItem('acceptCookies') === 'true') ? 'accepted' : 'rejected');
// If we cannot find the info anywhere, let's check the
// user country to see if we need to display him the consent.
else
this.$.checkCountry.generateRequest();
},
});
</script>
</dom-module>