Code Monkey home page Code Monkey logo

share-this's Introduction

share-this

Medium-like text selection sharing without dependencies

Version Build Status License Type

share-this in action

Purpose

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).

Installation

Via npm:

$ npm install --save share-this

Via bower:

$ bower install share-this

Via CDN:

<script src="https://cdn.jsdelivr.net/npm/share-this/dist/share-this.js"></script>

Usage

The library is in UMD format, so feel free to use the module loader of your choice:

// CommonJS
const shareThis = require("share-this");

// ES6
import shareThis from "share-this";

// AMD
define([ "share-this" ], shareThis => {
    // ...
});

// Global
var shareThis = window.ShareThis;

shareThis is a factory for text selection sharing functionality:

const selectionShare = shareThis({
    selector: "#shareable",
    sharers: mySharerList
});

selectionShare.init();

These are the options for the factory:

  • document: the Document 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: share-this-popover);
  • selector: restricts the shared text to the contents of the elements matching selector (default: "body");
  • sharers: an array of sharing channels (Twitter, Facebook, email...); see later for details;
  • shareUrl: a reference URL for the shared text (default: the location object of the document 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 initialized again.

If a layout change in the page moves the selected text from its original position, it might happen that the relative popover is not aligned to it anymore. If that happens, call the instance's reposition method:

if (selectionShare.reposition()) {
    console.log('Popover correctly realigned');
}

Sharers

A "sharer" is simply an object with just one mandatory method: render, that must return the HTML string of the sharing button; and a name property.

render(text: string, rawText: string, shareUrl: string) => string (mandatory)

This function receives these arguments:

  • text: the text that should be shared;
  • rawText: the original selected text content (i.e., not mangled by the transformer);
  • 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.

name: string (mandatory)

A unique string (among the sharers) that identifies the sharer (e.g.: "twitter", "facebook", ...).

active(text: string, rawText: string): any | boolean (optional)

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.

action(event: MouseEvent, item: HTMLLIElement): void (optional)

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.

Using the sharers

This library provides some default sharers, that could be loaded like this:

// CommonJS
const twitterSharer = require("share-this/dist/sharers/twitter");

// ES6
import * as twitterSharer from "share-this/dist/sharers/twitter";

// AMD
define([ "share-this/dist/sharers/twitter" ], twitterSharer => {
    // ...
});

// Global
const twitterSharer = window.ShareThisViaTwitter;

Then you can use the sharers of your choice:

const selectionShare = shareThis({
    sharers: [ twitterSharer ]
});

Note: the sharers array should not be empty, or nothing will ever happen.

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.

The following are the default basic sharers provided by the package:

Site File location Name Global variable
Twitter dist/sharers/twitter.js twitter ShareThisViaTwitter
Facebook dist/sharers/facebook.js facebook ShareThisViaFacebook
Reddit dist/sharers/reddit.js reddit ShareThisViaReddit
Email dist/sharers/email.js email ShareThisViaEmail
LinkedIn (*see note below!) dist/sharers/linked-in.js linked-in ShareThisViaLinkedIn

You can find a couple more on the presentation page of the library.

Note about the LinkedIn sharer: LinkedIn doesn't allow sharing a site with a custom title/snippet of text. Therefore ShareThis would fail to bring any value relatively to other sharing methods. The sharer is kept for backwards compatibility only. The following warning will appear in the console the first time the sharer is rendered:

LinkedIn doesn't allow sharing links with custom titles anymore, so the main point of ShareThis (sharing a portion of text) couldn't be accomplished. You're encouraged to share your URLs with other, more conventional means, like the official LinkedIn share plugin. See https://docs.microsoft.com/en-us/linkedin/consumer/integrations/self-serve/plugins/share-plugin

Developer friendly

This library's source code (that can be found in the src folder) uses ES2015 profusely, including ES2015 module definition and loading. This means that, at the moment, its modules can't be required without prior transpilation, but this also mean that this library is directly usable in environments that 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.

Browser support

  • Chrome/Opera
  • Firefox 52+ (1)
  • Edge
  • Safari 5.1+
  • Internet Explorer 9+

Notes:

  1. Firefox below v52 lacks support of the selectionchange event.

Mobile devices

On mobile browsers, you might not want to have share-this 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();
}

(The rationale of this is that 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 share-this.)

Keep in mind that native sharing features let the device do the job, using apps or services installed on it, share-this keep this task on the page, which means 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.

To do

  • Name change (issue)
  • More test coverage
  • Support for JSX in sharers' render method
  • Move the sharers from the library to separate packages (issue)

License

MIT @ Massimo Artizzu 2016-2019. See LICENSE.

share-this's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

share-this's Issues

undesired action with email sharer: create a new tab

Hi,

It's not really a bug but really ugly πŸ€“ !

Because of target"_blank" in the mailto link a new tab is create in browser on click.

Can you remove this attribute please?
It's not needed for mailto link as it will always open the mail client which is a different program.

Thank you πŸ˜„

More control over where the popup appears

I would like finer control over where the popup appears. The 'selector' option is OK but I could do with the option to exclude elements which are marked up with a specific class.

e.g. if I set my selector to 'body' then within the body I have

<p class="no-sharethis">blah blah</p>

Then the popup would not trigger when 'blah blah' is selected.

Thanks

shareThis is not a function

I'm probably doing something stupid but I need a hand please.

`
const shareThis = require("share-this");
const facebook = require("share-this/dist/sharers/facebook");
const email = require("share-this/dist/sharers/email");

const shareList = [facebook, email];

function configureShare() {
console.log("shareThis: ", shareThis);
shareThis({
selector: ".transcript",
sharers: shareList
}).init();
}

configureShare();
`

When I run this in Chrome I get:
"Uncaught Type Error: shareThis is not a function."

What am I doing wrong? thanks.

Uncaught TypeError: Cannot set property 'ShareThis' of undefined

First off, thanks for creating and sharing this tool!

I'm a Mac user running Codekit and have copied your code from the demo page. I'm getting this error when the page loads:

Uncaught TypeError: Cannot set property 'ShareThis' of undefined

Any thoughts? Thnx!

Popover is not in sync with scrollable/movable content

a demo of the problem can be found here: https://jsfiddle.net/0swr3m18/

  1. select content in the scrollable div
  2. scroll

actual: the popup's position is wrong
expected: the popup stays with the content

share-this cannot solve the problem itself, since it cannot track all possible ways how content could move.
However, there is currently no way for users of the library to trigger a refresh of the popover.

Request: Expose a redraw/refresh function, as shown in PR #15

BUG: share-this display with empty selection

Hi,

Just want to report a small bug.

If double click on a line-end it can select a space or a line-break.
Because share-this doesn't check the selection length when the previous happen, share-this popup.

You should add condition check to handle this (for exemple selection > 1)

Here is a screenshot so you can see by yourself the BUG:
screen shot 2017-12-30 at 11 25 35

Check for selection's actual appearance

It may happen that a selection may comprise just white space that gets collapsed, thus producing no visible selection. This leads to range.getClientRects() to produce an empty array of rects, so the library has no way to position the popover.

It may happen whn double-clicking outside the area that triggers the popover, or by modifiying the existing selection.

A check has to be performed on the constrained range prior to re/draw the popover.

Source map support

A project that utilizes this package and has source maps, emits this sort of trace when there is an error thrown from this package:

TypeError: Argument not optional
1
File "webpack:///./node_modules/share-this/dist/share-this.js" line 1 col 1655 in a
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"...
2
File "webpack:///./node_modules/share-this/dist/share-this.js" line 1 col 3262 in f
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"...
3
File "webpack:///./node_modules/share-this/dist/share-this.js" line 1 col 3162 in Anonymous function
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"...

I'm not 100% sure how to resolve this, it's either going to be one of two ways:

  1. Emit a source map .js.map alongside each file in dist/. I'm unsure if typical tooling can utilize source maps like this, but maybe!
  2. Maintain a ES2015 module entry point - so instead of importing share-this, the user can import share-this/es2015 and whatever compilation process a user uses can create the mappings.

Cannot read property 'getSelection' of undefined when unmounting React component

Hi,

first of all great little library! Congrats. We are trying to create a React component that will serve as a wrapper around share-this library. We have an issue when unmounting that component. It says

Cannot read property 'getSelection' of undefined

Here is the codesandbox that you can take a look https://codesandbox.io/s/0pl29v3p5l

Steps to reproduce:

  • Select a text
  • Clear selection by clicking outside of the text
  • Click on toggle button

Expected results

  • No error is thrown

z-index

Hello and happy new year!

I've notice a small improvement because of a bug on my side.

There is no way to modify the z-index.

Could you had a variable so we can adapt it to each case?

Thank you so much

SCSS organisation omit customisation

Hi,

Actually it's impossible to modify the variables by doing this for exemple:

// Changing variables
$share-this-highlight-link: transparent;

// Import the lib
@import '../../../node_modules/share-this/style/scss/share-this.scss';

It's not working because changed variables will be reseted as you are importing default variables along the main style.

To change this, you just need to create a new file call _style.scss where you'll put only the style classes without import _vars.scss.

Then inside share-this.scss you can import everything:

@import "vars";
@import "mixins";
@import "style";

Also you should add !default to all your variables likes this:

$share-this-vertical-offset: -.25em !default;
$share-this-background: #333333 !default;
$share-this-foreground: #ffffff !default;
$share-this-highlight-link: rgba(#ffffff, .25) !default;
$share-this-border-radius: .25em !default;
$share-this-arrow-size: .5em !default;
$share-this-sharer-width: 2em !default;
$share-this-sharer-height: 2em !default;
$share-this-sharer-padding: .35em !default;
$share-this-border-distance: 4em !default;
$share-this-animation-length: .3s !default;
$share-this-small-devices-max: 575px !default;

This will not break naming for actuals users but it will offer the possibility to change the variables.

And that's great ! πŸ˜„

LinkedIn not pulling in data

Im using the default implementation of the script and Facebook and Twitter are pull in dynamic text thats highlighted but LinkedIn opens the sharing window but dosent seem to be pulling in anything.

  var twitterSharer = window.ShareThisViaTwitter;
  var facebookSharer = window.ShareThisViaFacebook;
  var linkedinSharer = window.ShareThisViaLinkedIn;
  ShareThis({
    sharers: [ facebookSharer, twitterSharer, linkedinSharer ],
  }).init();

Does not work properly on iPhone

I discovered this bug in December 2021.
Reproduce on the latest iOS.

When I display share-this and try to tap the share button, it disappears.
https://maxart2501.github.io/share-this/
Perhaps the click event isn't working properly, but I'm not sure.

It works on PC and Android, so I think it's a problem only for iOS.
Is there any improvement plan?

Translate

I have A One Suggestion For You......

● That Add One another option in Pop-Up Window that , It Will Translate The Word or Sentence In User's Mother Tongue
β€’So that users can easily read and understand the blogs and readable content .

controlling when not to pop

Hello, many times, I see that the pop-up fires unintentionally. That happens when you highlight a text. Many times you get single word selections... Is there a way to tell the system that if the selection, say, more than 10 chars, only then pop?

Support for hiding the popover

Once the action is performed, it should be possible to call hide/close/killPopover. At the moment, it's only possible to destroy.

Popover goes over scrollable content

Hello Max,

Reposition method works as expected, it follows the text as it scrolls, but there is still one small problem here. If you scroll up while a text is selected and the popup is active, you will notice that popup goes over the "parent"(div that holds the text) and doesn't follow the text under it.

I made small fiddle example of the problem and you can check it at the following link: https://jsfiddle.net/Nikola22/oL5ha3tw/

Sharers not available in window object

<script src="https://cdn.jsdelivr.net/npm/share-this/dist/share-this.js"></script>

<script type="text/javascript">
	var shareThis = window.ShareThis;
	var twitterSharer = window.ShareThisViaTwitter;
	var facebookSharer = window.ShareThisViaFacebook;
	var linkedInSharer = window.ShareThisViaLinkedIn;
	var emailSharer = window.ShareThisViaEmail;

	console.log("TWT", twitterSharer);

	var selectionShare = shareThis({
    		sharers: [ twitterSharer, facebookSharer, linkedInSharer, emailSharer ]
	});

	selectionShare.init();
</script>

Inject above script in a web page, console.log("TWT", twitterSharer); is undefined. Same for other sharers

Disabling this as a user

Hello, I am a computer scientist who likes to highlight text of articles as I read them (similar to using my finger while reading a book). I do not like this extension and would like to disable it on my web-browser permanently. While I am technically savvy enough to add a rule on ublock-origin to stop this popup, I doubt most web-users are.

While I realize a global blocking rule is not feasible, I would love to have a little "x" to click on the first share-this popup that lets me disable this feature for whatever website, hopefully larger websites would keep this feature enabled as a positive user experience.

How to center tooltip?

Is there any option by any chance to center tooltip?
If you look closely to Medium, they have it.

BUG: Line height 2em breaking design

Hi @MaxArt2501 !

I have a new train coding chalenge for you haha.

There is a little gap in the bottom of each buttons. (easier to see on hover)

The problem come from the line-height property set to 2em on .share-this-popover>ul>li.
It should be reset to 1 without unit.

That's it πŸ˜„

babel-preset-es2015 is deprecated

Hello,

I use this plugin as dependency in my project but I remove recently babel-preset-es2015 because it is deprecated.

I replace it by babel-preset-env as recommended.

But import of hightlight-share fail without babel-preset-es2015

internal/streams/legacy.js:59
      throw er; // Unhandled stream error in pipe.
      ^
Error: ./node_modules/share-this/src/core.js
Module build failed: Error: Couldn't find preset "es2015" relative to directory "…/node_modules/share-this"
    at …/node_modules/babel-core/lib/transformation/file/options/option-manager.js:293:19
    at Array.map (native)
    at OptionManager.resolvePresets (…/node_modules/babel-core/lib/transformation/file/options/option-manager.js:275:20)
    at OptionManager.mergePresets (…/node_modules/babel-core/lib/transformation/file/options/option-manager.js:264:10)
    at OptionManager.mergeOptions (…/node_modules/babel-core/lib/transformation/file/options/option-manager.js:249:14)
    at OptionManager.init (…/node_modules/babel-core/lib/transformation/file/options/option-manager.js:368:12)
    at File.initOptions (…/node_modules/babel-core/lib/transformation/file/index.js:212:65)
    at new File (…/node_modules/babel-core/lib/transformation/file/index.js:135:24)
    at Pipeline.transform (…/node_modules/babel-core/lib/transformation/pipeline.js:46:16)
    at transpile (…/node_modules/babel-loader/lib/index.js:50:20)
 @ ./app/Resources/assets/js/highlightshare.js 3:17-38
 @ ./app/Resources/assets/js/main.js
 @ multi ./app/Resources/assets/js/main.js

I use webpack and babel-loader.
Babel seems to read .babelrc file of your package because I try to import a file heriting of this babel config. But babel-preset-es2015 is not present.

I think you should remove your .babelrc file form the prod package.

need help

hello.....first of all...thanks for this amazing code... I am learning java script...so its kinda hard for me grasp the code...and I wanted to learn this code...so .can you please help me...on where to start on this code...and the steps of this code....

Popover text not showing

Hey I tried implementing this in my React Project, in the useEffect Hook. But its is not working

Feature request: ability to change email icon

Social icon are pretty much all the same but there is no standard for icon.

Because of that it can break the design and uniformity and it could be nice to be able to change it in the config of each sharers.

By the way I've shared above a mail icon that would probably be a better choice than the actual one.
It is plain like other sharers contrary of the actual mail icon that is outline...

<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" width="32px" height="32px" viewBox="0 0 32 32">
<path d="M4.527 9.819l.983-.983 10.489 8.991 10.489-8.991.983.983-11.473 9.834L4.525 9.819zM3.221 6.26A2.435 2.435 0 0 0 .782 8.688v14.624a2.428 2.428 0 0 0 2.439 2.428H28.78a2.435 2.435 0 0 0 2.439-2.428V8.688A2.428 2.428 0 0 0 28.78 6.26H3.221z"/>
</svg>

Move the sharers to seperate packages

The sharers weren't meant to be a core part of the library, but rather ready-made examples of its usage.

On the other hand, they have been used like part of the library and became part of CI pipelines, causing issues like #37 when one has been removed.

For the next major release, remove the sharers from the library and move them in their separate packages.

whatsapp

Hi Max,

Probably it is no news to you, but I just want to tell that I appreciate your code. :)

I've got one question on how to bring in new sharers..
I've checked the twitter.js to understand what is going on there.
But the code there is minimized/uglified for a good reason.

Could you recommend a place where I can go get/or study & build ,say WhatsApp sharing, capability for example?

The ES module points to non-transpiled src/core.js file

This module claims support for various older versions of browsers.

But there is an edge case where this is not true.

When used with webpack or similar tools, it's a common practice to use import. Even the docs suggest using

// ES6
import shareThis from "share-this";

But there's a catch. The module resolver prefers module over main in package.json. This is true only for JS Modules (import syntax).

https://github.com/MaxArt2501/share-this/blob/v1.3.1/package.json#L13-L14

  "main": "dist/share-this.js",
  "module": "src/core.js",

In the case of share-this, it means that the import syntax will take the src/core.js. The usual webpack config will not compile anything from node_modules folder for performance reasons.

So when we put all of this together, the result is the raw src/* code landing in the vendor bundle, with const and everything. Internet Explorer says πŸ‘Ž πŸ˜„


There are a few possible solutions:

  1. Ship a transpiled dist/share-this.es.js and change the module to point to it.
  2. Remove the module and leave only the main. Most current build pipelines will work with the old commonjs way. Not sure if this will hold true in the future.
  3. Leave it to the consumers to figure it out, either import share-this/dist/share-this or transpile it on their end. It's like this at the moment, so no work required. It's a solution, but a bad one.

How to change append selector?

I see that the .share-this-popover is appended at the end of the body tag. Is there a way to change this to append it in another selector? Thanks.

Facebook sharer error

Hi,

first of all big thank for this library and your coding skills.

I am just finishing highlighting feature as a new "sharer", based on https://github.com/timdown/rangy
I hope to share it with you soon.

In the meantime I have also tried to test facebook sharer but unfortunately Facebook returns this error: "Invalid App ID: The provided app ID does not look like a valid app ID." Any hint how to update facebook sharer code?

Thank you very much

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.