JSPM

  • Created
  • Published
  • Downloads 79
  • Score
    100M100P100Q69782F
  • License MIT

A super light weight package for querying the DOM, adding event listeners, removing them, making and manipulating elements and more.

Package Exports

  • base-elem-js
  • base-elem-js/dist/js/base-elem-js.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (base-elem-js) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

Base Elem Js

base-elem-js is a light-weight utility for DOM manipulation, including querying elements, adding/removing classes, setting/removing attributes, transitions and handling events. This package takes advantage of many the modern features of JavaScript, which has evolved greatly over the years. The minified package comes in at ~5.4kb which is about 93.7% smaller than jQuery 3.7.1!

Usage

To use the base-elem-js utility, you need to import it as follows:

import $be from 'base-elem-js';

Use via a CDN

Or you can simply add to your project via a CDN.

<!-- latest -->
<script src="https://cdn.jsdelivr.net/npm/base-elem-js"></script>
<script src="https://cdn.jsdelivr.net/npm/base-elem-js/dist/js/base-elem-js.min.js"></script>

<!-- unminified latest-->
<script src="https://cdn.jsdelivr.net/npm/base-elem-js/dist/js/base-elem-js.js"></script>

<!-- by version -->
<script src="https://cdn.jsdelivr.net/npm/base-elem-js@1.6.2"></script>

Base Elem Methods

find(selector: string | (elem: HTMLElement, i: number) => HTMLElement[], filter?: (elem: any, i: number) => boolean): BaseElem

// Examples
$be('ul').find('li');
//returns list of <li>'s

const bes = $be.static;
$be('ul').find('li', el => bes.hasClass(el,'foo')); 
//returns only <li> with .foo class

$be('li').find(el => el.closest('ul'));
// returns the parent element <ul>

$be('li:first-child').find(el => el.nextElementSibling as HTMLLIElement);
// find the first then get the next element

findBy

Finds elements matching the selector within the current elements and returns a new BaseElem instance.

findBy(type: FindBy, selector: string, filter?: (elem: any, i: number) => boolean): BaseElem

// Examples
const $siteHeader = $be('#site-header'); 
//returns the <header id="site-header" /> element.

$siteHeader.findBy('tag','li'); 
//returns all the <li> items in the $siteHeader

Finds elements by type (id, class, or tag) within the current elements and returns a new BaseElem instance.

findOne

findOne(selector: string): BaseElem

Finds the first element matching the selector within the current elements and returns a new BaseElem instance.

filter

filter(fn: (elem: HTMLElement, i: number) => boolean): BaseElem

Finds elements based on the filtering function within the current elements and returns a new BaseElem instance.

toArray

toArray(): HTMLElement[]

Returns a copy of the array of elements from the instance.

each

each(fn: (elem: HTMLElement, i: number) => void): BaseElem

Iterates over each element and applies the provided function.

map

map<T>(fn: (el: HTMLElement, i: number) => T, unique: boolean = true): (T | HTMLElement)[];

// Examples

const ulsList = $be('li').map(el => $li.map(el => el.closest('ul')));
// returns array of <ul>'s.

const liNexts = $be('li').map(el => el.nextElementSibling as HTMLElement);
//return's list of the next sibling <li>'s

The map method returns an array of the results of applying the function to each element. Optionally, it can ensure that the results are unique. This is designed to primarily return elements, so by default it filters out 'falsy' values, so be aware! If you need to filter an attribute or derive some value querying the elements, use the Array map method instead.

css

css(attrs: Partial<CSSProperties> | string): BaseElem | string;

// Examples
const $h1 = $be('h1');

$h1.css({color: 'green'}); // set the color green
$h1.css('color'); //returns the color 'green'

Sets or gets CSS properties for the current elements. If only passing a string, will return the property value.

addClass

addClass(cssNames: string | string[]): BaseElem

Adds the specified class(es) to the current elements.

rmClass

rmClass(cssNames: string | string[]): BaseElem

Removes the specified class(es) from the current elements.

tgClass

tgClass(cssNames: string | string[], toggle?: boolean): BaseElem

Toggles the specified class(es) on the current elements.

hasClass

hasClass(cssNames: string | string[], method: 'some' | 'every' = 'some'): boolean

Checks if the current elements have the specified class(es).

attr

attr(attrs: Record<string, string> | string): BaseElem

Sets or gets attributes for the current elements.

empty

empty(): BaseElem

Empties the content of the current elements.

remove

remove(): BaseElem

Removes the current elements from the DOM.

insert

insert(html: string | HTMLElement | HTMLElement[], method: AppendMethod = 'append'): BaseElem

// Examples
const $body = $be.findOne(document.body);

$body.find('h1').insert('<p>Some more copy</p>', 'before');
$body.insert('<p>Copy Prepended</p>', 'prepend');

Inserts HTML or elements into the current elements using the specified method (append, prepend, after, before).

html

html(html?: string): BaseElem | string;

// Examples
const $h1 = $be.find('h1');
$h1.html();//gets the inner html of the <h1>
$h1.html('<em>Light Weight Babbbbay</em>!');

Sets the inner HTML of the current elements. Left blank it will return the innerHTML.

text

text(text?: string): BaseElem | string;

Sets the inner text of the current elements. Left blank it will return the textContent.

on

// types for the Event
export type NativeEvents = keyof HTMLElementEventMap;
export type WindowEvents = keyof WindowEventHandlersEventMap;
export type DocEvents = keyof DocumentEventMap;
export type EventName = `${NativeEvents | WindowEvents | DocEvents}.${string}` | NativeEvents | WindowEvents | DocEvents | SyntheticEvent;
 

on(evtName: EventName | EventName[], fn: EventFn, delegateEl: string = null, config: boolean | AddEventListenerOptions = false): BaseElem;

// Examples
const $div = $be(div);

// attach a click event on a <div> and delegate the event to its <button> elements
$div.on('click.myClickName', (ev, elem) => {
    console.log('clicked', elem.textContent);
},'button');

// attach multiple events
$div.on(['mousemove.myMoveName', 'click.myClickName2'], (ev, elem) => {
    // your code here
},'button');

$div.on('[syntheticEventName]', (ev, elem) => {
    console.log('synthetic event!', ev.type, elem)
})

Adds an event listener to the current elements. It's recommended to namespace the events with a '.', for example click.myClickName. This method is not designed to keep track of multiple events o the same name, so namespacing is important if you seek to potentially remove an event. Pass in an array or single value for the evtName parameter. For a synthetic event pass it in [], so [syntheticEventName], this is essentially for the best Typescript support (otherwise string would invalidate the type checking of the event name).

off

// see EventName type right above
off(evtName: EventName | EventName[], config: boolean | AddEventListenerOptions = false): BaseElem;

// Examples
$div.off('click.myClickName');
//remove one event

$div.off(['mousemove.myMoveName', 'click.myClickName']);
//removes multiple events

Removes an event listener from the current elements. Pass in the same string value as the 'on' method. Namespace with '.', or click.myClickName as the function name. Can also pass in an array of strings for the evtName param.

trigger

trigger(evtName: EventName, delgateEl?: string): BaseElem;

// Examples
$div.trigger('click.myClickName','button');

$div.trigger('[syntheticEventName]');

Triggers native events as well as synthetic events. Can also trigger namespaced events such as click.myClickName.

Extending library

The BaseElem class can be refrenced for extension as seen below.

$be.BaseElem.prototype.superbPlugin = superbPlugin();

Base Elem Static ($be.static)

make

make(tag: string, attrs?: Record<string, any>, html?: string): HTMLElement;

// Example
const div = bes.make('div', { id: 'test', className: 'test' }, 
    `<h2>Hello Make!</h2>
    <p>Some copy goes here</p>`
);
document.body.appendChild(div);

Creates a new HTML element with the specified tag, attributes, and inner HTML content.

isHidden

isHidden(elem: HTMLElement): boolean

Checks if the specified element is hidden (i.e., has display: none or visibility: hidden).

isVisible

isVisible(elem: HTMLElement): boolean

Checks if the specified element is visible (i.e., does not have display: none or visibility: hidden).

find

find(selector: string, base: HTMLElement = document): HTMLElement[]

Finds elements matching the selector within the specified base element.

findBy

findBy(type: FindBy, selector: string, base: HTMLElement = document): HTMLElement[]

Finds elements by type (id, class, or tag) within the specified base element.

findOne

findOne(selector: string, base: HTMLElement = document): HTMLElement

Finds the first element matching the selector within the specified base element.

addClass

addClass(elem: HTMLElement, cssNames: string | string[]): void;

// Examples
const div = bes.findOne('div');

// add a single class
bes.addClass(div, 'new-class');

// add multiple
bes.addClass(div, ['new-class', 'another']);

Adds the specified class(es) to the element.

rmClass

rmClass(elem: HTMLElement, cssNames: string | string[]): void

Removes the specified class(es) from the element.

tgClass

tgClass(elem: HTMLElement, cssNames: string | string[], toggle?: boolean): void

Toggles the specified class(es) on the element.

hasClass

hasClass(elem: HTMLElement, cssNames: string | string[], method: 'some' | 'every' = 'some'): boolean

Checks if the element has the specified class(es).

attr

attr(elem: HTMLElement, attrs: Record<string, string> | string): void

Sets or gets attributes for the element.

empty

empty(elem: HTMLElement): void

Empties the content of the element.

remove

remove(elem: HTMLElement): void

Removes the element from the DOM.

insert

insert(elem: HTMLElement, html: string | HTMLElement | HTMLElement[], method: AppendMethod = 'append'): void;

// Example
bes.insert(div, '<p>Inserted content</p>', 'before');

Inserts HTML or elements into the specified element using the specified method (append, prepend, after, before).

html

html(elem: HTMLElement, html: string): void

Sets the inner HTML of the element.

text

text(elem: HTMLElement, text: string): void

Sets the inner text of the element.

on

on(baseEl: EventElem, evtName: `${Event['type']}.${string}` | string, fn: EventFn, delegateEl: string = null, config: boolean | AddEventListenerOptions = false)

Adds an event listener to the current elements. Namespace the events with a '.', for example click.myClickName.

off

off(evtName: string, config: boolean | AddEventListenerOptions = false);

Removes an event listener from the current elements. Pass in the same string value as the 'on' method. Namespace with '.', or click.myClickName as the function name.

trigger

trigger( target: HTMLElement, evtName: string, delegateEl?: string, config?: boolean | AddEventListenerOptions);

Trigger native, synthetic and namespaced navtive events.

Animate/Transition Static Methods

This library includes a couple extra functions to help with transitions and simple animations.

useCssAnimate

The useCssAnimate function is a utility for handling CSS animations on HTML elements. It provides a way to start and end CSS animations with a specified duration and optional callback function.

const [cssAnimate, cssState] = useCssAnimate(elems: HTMLElement | HTMLElement[], baseCss: string = '');

Adds the following CSS classes to and element or elements

  • [custom name]-starting or starting (if second param is empty) at the start of the animation
  • [custom name]-ending or ending as the animation is ending
  • [custom name]-active or active if the animation is active. Inactive state would be left without this class

Returns

[(start: boolean, duration?: number, endFn?: () => void) => void, CSSActionStates]: A tuple containing: A function to start the animation. An object representing the CSS action states.

Example

const [cssAnimate, cssState] = useCssAnimate(element, 'my-animation');

// To start the animation
cssAnimate(true, 500, () => {
    console.log('Animation started');
});

// To end the animation
cssAnimate(false, 500, () => {
    console.log('Animation ended');
});

console.log(cssState.starting) // returns the name of the starting class
console.log(cssState.ending) // returns the name of the ending class
console.log(cssState.active) // returns the name of the active class

useTransition

The useTransition function is a utility for managing transitions. It provides a way to handle the start and end of transitions with a specified duration.

Returns

Function: A function that takes three parameters: startFn ((...args: any) => void): A function to be called when the transition starts. endFn ((...args: any) => void): A function to be called when the transition ends. duration (number, optional): The duration of the transition in milliseconds. Default is 300ms.

const transition = useTransition();

const startTransition = () => {
    console.log('Transition started');
};

const endTransition = () => {
    console.log('Transition ended');
};

// Start the transition with a duration of 400ms
transition(startTransition, endTransition, 400);

Internal Functionality

The useTransition function maintains the state of the transition using a boolean flag (inTransition) and a timeout (tto). It also keeps track of the current end transition function (currEndTransitionFn).

When the returned function is called:

  • If a transition is already in progress, it clears the current timeout and calls the current end transition function.
  • It then calls the provided startFn to start the transition.
  • It sets a timeout to call the provided endFn after the specified duration, marking the transition as complete.

This ensures that transitions are properly managed and do not overlap.