npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

shadow-selection-polyfill

v1.1.0

Published

Polyfill for shadowRoot.getSelection in Safari 10+

Downloads

864

Readme

Polyfill for the shadowRoot.getSelection() method for Safari 10+. See a demo!

Safari supports .attachShadow() to create a Shadow Root, but does not support retrieving user selection within this root. You can safely use this code with other browsers (Firefox and Chromium), where it'll use the native version.

⚠️ This has been rewritten in February 2020 to fix a number of issues with the older version.

Usage

Include ./shadow.js as an ES6 module, and call its getRange method, passing the shadow root you would like to check. This uses a native implementation where available (on Firefox and Chromium).

Typically, you'd call this method in response to a selectionchange event, which is a global event on the document. However, this polyfill will cause additional selectionchange events to fire in the course of its work—possibly hundreds. Instead, you can listen to the -shadow-selectionchange event (exposed as shadow.eventName), which will safely fire only once.

import * as shadow from './node_modules/shadow-selection-polyfill/shadow.js';

const root = myElement.createShadowRoot({mode: 'open'});
root.innerHTML = `...`;

document.addEventListener(shadow.eventName, () => {
  const range = shadow.getRange(root);
  if (range) {
    console.info('range selected within root element', range.toString());
  }
});

Don't use this with .attachShadow({mode: 'closed'}), which is generally considered an antipattern anyway.

Install

Install via NPM as shadow-selection-polyfill, this has no dependencies. Depending on your transpiler, you might be able to include the polyfill with:

// naked imports
import * as shadow from `shadow-selection-polyfill`;
// require() compatibility
const shadow = require('shadow-selection-polyfill');

Implementation

This polyfill basically rapidly splits Text nodes until it can find out just how many characters from the 'edge' of a Shadow Root that a user has selected. It uses this combined with a few other tricks to come up with a range.

The algorithm is O(n) with respect to:

  • the maximum length of a text node that contains the start or end of a selection range
  • the depth of your nodes

If speed is important to you, then keep individual text nodes small.

Notes

Native Versions

As of February 2020, Firefox does not implement getSelection() on the Shadow Root (issue), but happily pierces the Shadow Root from the document globally. Chromium also implements ShadowRoot.getSelection() in an unofficial way. You can use this library to work around differences in browser implementations, as it'll use the native version when available.

Other

This isn't technically a polyfill, as it adds completely new functionality: it doesn't patch an existing method. There's nothing stopping us from emulating a faux-Selection, but it would probably make the code more complex than required.

This is not an official Google product.