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

data-xclass

v0.3.0

Published

A lightweight widget library for traditional SSR apps

Downloads

18

Readme

data-xclass

This is a lightweight library that is designed to make applying widgets to old-school SSR applications. It works by letting you add the names of the widgets you want to use in the data-xclass attribute.

Installation

There are few options on how to include/import data-xclass into your project.

Install from NPM

We can install XClass from NPM

npm install data-xclass
import XClass from "data-xclass";

XClass.register(...);

Use XClass from CDN

If you don't want to include data-xclass files in your project, you may use it from CDN:

<script src="https://cdn.jsdelivr.net/npm/data-xclass/dist/umd.min.js"></script>

Download assets

If you want to use data-xclass locally, you can directly download them from https://www.jsdelivr.com/package/npm/data-xclass

Quick Start

Creating a simple widget:

import XClass from "data-xclass";

// Register a new widget "red-class"
XClass.register("red-class", {
    // Initalize the widget on the element
    init: function (element) {
        element.classList.add("red");
    },

    // Clean up any resources when the widget is destroyed
    destroy: function (element) {
        element.classList.remove("red");
    }
});

The above code will register the red-class widget, which will add the red class to any element it is applied to.

To apply the widget, we add the data-xclass attribute to the element:

<div data-xclass="red-class">
  This element will have the red class
</div>

You can apply multiple widgets to an element by separating the widget names with a space.

Now we need to initialize XClass:

window.addEventListener("DOMContentLoaded", () => {
    XClass.start();
});

This method will search for DOM elements with the data-xclass attribute and initialize the appropriate widgets on them. In addition, it will track changes in the DOM tree and initialize widgets on new DOM elements.

If you imported XClass into a bundle, you have to make sure you are registering any widget IN BETWEEN when you import the XClass global object, and when you initialize XClass by calling XClass.start(). Otherwise, you will have to call XClass.initTree() to manually initialize the widgets.

API

XClass.register(name, widgetObject)

Register a widget with the given name.

Parameters

  • name: The name of the widget.
  • widgetObject: The widget object to be registered. It can have the following properties:
    • onRegister(self) - A method that is called when the widget is registered.
    • init(element, self) - A method that is called when the widget is applied to an element.
    • destroy(element, self) - A method that is called when the widget is removed from an element.
    • dependencies - An array of widget names that have to be initialized before this widget.

XClass.start()

Initialize XClass by searching for DOM elements with the data-xclass attribute and initializing the appropriate widgets on them.

In addition, it will track changes in the DOM tree and initialize widgets on new DOM elements.

XClass.stop()

Stops XClass from tracking changes in the DOM tree and initializing widgets on new DOM elements.

XClass.mutateDOM(callback)

Mutates the DOM in a safe way by temporarily disabling XClass and then re-enabling it after the DOM mutation is finished.

Parameters

  • callback: A function that will be called with no arguments. This callback will be executed with XClass disabled and should contain the DOM mutation logic.

XClass.isWidgetApplied(element, name)

Checks if the widget with the given name is applied to the given element.

Parameters

  • element: The element to check.
  • name: The name of the widget to check.

Returns

A boolean value indicating if the widget is applied to the given element.

XClass.addWidget(element, ...names)

Adds the given widgets to the given element.

Parameters

  • element: The element to which the widgets will be applied.
  • names: The names of the widgets to be applied.
const button = document.querySelector("#form-button");
XClass.addWidget(button, "red-class", "animated-button");

XClass.deleteWidget(element, ...names)

Removes the given widgets from the given element.

Parameters

  • element: The element from which the widgets will be removed.
  • names: The names of the widgets to be removed.
const button = document.querySelector("#form-button");
XClass.deleteWidget(button, "animated-button");

XClass.deleteAllWidgets(element)

Removes all widgets from the given element.

Parameters

  • element: The element from which all widgets will be removed.
const button = document.querySelector("#form-button");
XClass.deleteAllWidgets(button);

XClass.findClosest(element, name)

Finds the closest ancestor of the given element that has the given widget applied.

Parameters

  • element: The element to start searching from.
  • name: The name of the widget.

Returns

The element that has the widget applied, or null if the widget is not found.

const nameField = document.querySelector("input[name=name]");
const ajaxFormElement = XClass.findClosest(nameField, "ajax-form");

XClass.find(root, name)

Finds the first element in the given root element that has the given widget applied.

Parameters

  • root: The element to start searching from.
  • name: The name of the widget.

Returns

The element that has the widget applied, or null if the widget is not found.

const redElement = XClass.find(document, "red-class");
if (redElement) {
    XClass.deleteWidget(redElement, "red-class");
}

XClass.findAll(root, name)

Finds all elements in the given root element that have the given widget applied.

Parameters

  • root: The element to start searching from.
  • name: The name of the widget.

Returns

An array of elements that have the widget applied.

// Delete all instances of "red-class" widget
const redElements = XClass.findAll(document.documentElement, "red-class");
redElements.forEach(node => {
  XClass.deleteWidget(node, "red-class");
});

XClass.initTree(root = document.documentElement)

Initalizes all widgets in the given root element.

Parameters

  • root: The root element to start searching from. Defaults to document.documentElement.

XClass.destroyTree(root = document.documentElement)

Destroys all widgets in the given root element.

Parameters

  • root: The root element to start searching from. Defaults to document.documentElement.

Examples

Swiper.js widget

This example shows how to create a simple widget that uses Swiper.js to create a carousel:

import XClass from "data-xclass";
import Swiper from "swiper";
import { FreeMode } from "swiper/modules";

import "swiper/css";

XClass.register("simple-swiper", {
    init: function (element) {
        new Swiper(element, {
            modules: [FreeMode],
            spaceBetween: parseInt(element.dataset.swiperSpaceBetween) || 10,
            slidesPerView: parseInt(element.dataset.swiperSlidesPerView) || "auto"
        });
    },
    destroy: function (element) {
        const swiper = element.swiper;
        if (swiper) {
            swiper.destroy();
        }
    }
});

We can then apply this widget to an element with the data-xclass attribute:

<div class="swiper" data-xclass="simple-swiper" data-swiper-space-between="10" data-swiper-slides-per-view="3">
    <div class="swiper-wrapper">
        <div class="swiper-slide">Slide 1</div>
        <div class="swiper-slide">Slide 2</div>
        <div class="swiper-slide">Slide 3</div>
    </div>
</div>

Note that we are passing options to the widget via the data- attributes. This is a good practice as it allows us to configure the widget without having to modify our code.

Widget dependencies

This example shows how to create a widget that depends on another widget:

import XClass from "data-xclass";

XClass.register("red-class", {
    init: function (element) {
        element.classList.add("red");
    },
    destroy: function (element) {
        element.classList.remove("red");
    }
});

XClass.register("blue-class", {
    dependencies: ["red-class"],
    init: function (element) {
        element.classList.add("blue");
    },
    destroy: function (element) {
        element.classList.remove("blue");
    }
});

In this example, the blue-class widget depends on the red-class widget. This means that when the blue-class widget is applied, the red-class widget will automatically be applied first.

To apply the blue-class widget, we just need to set the data-xclass attribute:

<div data-xclass="blue-class">
  This element will have the red and blue classes
</div>

Alias for a set of widgets

Sometimes we want to apply multiple widgets to an element with a single command. We can do this by creating an alias for a set of widgets:

// Create an alias for the red-class and blue-class widgets
XClass.register("red-blue-classes", {
    dependencies: ["red-class", "blue-class"]
});

Now we can apply both the red-class and blue-class widgets with a single command:

<div data-xclass="red-blue-classes">
  This element will have the red and blue classes
</div>

License

MIT