Medium-like text selection sharing without dependencies
Demo from the HubSpot blog
This lightweight library allows to create a simple interface to share selected text in a page, in the form of a small popover over the selected portion of text.
Features:
- customizable sharing channels ("sharers")
- restriction on selected elements
- customizable CSS classes and stylesheets
- hooks on opening and closing the popover, and on sharing action
All in a tiny library (less than 1.8 KB minified and gzipped, plus less than 0.5 KB for the optional provided style sheet and 0.5-1.3 KB for the sample sharers).
Via npm:
$ npm install --save highlight-share
After installing, import the library using the module loader of your choice:
// CommonJS
const highlightShare = require('highlight-share');
// ES6
import highlightShare from 'highlight-share';
// AMD
define([ 'highlight-share' ], highlightShare => {
// ...
});
// Global
var highlightShare = window.highlightShare;
Import any sharers you need:
import * as twitterSharer from 'highlight-share/dist/sharers/twitter';
import * as facebookSharer from 'highlight-share/dist/sharers/facebook';
import * as emailSharer from 'highlight-share/dist/sharers/email';
import * as copySharer from 'highlight-share/dist/sharers/copy';
import * as linkedInSharer from 'highlight-share/dist/sharers/linked-in';
import * as facebookMessengerSharer from 'highlight-share/dist/sharers/facebook-messenger';
Note that Facebook Messenger also requires a Facebook app ID, for example the abc123
string here:
const messengerShare = new facebookMessengerSharer.FacebookMessenger('abc123');
Create a variable specifying a DOM element selector
and an array of your sharers
:
const selectionShare = highlightShare({
selector: '#shareable',
sharers: [twitterSharer, facebookSharer, emailSharer, linkedInSharer, messengerShare, copySharer]
});
selectionShare.init();
Note: If the sharers
array is empty, nothing will happen.
The options for the highlightShare
factory include:
document
: theDocument
object to apply the sharing functionality (default:document
);popoverClass
: the class name (or names) to be used in the root element of the popover (default:highlight-share-popover
);selector
: restricts the shared text to the contents of the elements matchingselector
(default:"body"
);sharers
: an array of sharing channels (Twitter, Facebook, email...); see later for details;shareUrl
: a reference URL for the shared text (default: thelocation
object of thedocument
property);transformer
: a function that transforms the extracted selected text (default: a function that trims and collapses whitespaces);onOpen
: a function that gets called when the sharing popover is opened. The popover's element, the transformed selected text and its original version are passed as arguments;onClose
: a function that gets called when the sharing popover is closed.
When you're done sharing text, you can call the destroy
method;
selectionShare.destroy();
A destroyed sharing object can not be init
ialized again.
A "sharer" is an object with just one mandatory method: render
, that must return the HTML string of the sharing button;
and a name
property.
Note that Facebook Messenger also requires a Facebook app ID, for example the abc123
string here:
const messengerShare = new facebookMessengerSharer.FacebookMessenger('abc123');
This function receives these arguments:
text
: the text that should be shared;rawText
: the original selected text content (i.e., not mangled by thetransformer
);shareUrl
: the reference URL to be shared (see the options).
It must return the HTML of the button/link/element that should provide the required sharing functionality.
A unique string (among the sharers) that identifies the sharer (e.g.: "twitter"
, "facebook"
, ...).
This property could actually be a function (with the above signature) or a boolean, stating if the sharer is enabled (true
) or not.
If it's a function, it should return a truthy or falsy value, with the same meaning.
A function to be called when the user clicks/taps on the sharing button. The event
's default is not prevented. item
is the
<li>
element that wraps the sharer's button.
The following are the default basic sharers provided by the package:
Site | File location | Name | Global variable |
---|---|---|---|
dist/sharers/twitter.js |
twitter |
highlightShareViaTwitter |
|
dist/sharers/facebook.js |
facebook |
highlightShareViaFacebook |
|
Facebook Messenger | dist/sharers/facebook-messenger.js |
facebook-messenger |
highlightShareViaFacebookMessenger |
dist/sharers/linked-in.js |
linked-in |
highlightShareViaLinkedIn |
|
dist/sharers/reddit.js |
reddit |
highlightShareViaReddit |
|
dist/sharers/email.js |
email |
highlightShareViaEmail |
|
Copy | dist/sharers/copy.js |
copy |
highlightShareViaCopy |
The list of the sharers is also available on the sharers
property on the popover element (e.g. passed to the onOpen
callback), for dynamic
runtime handling.
On mobile browsers, you might not want to have highlight-share
to interfere with native sharing features, so you might want it disabled. In order
to it, you might want to do something like this:
if (!window.matchMedia
|| !window.matchMedia('(pointer: coarse)').matches) {
selectionShare.init();
}
(Why pointer: coarse
? If the device's primary pointer is "coarse" — that includes touch devices, but also Kinect and WiiMotes - then the
device probably features a native sharing interface. See CanIUse for details about Interaction
Media Features. If the browser doesn't support window.matchMedia
altogether, then it's probably a PC with a mouse/trackpad, so it's fine to
initialize highlight-share
.)
Keep in mind that native sharing features let the device do the job, using apps or services installed on it, highlight-share
keep this task on the page, meaning it could offer "sharing" capabilities that the device may not have (e.g.: "save to my account's notes" or "pronounce this using
voice synthesis"), so you might want to show both native and custom sharing interfaces.
This library's source code (that can be found in the src folder) uses ES2015 profusely, including ES2015 module definition and loading. Therefore, at the moment, its modules can't be require
d without prior transpilation. This also mean that this library is ready for when environments will finally support ES2015 modules. 🎉
The "module"
property is defined in package.json for those module loaders that support it. (Rollup, for example, which is also used to bundle the library).
Source files for style sheets are also provided in both LESS and SCSS form.
- Chrome/Opera
- Firefox 52+ (1)
- Edge
- Safari 10+ (2)
- Internet Explorer 9+
Notes:
- Firefox version 51 and below lacks support of the
selectionchange
event. - Safari version 9 and below lacks support of the
execCommand('copy')
event. If you aren't using thecopy
sharer, Safari support is version 5.1 and above.
- More tests (with headless browsers)
- More test coverage
- Fine-tune Babel
- Support for JSX in sharers'
render
method - Update ESLint rules to use Airbnb package
MIT @ Liz Shaw 2017-2018. See LICENSE. Project based on share-this.