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

selectricity

v1.3.0

Published

Simple DOM querying and event listening

Downloads

186

Readme

selectricity

A concise and effective replacement for jQuery.

selectricity is a simple library used to emulate some of the functonality provided by jQuery without the hefty filesize and unneeded complexity. It is a great tool for dev teams that have junior developers who may be transitioning to using vanilla JS, but can be useful for developers of any skill level. Type definitions now included for TypeScript projects!

Some of the main features of selectricity include:

  • Easy event listening
  • Reduce excessive looping
  • More concise and readable syntax than Vanilla JS

How to import:

 import select from 'selectricity';

Easy event listening

selectricity:

  select('[data-foo]').listen('click', () => {
    console.log('bar');
  });

Compare to Vanilla JS:

  const elements = document.querySelectorAll('[data-foo]');
  
  elements.forEach(($elem) => {
    $elem.addEventListener('click', () => {
      console.log('bar');
    });
  });

You can pass multiple event names to the "listen" method as you can in jQuery:

selectricity:

  const hoverElements = select('[data-hotspot]');

  hoverElements.listen('mouseenter mouseleave', ({ $node }) => {
    $node.toggleClass('active');
  });

Compare to Vanilla JS:

  const hoverElements = document.querySelectorAll('[data-hotspot]');

  hoverElements.forEach((el) => {
    el.addEventListener('mouseenter', () => {
      el.classList.toggle('active');
    });
    el.addEventListener('mouseleave', () => {
      el.classList.toggle('active');
    });
  })

Use object destructuring within the listen callback function to leverage helpful data. The data returned from the listen method are:

  • $node (the current node the event was fired on)
  • e (the event)
  • index (the index of the node in the query)
  const buttons = select('[data-button]');
  
  buttons.listen('click', ({ $node, e, index }) => {
    // callback code here
  });

To add an event listener to a dynamic element, simply pass a value of true as the second argument of the listen method.

  const buttons = select('[data-button]');
  
  buttons.listen('click', ({ $node, e, index }) => {
    // callback code here
  }, true);

Reduce excessive looping

In the following example, we will update the active image based on the index of the currently selected button.

selectricity:

  const buttons = select('[data-button]');
  const images = select('[data-image]');
  
  buttons.listen('click', ({ $node, e, index }) => {
    e.preventDefault();
    // remove active class from all buttons without looping!
    buttons.removeClass('active');
    // add active class to currently clicked button
    $node.addClass('active');
    // remove active class from all images without looping!
    images.removeClass('active');
    // add active class to image with the same index as the currently clicked button
    images[index].addClass('active');
  });

Compare to Vanilla JS:

  const buttons = document.querySelectorAll('[data-button]');
  const images = document.querySelectorAll('[data-image]');

  buttons.forEach((button, index) => {
    button.addEventListener('click', (e) => {
      e.preventDefault();
      // notice here how loops also create problematic variable shadowing which require awkward variable names in the loop to avoid duplication of variable names in parent scopes.
      buttons.forEach((btn) => {
        btn.classList.remove('active');
      });
      images.forEach((image) => {
        image.classList.remove('active');
      });

      button.classList.add('active');
      images[index].classList.add('active');
    });
  });

By using select JS in this instance, we've reduced our code from 16 lines to 10, completely removed the presence of looping, and made the code much easier to scan.

By default, select will search for the selector at the document level, but a different parent in which to perform the query can be provided as the second argument to the function. This can be especially useful when using web components:

JS:

  // update corresponing variant id on "Add to Cart" button as user selects different swatches.
  class AddToCart extends HTMLElement {
    constructor() {
      super();
      
      this.swatches = select('[data-swatch]', this);
      this.addToCart = select('[data-add-to-cart]', this);

      this.swatches.listen('click', ({ $node }) => {
        const { variantId } = $node.dataset;
        // remove active class from all swatches without looping!
        this.swatches.removeClass('swatch--selected');
        // add class to currently clicked node
        $node.addClass('swatch--selected');
        // update variant id value on add to cart button
        this.addToCart.dataset.addToCart = variantId;
      });
    }
  }

HTML:

  <add-to-cart>
    <button class="btn btn--primary" data-add-to-cart="12345">
      Add To Cart
    </button>
    <ul class="swatch-list">
      <li>
        <button class="swatch swatch--selected" data-swatch data-variant-id="12345">
          Grey
        </button>
      </li>
      <li>
        <button class="swatch" data-swatch data-variant-id="23456">
          Green
        </button>
      </li>
      <li>
        <button class="swatch" data-swatch data-variant-id="34567">
          Brown
        </button>
      </li>
    </ul>
  </add-to-cart>

API

Methods

listen(eventName, callback, dynamic) ⇒ void

Attach event listeners to selected element(s).

| Param | Type | Description | | ------ | ------------------- | ------------ | | eventName | string | Name of event to listen for on selected element(s). For multiple events, separate each event name by a single space. | | callback | function | Callback function to fire on event. | | dynamic | boolean | Indicates if element was dynamically generated. |

addClass(className) ⇒ void

Add class to selected element(s).

| Param | Type | Description | | ------ | ------------------- | ------------ | | className | string | Name of the class to add. |

removeClass(className) ⇒ void

Remove class from selected element(s).

| Param | Type | Description | | ------ | ------------------- | ------------ | | className | string | name of the class to remove. |

toggleClass(className) ⇒ void

Toggle class on selected element(s).

| Param | Type | Description | | ------ | ------------------- | ------------ | | className | string | name of the class to toggle. |

addAttr(attribute, value) ⇒ void

Add attribute to selected element(s).

| Param | Type | Description | | ------ | ------------------- | ------------ | | attribute | string | name of the attribute to add. | | value | string | value of the attribute to add. Defaults to empty string. |

removeAttr(attribute) ⇒ void

Remove attribute from selected element(s).

| Param | Type | Description | | ------ | ------------------- | ------------ | | attribute | string | name of the attribute to remove. |

toggleAttr(attribute) ⇒ void

Toggle attribute on selected element(s).

| Param | Type | Description | | ------ | ------------------- | ------------ | | attribute | string | name of the attribute to toggle. | | value | string | value of the attribute to toggle. Defaults to empty string. |