Skip to content

Commit 294a50d

Browse files
committed
Extend browser support with dialog polyfill
1 parent 82af447 commit 294a50d

18 files changed

+197
-67
lines changed

README.md

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
#### [View demo](https://replete.github.io/biscuitman)
66

7-
100kB+ seemed too heavy for a cookie popup so I wrote this. It's currently < 4kB gz/br, including CSS. It's designed to be as small as possible with an adequate featureset for basic website cookie consent.
7+
100kB+ seemed too heavy for a cookie popup so I wrote this. It's around 4kB gz/br, including CSS. It's designed to be as small as possible with an adequate featureset for basic website cookie consent.
88

99
- Stores consent in `localStorage`, exposes in `window.Consent` and through custom events fired on `document`
1010
- Handles consent granulated by custom sections (e.g. essential, performance, analytics...)
@@ -21,16 +21,10 @@
2121
- include optional link in any text
2222
- CSS classes on `<html>` element for consents
2323
- Progressively enhanced CSS
24-
- Ideal experience browser support (targeted via browserlist string `>= 2%, last 2 years`):
25-
- Chrome/Edge 105+ (should be fine in many earlier versions, TBD)
26-
- Safari 15.4+
27-
- Firefox 121+ (should be fine in many earlier versions, TBD)
28-
- If JS fails in an old browser, it will probably be fixable by updating `browserlist` in `package.json` then rebuilding
29-
- (Will be tested more definitively with browserstack at some point)
30-
- source styles use CSS Nesting which is explicitly processed out for compatibility
24+
- Dialog polyfill loads as required (see [Browser Support](#browser-support))
3125
- Experimental ESM version included `biscuitman.mjs` (see [ESM demo](https://replete.github.io/biscuitman/index-esm.html))
3226
- Preliminary e2e tests:
33-
![tests](https://github.com/replete/biscuitman/actions/workflows/node.js.yml/badge.svg)
27+
![tests](https://github.com/replete/biscuitman/actions/workflows/node.js.yml/badge.svg) ([failing due to GTM.js bug](https://github.com/replete/biscuitman/issues/4), pass locally)
3428

3529
## How to use
3630
[View demo](https://replete.github.io/biscuitman) for a more detailed example
@@ -74,6 +68,7 @@
7468
// more: '(Show more)', // Show more button text
7569
// noCookies: 'No cookies to display', // Displayed in expanded sections within modal
7670
// acceptNonEU: false, // When enabled biscuitman checks browser locale timezone to see if it matches EU, if not it will auto consent
71+
//dialogPolyfillUrl: '//cdnjs.cloudflare.com/ajax/libs/dialog-polyfill/0.5.6/dialog-polyfill.min.js' // extends browser support, overridable if you want to self-host. Grab the .css too, and host in the same place.
7772
7873
message: 'By clicking "Accept All", you agree to the use of cookies for improving browsing, providing personalized ads or content, and analyzing traffic. {link}',
7974
// {link} inside any configuration string will be replaced with an <a> link
@@ -151,7 +146,7 @@ I've included an ESM version as an alternative packaging format. Longterm it's b
151146

152147
## Theme CSS
153148

154-
It's easy enough to theme the included styles by overriding CSS variables. They are shortened for filsize savings, but straightforward:
149+
It's easy enough to theme the included styles by overriding CSS variables. They are shortened but straightforward:
155150

156151
```css
157152
/* hacker mode */
@@ -185,15 +180,22 @@ html.bm-show::after {
185180

186181
## Browser Support
187182

188-
With browserlist, we're targeting `">= 2%, last 2 years"`. This project is tested with BrowserStack. The earliest versions tested working are:
183+
With browserlist, we're targeting `">= 2%, last 2 years"`. The earliest versions tested working are:
189184

190185
- Chrome/Edge/Opera: 85+ (released June 2020)
191186
- Firefox: 98+ (released March 2022)
192-
- Safari Desktop+iOS: 15.4+ (released March 2022)
193-
- I couldn't easily test 15.0-15.3, 14.1 is broken though
187+
- Safari (inc iOS): 15.4+ (released March 2022)
194188
- Samsung Internet: 14+ (released April 2021)
195189

196-
Currently if this is used in a browser that breaks interactivity (e.g. Safari 14.1, released April 2021), the site is unusable. It might be worth catching errors for unsupported browsers and removing the UI altogether for these extreme edge cases of users not updating their browsers.
190+
With `v0.3.19`, a [polyfill for dialog](https://github.com/GoogleChrome/dialog-polyfill) is loaded as necessary, extending the support to include these browsers (tested):
191+
192+
- Safari (inc iOS): 13.1+ (released March 2020)
193+
- Firefox: 77+ (released June 2020)
194+
- Firefox Android: 79+ (released August 2020)
195+
196+
If you need to support earlier than these browsers, you will need to start loading polyfills for missing javascript features, starting with `String.prototype.replaceAll`. [Cloudflare's polyfill CDN site](https://cdnjs.cloudflare.com/polyfill) will help you generate a package which will need to load before biscuitman.
197+
198+
This project is tested with BrowserStack.
197199

198200
## Globals
199201
- `biscuitman` – configuration object, must be `window.biscuitman` (`biscuitman.create(options)` for ESM version)
@@ -213,10 +215,12 @@ Currently if this is used in a browser that breaks interactivity (e.g. Safari 14
213215
- `bmOpen()` – Opens My Consent Settings modal (you might want to link this on your Privacy policy or footer nav)
214216
- example usage: `<a href="javascript:bmOpen();"> Update my consent settings</a>`
215217

218+
The ESM version currently does still use some globals.
219+
216220
## CSS Classes
217221

218222
- `biscuitman` on UI container
219-
- `bm-{sectionName}`, `bm-no-{sectionName}`, `bm-show` on `<html>`
223+
- `bm-{sectionName}`, `bm-no-{sectionName}`, `bm-show` and sometimes `bm-dialog-polyfill` on `<html>`
220224
- `--bm-height` CSS variable written to `<html style="--bm-height:0px;">`
221225

222226
## Events
@@ -241,22 +245,22 @@ document.addEventListener('biscuitman:open', (e) => {
241245

242246
## Development
243247

244-
`npm run dev` fires up a browsersync dev server on `https://localhost:3000`.
248+
`npm run dev` fires up a browserSync development server on `https://localhost:3000`.
245249

246-
We need to use `https://` to be able to delete Secure cookies.
250+
We need `https://` active to be able to delete Secure cookies.
247251

248252
### Fix NET::ERR_CERT_AUTHORITY_INVALID error
249253

250-
This isn't a problem for testing the UI, but is a problem for the tests running headless browsers. To fix this:
254+
To prevent invalid certificate warnings, you can generate a local SSL key with `mkcert`:
251255
- Install `mkcert` ([Installation instructions](https://github.com/FiloSottile/mkcert#installation)) and then run:
252-
- run `npm run makecerts`, to create `server.crt` and `server.key` for browserSync
256+
- run `npm run makecerts`, to generate `server.crt` and `server.key` for browserSync dev server
253257
- if you're using another solution for local SSL certs, generate `server.crt` and `server.key` manually and place them in the root
254258

255259
Visiting `https://localhost:3000` should now work without warnings.
256260

257261

258262
### Building
259-
`npm run build` - creates project distributes via `run.js` a custom build script requiring `Node v20`
263+
`npm run build` - creates project distributes via `run.js`, a custom build script requiring `Node v20`
260264

261265
### Tests
262266
Jest is set up with puppeteer to run some integration tests. We're using `@swc/jest`'s rust implementation of jest to speed things up. This is only chromium for now, but at some point it would be good to implement browserStack selenium tests to automate browser compatibility checks.

dist/biscuitman.css

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/*! biscuitman.js 0.3.18 */
1+
/*! biscuitman.js 0.3.19 */
22
.biscuitman {
33
--ui: 0, 0, 0;
44
--tx: #444;
@@ -16,7 +16,7 @@
1616
box-shadow: 0 -2px 10px #00000029;
1717
}
1818

19-
html.bm-show .biscuitman {
19+
.bm-show .biscuitman {
2020
display: block;
2121
}
2222

@@ -175,7 +175,7 @@ html.bm-show .biscuitman {
175175

176176
.biscuitman .bm-dialog > b:after {
177177
content: "";
178-
background: linear-gradient(180deg, var(--bg) 20%, transparent);
178+
background: linear-gradient(180deg, var(--bg) 20%, #fff0);
179179
pointer-events: none;
180180
z-index: 1;
181181
width: 100%;
@@ -188,7 +188,7 @@ html.bm-show .biscuitman {
188188

189189
.biscuitman .bm-dialog nav:after {
190190
content: "";
191-
background: linear-gradient(0deg, var(--bg) 20%, transparent);
191+
background: linear-gradient(0deg, var(--bg) 20%, #fff0);
192192
pointer-events: none;
193193
width: 100%;
194194
height: 25px;
@@ -385,3 +385,9 @@ html.bm-show .biscuitman {
385385
.biscuitman label input {
386386
opacity: 0;
387387
}
388+
389+
.bm-dialog-polyfill .biscuitman dialog {
390+
position: fixed;
391+
top: 50%;
392+
transform: translateY(-50%);
393+
}

dist/biscuitman.js

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/*! biscuitman.js 0.3.18 */
1+
/*! biscuitman.js 0.3.19 */
22
((d, w, O, h, bm)=>{
33
const defaults = {
44
key: 'myconsent',
@@ -18,7 +18,8 @@
1818
info: '',
1919
more: 'Show more',
2020
noCookies: 'No cookies to display',
21-
acceptNonEU: false
21+
acceptNonEU: false,
22+
dialogPolyfillUrl: '//cdnjs.cloudflare.com/ajax/libs/dialog-polyfill/0.5.6/dialog-polyfill.min.js'
2223
};
2324
const o = {
2425
...defaults,
@@ -82,6 +83,7 @@
8283
</dialog>`.replaceAll('{link}', `<a href="${o.linkURL}">${o.linkText}</a>`);
8384
ui.querySelectorAll('button').forEach((b)=>b.addEventListener('click', buttonHandler));
8485
dialog = ui.querySelector('dialog');
86+
if (!dialog.showModal || !dialog.close) loadDialogPolyfill();
8587
dialog.addEventListener('close', closeModalHandler);
8688
dialog.addEventListener('cancel', cancelModalHandler);
8789
const moreLink = ui.querySelector('.more');
@@ -235,7 +237,7 @@
235237
});
236238
clearStorages();
237239
insertScripts();
238-
dialog.close();
240+
if (dialog.open) dialog.close();
239241
displayUI(false);
240242
}
241243
function insertScripts() {
@@ -312,4 +314,18 @@
312314
});
313315
openModal();
314316
};
317+
function loadDialogPolyfill() {
318+
// https://github.com/GoogleChrome/dialog-polyfill
319+
h.classList.add('bm-dialog-polyfill');
320+
const script = d.createElement('script');
321+
script.src = o.dialogPolyfillUrl;
322+
script.onload = ()=>{
323+
w.dialogPolyfill.registerDialog(dialog);
324+
};
325+
d.head.appendChild(script);
326+
const link = d.createElement('link');
327+
link.rel = 'stylesheet';
328+
link.href = o.dialogPolyfillUrl.slice(0, -2) + 'css';
329+
d.head.appendChild(link);
330+
}
315331
})(document, window, Object, document.documentElement, 'biscuitman');

0 commit comments

Comments
 (0)