Skip to content

Instantly share code, notes, and snippets.

@shgysk8zer0
Last active September 12, 2018 04:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shgysk8zer0/9d3923d2949fd66233e10ce4ca1d98f6 to your computer and use it in GitHub Desktop.
Save shgysk8zer0/9d3923d2949fd66233e10ce4ca1d98f6 to your computer and use it in GitHub Desktop.
Share API shim
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Share API Shim Demo</title>
<script type="aplication/javascript" src="/path/to/dialog-shim.js"></script>
<script type="module" src="index.js" async=""></script>
<script type="application/javascript" async="" nomodule=""></script>
</head>
<body>
<button class="share">Share this page</button>
</body>
</html>
import shareShim from './share-shim.js';
import {facebook, twitter, googlePlus, linkedIn, reddit} from './share-config.js';
shareShim(facebook, twitter, linkedIn, googlePlus, reddit);
document.querySelector('.share').addEventListener('click', async () => {
try {
navigator.share({
title: document.title,
url: location.href,
text: 'Shared using `navigator.share`'
});
} catch(err) {
console.error(err);
}
});
/**
* Icons available at https://github.com/shgysk8zer0/logos
* `mkdir img`
* `git submodule add https://github.com/shgysk8zer0/logos.git img/logos`
*/
export const facebook = {
url: new URL('https://www.facebook.com/sharer/sharer.php?u&t'),
icon: new URL('/img/logos/Facebook.svg', location.origin),
text: 'Facebook',
};
export const twitter = {
url: new URL('https://twitter.com/intent/tweet/?text&url'),
icon: new URL('/img/logos/twitter.svg', location.origin),
text: 'Twitter',
};
export const googlePlus = {
url: new URL('https://plus.google.com/share/?url'),
icon: new URL('/img/logos/Google_plus.svg', location.origin),
text: 'Google+',
};
export const linkedIn = {
url: new URL('https://www.linkedin.com/shareArticle/?title&summary&url'),
icon: new URL('/img/logos/linkedin.svg', location.origin),
text: 'LinkedIn',
};
export const reddit = {
url: new URL('https://www.reddit.com/submit/?url&title'),
icon: new URL('/img/logos/Reddit.svg', location.origin),
text: 'Reddit',
};
export default (...shares) => {
if (! Navigator.prototype.hasOwnProperty('share')) {
Navigator.prototype.share = ({
text = null,
title = null,
url = null,
} = {}) => new Promise((resolve, reject) => {
const size = 64;
const dialog = document.createElement('dialog');
const header = document.createElement('header');
const close = document.createElement('button');
const body = document.createElement('div');
const msg = document.createElement('b');
const font = 'Roboto, Helvetica, "Sans Seriff"';
function closeDialog(event) {
if (
(event.type === 'click'
&& ! event.target.matches('dialog[open],dialog[open] *')
) || (event.type === 'keypress' && event.code === 'Escape')
) {
dialog.close('Share canceled');
}
}
function closeHandler(event) {
if (Element.prototype.hasOwnProperty('animate')) {
const rects = dialog.getClientRects()[0];
const anim = dialog.animate([
{top: 0},
{top: `-${rects.height}px`},
], {
duration: 400,
easing: 'ease-out',
fill: 'both',
});
anim.onfinish = () => dialog.remove();
} else {
dialog.remove();
}
document.removeEventListener('keypress', closeDialog);
document.removeEventListener('click', closeDialog);
reject(new DOMException(event.detail));
}
if (text === null && title === null && url === null) {
reject(new TypeError('No known share data fields supplied. If using only new fields (other than title, text and url), you must feature-detect them first.'));
} else {
msg.textContent = 'Share via';
close.title = 'Close dialog';
shares.forEach(share => {
const link = document.createElement('a');
const icon = new Image(size, size);
if (share.url.searchParams.has('url')) {
share.url.searchParams.set('url', url);
} else if (share.url.searchParams.has('u')) {
share.url.searchParams.set('u', url);
}
if (share.url.searchParams.has('title')) {
share.url.searchParams.set('title', title);
} else if (share.url.searchParams.has('t')) {
share.url.searchParams.set('t', title);
}
if (share.url.searchParams.has('text')) {
share.url.searchParams.set('text', text);
}
link.style.setProperty('display', 'inline-block');
link.style.setProperty('margin', '0.3em');
link.style.setProperty('text-decoration', 'none');
link.style.setProperty('color', '#626262');
link.style.setProperty('text-align', 'center');
link.style.setProperty('font-family', font);
link.style.setProperty('font-size', '20px');
link.target = '_blank';
icon.src = share.icon.toString();
link.href = share.url.toString();
link.title = share.text;
link.append(icon, document.createElement('br'), share.text);
body.append(link);
link.addEventListener('click', () => {
resolve();
dialog.close();
});
});
dialog.style.setProperty('display', 'block');
dialog.style.setProperty('position' ,'fixed');
dialog.style.setProperty('background', '#fefefe');
dialog.style.setProperty('top', '0');
dialog.style.setProperty('bottom', 'auto');
dialog.style.setProperty('left', '0');
dialog.style.setProperty('right', '0');
dialog.style.setProperty('transform', 'none');
dialog.style.setProperty('border-radius', '0 0 5px 5px');
dialog.style.setProperty('max-height', '500px');
header.style.setProperty('height', '47px');
header.style.setProperty('line-height', '47px');
header.style.setProperty('color', '#232323');
header.style.setProperty('box-shadow', 'none');
header.style.setProperty('border-bottom', '1px solid #d5d5d5');
msg.style.setProperty('font-family', font);
msg.style.setProperty('font-size', '24px');
msg.style.setProperty('display', 'block');
close.style.setProperty('float', 'right');
close.style.setProperty('font-family', font);
close.style.setProperty('font-weight', 'bold');
close.style.setProperty('font-size', '16px');
if (CSS.supports('width', 'fit-content')) {
dialog.style.setProperty('width', 'fit-content');
} else if (CSS.supports('width', '-moz-fit-content')) {
dialog.style.setProperty('width', '-moz-fit-content');
} else if (CSS.supports('width', '-webkit-fit-content')) {
dialog.style.setProperty('width', '-webkit-fit-content');
} else {
dialog.style.setProperty('min-width', '320px');
}
header.append(close, msg);
close.append('X');
dialog.append(header);
dialog.append(body);
document.body.append(dialog);
dialog.showModal();
if (Element.prototype.hasOwnProperty('animate')) {
const rects = dialog.getClientRects()[0];
dialog.animate([
{top: `-${rects.height}px`},
{top: 0},
], {
duration: 400,
easing: 'ease-out',
fill: 'both',
});
}
dialog.addEventListener('close', closeHandler, {once: true});
document.addEventListener('keypress', closeDialog);
document.addEventListener('click', closeDialog);
close.addEventListener('click', () => {
dialog.close('Share canceled');
}, {once: true});
}
});
}
};
@kodeine
Copy link

kodeine commented Sep 12, 2018

Demo does not work on chrome browser?

screen shot 2018-09-11 at 11 52 20 pm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment