🚀 Big News:Socket Has Acquired Secure Annex.Learn More
Socket
Book a DemoSign in
Socket

baseframe-js

Package Overview
Dependencies
Maintainers
1
Versions
167
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

baseframe-js

Baseframe JS is a comprehensive suite of modular plugins and utilities designed for front-end development

latest
Source
npmnpm
Version
7.2.2
Version published
Weekly downloads
60
-69.07%
Maintainers
1
Weekly downloads
 
Created
Source

Baseframe JS

Baseframe JS is a comprehensive suite of modular plugins and utilities designed for front-end development. It provides solutions for common UI needs supplying solutions for: modals, collapsible sections, parallax effects, tabs and more. Additionally it has utility functions for cookies, smooth scrolling, debouncing, and URL state management. All plugins are highly configurable and follow consistent patterns, making it easy to integrate and extend them in your projects.

Features

Baseframe JS is meant to be something you can build off of.

  • Consistent Plugin Architecture: All plugins share a unified API and configuration approach, simplifying usage and customization.
  • Data Attribute Configuration: Easily configure plugins via data- attributes using object literal syntax.
  • Dynamic Parameter Updates: Update most plugin parameters after initialization without re-instantiating.
  • Event Callbacks: Register callbacks for key plugin events (e.g., open, close, update).
  • TypeScript Support: Full type definitions for seamless integration with TypeScript projects.
  • Flexible DOM Library Integration: Extend plugins into jQuery, Cash-Dom, or Base Elem JS.
  • Minimal, Customizable SCSS: Base styles provided for all plugins, easily extended or overridden.

Usage

Importing Plugins

You can import all plugins and utilities at once, or selectively import only what you need for optimal bundle size:

import libraryExtend, {
    AccessibleMenu,
    Collapse,
    Cookies,
    LazyLoad,
    NavDesktop,
    NavMobile,
    Parallax,
    SelectEnhance,
    Tabs,
    Toastr,
    UrlState,
    smoothScroll,
    debounce,
    debounceResize,
    focusTrap
} from 'baseframe-js';

// For tree-shaking, import individual modules:
import Collapse from 'baseframe-js/dist/js/Collapse';

Extending a DOM Library

Baseframe JS plugins can be installed into jQuery, Cash-Dom, or Base Elem JS:

libraryExtend([
    Collapse,
    LazyLoad,
    Modal,
    NavDesktop,
    NavMobile,
    Parallax,
    SelectEnhance,
    Tabs,
    Toastr
], $library);

TypeScript Integration

To enable full type support with jQuery or Cash-Dom, extend their interfaces with the provided plugin types:

import {
    Collapse, type CollapsePlugin,
    Modal, type ModalPlugin,
    // ...other plugins: 
    // All plugins types are named the following way: [Plugin Name]Plugin
} from 'baseframe-js';

declare global {
    interface JQuery<TElement = HTMLElement> extends CollapsePlugin, ModalPlugin {}
}

declare module 'cash-dom' {
    interface Cash extends CollapsePlugin, ModalPlugin {}
}

Configuring Plugins via Data Attributes

All plugins accept configuration via a data-pluginName-options attribute in object literal format:

<div id="your-plugin-elem" data-pluginName-options="{ option: 'value', anotherOption: true }"></div>

Updating Plugin Parameters

Most plugin parameters can be updated after initialization by calling the plugin method again with new options:

$('.your-plugin-elem').plugin({ option: 'newValue', height: 1000 });

Removing a Plugin Instance

Remove a plugin and its components by calling:

$('.element').plugin('remove');

Or, using the static method:

$.plugin.remove($('.element').eq(1));

Including Base Styles

All base SCSS styles are located in the dist/scss/ directory. Import and customize as needed for your project.

Available Plugins

  • Accessible Menu: Keyboard-friendly navigation with arrow key support and escape-to-close.
    View Accessible Menu

  • Collapse: Expandable/collapsible sections, suitable for accordions and more.
    View Collapse

  • Lazy Load: Run custom code for elements as they enter and exit the viewport. Also, loads images and backgrounds as they approach the viewport using IntersectionObserver.
    View Lazy Load

  • Modal: Flexible modal dialogs with focus trapping, customizable content, and event hooks.
    View Modal

  • Navigation Desktop: Enhanced desktop navigation with edge detection and mouse refocus.
    View Navigation Desktop

  • Navigation Mobile: Mobile-first navigation with toggleable sub-sections.
    View Navigation Mobile

  • Parallax Elements: Horizontal, vertical, and zoom parallax effects with background fill options.
    View Parallax Elements

  • Scroll Spy: Highlights navigation elements based on scroll position and anchor targets.
    View Scroll Spy

  • Select Enhance: Fully stylable <select> elements with enhanced dropdowns. Supports the <optgroup> option grouping. View Select Enhance

  • Tabs: Accessible tabbed interfaces with keyboard navigation and history tracking.
    View Tabs

  • Toastr: Dismissible notification messages with customizable positions and stacking.
    View Toastr

Utility Functions

libraryExtend

Integrates plugins into a DOM manipulation library (jQuery, Cash, or Base Elem JS):

libraryExtend(
  plugins: Array<Plugin> | Plugin,
  Library: Cash | jQuery | BaseElem,
  notify?: boolean
);

Parameters

  • plugins: Can be one Plugin, or an array of them.
  • Library: The second parameter is the library to extend into. Currently can plug into jQuery, Cash, or the Base Elem which is used in the package.
  • notify (optional): The final parameter console logs each updated parameter when they get updated. Really meant only for development purposes to help debugging.

smoothScroll

Smoothly scrolls to a target Y position with optional easing and callback:

smoothScroll(
    scrollTargetY: number,
    duration?: number,
    easing?: EasingFn | Easings,
    scrollEndFn?: (...args) => void
);

Parameters

  • scrollTargetY: The destination to scroll to. Pass in the Y position of the element you want to scroll to.
  • duration (optional): The time in milliseconds over which the scroll animation occurs. Defaults to 400ms if not specified.
  • easing (optional): Accepts a custom easing function or the following string values: 'linear', 'easeInOutCubic', 'easeInOutQuart', 'easeOutQuint'.

focusTrap

Traps keyboard focus within a container (used by Modal):

const trappedFocus = focusTrap(element: Cash | HTMLElement, params?: ITrapFocusProps);
// Remove later:
trappedFocus.remove();

Cookies

Static class for managing browser cookies:

Cookies.set('cookieName', 'value', { path: '/', expires: 60 });
Cookies.get('cookieName');
Cookies.remove('cookieName', { path: '/' });

Parameters

  • cookieName: The cookie name
  • cookieValue: The value of the cookie
  • config (optional): The configuration of the cookies being set

Cookie Configation Options

OptionDescription
pathPath to the cookie, default is the current location.pathname.
expiresSet in minutes. Time the cookie will expire.
secureSets the cookie so it can only be accessed via https protocol. This gets set automatically when sameSite is set to None.
sameSiteLax, Strict, or None are the options.

debounce and debounceResize

Debounce event handlers or window resize events to improve performance:

debounce('#my-button', 'click', (ev, elem) => { ... }, { delay: 300 });
debounceResize(() => { ... }, 200);

debounce Parameters

  • elem: The element(s) or selector to bind the event to.
  • event: The event name(s) to listen for (e.g., 'click', 'input').
  • cb: The callback function to run after the debounce delay.
  • config (optional):
    • immediate (boolean): If true, the callback fires immediately on the first event, then debounces subsequent calls. Default: false.
    • delay (number): The debounce delay in milliseconds. Default: 100.

UrlState

Static class for managing URL hash and search parameters:

UrlState.set('search', 'param', 'value');
UrlState.get('hash', 'section');

// by default the UrlState static class tracks 'popstate' updates. 
// Setting to false removes that tracking.
UrlState.refresh(true);

 
// prints the values, 'brackets' option will add the [] to any
// key that contains an array value, as back-end needs or doesn't
UrlState.print(type: UrlSearchType, options: UrlPrintOptions): string

// updates the url, this is used in the UrlState.set if the fourth param is set
UrlState.toUrl(type: UrlSearchType, paramName: string): UrlParamRawValue
 
// sets new value, updates params in url if 4th param set
UrlState.set( 
    type: UrlSearchType, 
    paramName: string, 
    value: UrlParamRawValue,
    state?: StateChangeType
): void;
 
// sets a hash value, ex: 'https://your-website.com/some-page#your-hash-val'
UrlState.setHashVal(null, 'push'): void; 
// updates to: https://your-website.com/some-page and pushes to the history

UrlState.setHashVal('new-hash-value', 'replace'): void; 
// updates to: https://your-website.com/some-page#new-hash-value and replaces to the history
 

Plugins



Accessible Menu

Features

This plugin allows a user to use the keyboard arrows to navigate a desktop navigation, and are configurable depending on the design. It also allows the use of the escape key to go up a level in the navigation.

Settings

OptionTypeDefaultDescription
keyDirectionsarray['horizontal', 'vertical', 'vertical']The direction in which the menu appears. For example, 'horizontal' means the <li> elements are going across the page. The next in the array is 'vertical', which means they're stacked. Typically if a third level exists they're also vertical as well.
focusCssstring'focus'the focus class that allows the menu to appear as being active
focusInElemsstring'a, [tabindex]'Listing of elements that can be focused-in on.
focusLeaveElemsstring'a, [tabindex], select, button'Listing of elements to focus on to escape the last nav item via the arrow keys

Example

The following structure should be used with this plugin:

HTML

<nav id="main-menu">
    <ul>
        <li><a href="#level-1-link">Level 1 Link</a></li>
        <li><a href="#level-1-link">Level 1 Link</a>
            <ul>
                <li><a href="#level-2-link">Level 2 Link</a></li>
                <li><a href="#level-2-link">Level 2 Link</a></li>
            </ul>
        </li>		
        <li><a href="#healthy-choice">Level 1 Link</a></li>		
            <ul>
                <li><a href="#level-2-link">Level 2 Link</a></li>
                <li><a href="#level-2-link">Level 2 Link</a></li>
                <li><a href="#level-2-link">Level 2 Link</a></li>
            </ul>
        </li>	
    </ul>
</nav>

JavaScript

$('#main-menu').accessibleMenu({
	keyDirections: ['horizontal', 'vertical', 'vertical'],
	focusCss: 'focus'
});


Collapse

Features

This has a move-to-top after open feature, open with location hash, and callbacks after events and such.

Settings

OptionTypeDefaultDescription
cssPrefixstring'collapse'The primary CSS class and prefix for all other derived elements. The BEM CSS naming convention is used for all derived elements.
toggleDurationnumber500The speed at which the items will open, should pair with CSS transition settings.
toggleGroupbooleanfalseMore or less toggles the other opened element(s) closed, and make it behave like an accordion.
moveToTopOnOpenbooleanfalseAfter the element is opened, the item will move to the top of it. Good for mobile.
moveToTopOffsetnumber() => number0
moveToTopDurationnumber500duration to move to the top if the moveToTopOnOpen setting is being used.
urlFilterType'hash'|'search''hash'The filtering type to use (either location.hash or location.search) to track the status of an open modal.
historyType'replace'|'push''replace'The history state update. Either history.pushState or history.replaceState.
locationFilterstringnullKey name of the param to be captured in the location URL. Example: YOUR_URL#collapse=the-item-id, where the-item-id is the ID property and collapse is our locationFilter.
loadLocationbooleantrueLoads with a location hash in the browser address bar, must of course be the ID of the item.
afterOpenfunction($btnElems, $collapsibleItem) => {}callback function after an item is opened.
afterClosefunction($btnElems, $collapsibleItem) => {}callback function after an item is closed.
afterInitfunction(element) => {}callback function after collapse is initialized.

Example

The following is an example html structure for this plugin:

HTML

<section class="container">
    <div class="collapse collapse-group collapse-group-1" >
        <div class="collapse__item">
            <div class="collapse__header">
                <h2>Collapse Item 1</h2>
                <button class="collapse__btn" aria-controls="item-1" aria-label="toggle section"></button>
            </div>
            <div class="collapse__body" id="item-1">
                <div class="collapse__body-inner">
                    <p>Ut enim ad minim veniam, quis nostrud exercitation. Gallia est omnis divisa in partes tres, quarum. Contra legem facit qui pastrami id facit quod lex prohibet. Quis aute iure reprehenderit in voluptate velit esse. Cum ceteris in veneratione tui montes, nascetur mus.</p>
                    <a href="#item-3" class="collapse__btn" aria-controls="item-3"><strong>Open Item 3 from here!</strong></a>
                </div>
            </div>
        </div>
        <div class="collapse__item">
            <div class="collapse__header">
                <h2>Collapse Item 2</h2>
                <button class="collapse__btn" aria-controls="item-2" aria-label="toggle section"></button>
            </div>
            <div class="collapse__body" id="item-2">
                <div class="collapse__body-inner">
                    <p>Ut enim ad minim veniam, quis nostrud exercitation. Gallia est omnis divisa in partes tres, quarum. Contra legem facit qui pastrami id facit quod lex prohibet. Quis aute iure reprehenderit in voluptate velit esse. Cum ceteris in veneratione tui montes, nascetur mus.</p>
                    <p>Ut enim ad minim veniam, quis nostrud exercitation. Gallia est omnis divisa in partes tres, quarum. Contra legem facit qui pastrami id facit quod lex prohibet. Quis aute iure reprehenderit in voluptate velit esse. Cum ceteris in veneratione tui montes, nascetur mus.</p>

                    <p>Ut enim ad minim veniam, quis nostrud exercitation. Gallia est omnis divisa in partes tres, quarum. Contra legem facit qui pastrami id facit quod lex prohibet. Quis aute iure reprehenderit in voluptate velit esse. Cum ceteris in veneratione tui montes, nascetur mus.</p>
                </div>
            </div>
        </div>
        <div class="collapse__item">
            <div class="collapse__header">
                <h2>Collapse Item 3</h2>
                <button class="collapse__btn" aria-controls="item-3" aria-label="toggle section"></button>
            </div>
            <div class="collapse__body" id="item-3">
                <div class="collapse__body-inner">
                    <p>Ut enim ad minim veniam, quis nostrud exercitation. Gallia est omnis divisa in partes tres, quarum. Contra legem facit qui pastrami id facit quod lex prohibet. Quis aute iure reprehenderit in voluptate velit esse. Cum ceteris in veneratione tui montes, nascetur mus.</p>
                </div>
            </div>
        </div>
    </div>
</section>

JavaScript

$('.collapse-group').collapse();


Lazy Load

By default it will load background images and images lazily slightly before they appear in the viewport. But also run custom fuctions as well to hook into elements appearing (or disappearing) as well. This plugin uses window.IntersectionObserver. This plugin works to load images with the loading="lazy" attribute (yes it would work by itself!). It loads the image/iframe before the first pixel enters the viewport--see settings as we can pad so it can appear loaded once scrolled to. The loading="lazy" attribute only works once the first pixel enters the viewport, which may cause a blank space before the image loads.

OptionTypeDefaultDescription
imgSrcNamestring'src'Name of the data attribute to load an image source. For example <img src="cleardot.gif" data-src="your-lazy-image.jpg">.
bgSrcNamestring'bgSrc'Name of the data attribute to load a background image. Use camel casing when changing.
loadImgsbooleantrueLoad images and background images. Built-in function for this since its the core intended functionality.
inEvtFunctionnullCustom function that hooks into the element appearing on screen. the lazyElem and entry are the two parameters passed, so inEvt(lazyElem, entry) = > {console.log(lazyElem, entry)}.
outEvtFunctionnullCustom function that hooks into the element disappearing in the viewport. Same parameters are passed as the inEvt function.
forcebooleanfalsePass in a custom condition that will just bypass the lazy load.
observerIDstringnullID of window.IntersectionObserver which gets created with the 'new' operator, so one can get used for each instance.
unobservebooleantrueonce entered in on the viewport, it'll unobserve. Make false should you want to re-observe an element.
observerOptsobject{ rootMargin: '48px' }Object being passed is the 'options' argument for the IntersectionObserver, please refer to documentation regarding that here.

Example

The following is an example html structure for this plugin:

HTML

<img src="https://placehold.it/768x768/565656" alt="Placeholder" loading="lazy"/>

<img src="https://placehold.it/768x768/444" alt="Placeholder" loading="lazy"/>

<img src="https://placehold.it/768x768/222" alt="Placeholder" loading="lazy"/>

<img src="https://placehold.it/768x768" alt="Placeholder" loading="lazy"/>


<p>It's nearly inevitable your website will need these plugin's and functions for it to work. These are made to work with <a href="https://github.com/fabiospampinato/cash" target="_blank">Cash</a> (with jQuery still an option) as the only dependency.</p>
<h2>About</h2>
<p><a href="#page-bottom" class="smooth-scroll">Go To Page Bottom Smooth Scroll</a> Below are some common plugin's to help enhance your website. You'll notice some are missing (like a Carousel for example), that's because there are just some really, realy well made, IMO. Not touching that stuff, use it, its great. Others I always thought could be better, even though a few are frankly near duplicates 🤷🏻‍♂️. Anyways here we are, and you're stil reading this! If you download you probably work where I do, or somehow stumbled across.</p>

<h2>Some nice features are their is some shared syntax in the way they all operate.</h2>

<p><strong>For Example:</strong> all have options that can be plugged in as a data attribute, in JSON format (loosely written somehat)</p>
                

JavaScript


//load regular images few pixels before then enter
//the screen rather than the first pixel to enter
$('img[loading="lazy"]').lazyLoad({
    observerID: 'imgLazy',
    observerOpts: { rootMargin: '100px' }
});

//a bunch of paragraphs to style right!
$('p.highlight').lazyLoad({
    observerID: 'p',
    loadImgs: false, 
    unobserve:false,
    inEvt: (el) => {
        setTimeout(()=> {el.style.background = '#ccc';},1000);
    },
    outEvt: (el) => {
        setTimeout(()=> {el.style.background = null;},1000);
    }
});


Modal

Features

Settings

OptionTypeDefaultDescription
enableEventstring'click'The event to show the modal, change to whatever event on the element. Could be 'hover', or synthetic event triggred by another element.
appendTostringHTMLElementdocument.body
ariaLabelledbystringnullIf using an aria-labelledby to label the modal for ADA purposes.
ariaLabelstringnullIf using an aria-label to label the modal for ADA purposes.
cssPrefixstring'modal'The primary CSS class and prefix for all other derived elements. The BEM CSS naming convention is used for all derived elements.
closeBtnIconCssstring'ico i-close'CSS used on the close button.
closeOutDelaynumber250Time for closing the animation. Sync with CSS transition or animation.
focusInDelaynumbernull0
backDropClosebooleantrueToggle whether a user can click the backdrop to close the modal.
fromDOMbooleantrueIf the modal content is grabbed from the DOM. Set to false if grabbed via an AJAX call or otherwise generated.
modalCssstringnullAdditional modal css for styling or other scripting purposes
modalIDstringnullThe ID of the modal.
srcstring''CSS selector for DOM elements, or can be custom created element from data either from an AJAX call or computed otherwise. Optional if modal content is dynamic/generated.
urlFilterType'hash'|'search''hash'The filtering type to use (either location.hash or location.search) to track the status of an open modal.
historyType'replace'|'push''replace'The history state update. Either history.pushState or history.replaceState.
locationFilterstringnullKey name of the filter to be captured in the location URL. Example: YOUR_URL#modal=the-modal-id, where the-modal-id is the modalID property and modal is our locationFilter.
loadLocationbooleantrueLoads with a location from the browser address bar, must of course be the ID of the item.
onOpenOnceobject(modalObj) => {}Event that fires only the first time the modal is enabled
onOpenobject(modalObj) => {}Event that fires when the element is opened
afterCloseobject(modalObj) => {}Event that fires after the element is closed

Modal Object

This is an object with the following props/elements that is the first (and only) argument above in the callback functions (onOpenOnce,onOpen and afterClose). This should help allow for more flexibility with the prompt to attach any additional events or styling more easily. Below some examples with a little bit of custom code with this object.

{
    backdrop,
    content,// in the params this would be the src. If not specifying a source and using generated content use dialogContent instead
    contentAppended: false, //state
    dialog, //modal dialog
    dialogContent, // modal dialog content
    closeBtn,
    id: modalID,
    modal, //outermost element
    close: () => this.close(), //disable modal fn
    show: false //state
}

Example

The following structure should be used with this plugin:

HTML

<section class="modal-section container">
    <h2 id="section-modal">Modal</h2>

    <div>
        <h3>Modal with Hidden Content</h3>
        <p>Modal with grabbing content from the page in a hidden section.</p>
        <a href="#modal-content" class="button btn-modal"
            data-modal-options="{closeBtnLabel:'Close it up'}">Modal with content from DOM</a>

        <h3>Modal With Generated Content</h3>
        <p>Content that is generated from some source. Could be an AJAX call, or in this case just defined in the JS.</p>
        <button type="button" class="button" id="btn-gen-content">Generated Content</button>
        

        <h3>Modal Group / Carousel</h3>
        <p>Carousel of items. Note: the 'carousel' portion is done with additional scripting separate from the modal.</p>

        <div class="modal-section__group">
            <button type="button" 
                data-img-src="https://picsum.photos/600/400"
                alt="Picsum Pic 1" class="pic-group"
            >
                <img src="https://picsum.photos/600/400" alt="Picsum Pic 1" loading="lazy"/>
            </button>

            <button type="button" 
                data-img-src="https://picsum.photos/900/550"
                class="pic-group"
            >
            <img src="https://picsum.photos/900/550" alt="Picsum Pic 2" loading="lazy"/>
            </button>

            <button type="button" 
                data-img-src="https://picsum.photos/900/450"
                class="pic-group"
            >
                <img src="https://picsum.photos/900/450" alt="Picsum Pic 3" loading="lazy"/>
            </button>

            <button type="button" 
                data-img-src="https://picsum.photos/800/600"
                class="pic-group"
            >
                <img src="https://picsum.photos/800/600" alt="Picsum Pic 4" loading="lazy"/>
            </button>
        </div>
    </div>

     <div style="display: none;" hidden>
        <div id="modal-content">
            <h1>Pop-up</h1>
            <p>This is for a basic modal content</p>
            <p>Cum sociis natoque <a href="#"> some link </a>penatibus et magnis dis parturient. Etiam habebis
                sem dicantur magna mollis euismod. Curabitur blandit tempus ardua ridiculus sed magna. <button
                    type="button" disabled>Some Button</button> Unam incolunt Belgae, aliam Aquitani, tertiam.
                Nihil hic munitissimus habendi <button type="button">clickable btn</button> senatus locus, nihil
                horum?</p>
        </div>
    </div>
</section>

JavaScript

// Note: Examples all use the Base Elem Js DOM Library which is used internally in this package
import $be from 'base-elem-js';

$be('.btn-modal').modal({
    modalID: 'from-dom'
});

$be('#btn-gen-content').modal({
    locationFilter: 'modal',
    fromDOM: false,
    modalID: 'gen-content',
    onOpenOnce(modalObj) {
        
        modalObj.$dialogContent.on('click', modalObj.close,'button.dismiss');

        modalObj.$dialogContent.insert(
            `<h2>Some generated Content</h2>
            <p>Ullamco <a href="#">link</a> laboris nisi ut aliquid ex ea commodi consequat. Sed haec quis possit intrepidus aestimare tellus. Quam diu etiam furor <a href="#">iste tuus</a> nos eludet? Curabitur est gravida et libero vitae dictum.</p>
            <button type="button" class="button dismiss">Dimiss</button>`
        );
    }
});

// quick and dirty image carousel
const $picGroup = $be('.pic-group');

$picGroup.each((elem, index) => {
    
    let imgIndex: number = index;

    const 
        modalID = 'pic-group_' + index,
        imgDefaultSrc = elem.dataset.imgSrc,
        img = make('img', {loading:'lazy', src: imgDefaultSrc, alt: ''}),
        setImgSrc = (decrement: boolean) => {
            if (decrement)  imgIndex = imgIndex === 0 ? $picGroup.size - 1 : imgIndex - 1;
            else            imgIndex = imgIndex === $picGroup.size - 1 ? 0 : imgIndex + 1;
            
            return ($picGroup.elem[imgIndex] as HTMLElement).dataset.imgSrc || '';
        }
    ;

    $be(elem).modal({
        modalID,
        modalCss: 'modal--gallery', 
        locationFilter: 'gallery',
        fromDOM: false,
        onOpenOnce(modalObj) {
            modalObj.$dialogContent.insert(img).insert(`
                <footer class="pic-group-nav">
                    <button type="button" class="prev-btn">Previous</button>
                    <button type="button" class="next-btn">Next</button>
                </footer>
            `).on('click', (e, elem) => {
                const decrement = $be(elem).hasClass('prev-btn');
                img.src = setImgSrc(decrement);    
            },'button');
        },
        onOpen(modalObj) {
            $be(window).on('keyup.gallery', function(e:KeyboardEvent){
                const arrowLeft = e.key === 'ArrowLeft';

                if (e.key === 'Escape') modalObj.close();
                if (e.key === 'ArrowRight' || arrowLeft) {
                    img.src = setImgSrc(arrowLeft);
                }
            });
        },
        onClose() {
            $be(window).off('keyup.gallery');
        }
    });
});



Desktop Navigation

Features

This plugin adds a delay to the desktop navigation and for the nestled <ul>'s that fly out. Also, features an edge detection on the drop-down <ul> elements, and uses corresponding CSS to position, so it stays on the page.

Settings

OptionTypeDefaultDescription
stopWidthnumber768the width in which the navigaiton will stop for mobile.
delaynumber800The delay in time you can hover off a sub menu item.
edgeCssstring'ul-on-edge'The CSS class that moves the nav when if goes over the egde of the page.
outerElemstringdocument.bodyElement to attach the navHoveredCss option.
cssPrefixstring'menu'CSS class for <li> that have a <ul> nestled.
navLeavingDelaynumber800delay in milliseconds in which the navLeavingCss gets added to the outerElem
hoverCssstring'hover'The hover class to work in conjuction with the delay option to keep the item on the page when hovered off.

Example

The following is an example html structure for this plugin:

HTML

<nav id="main-nav">
	<ul>
		<li><a href="#">Some Link</a>
			<ul>
				<li><a href="#">Some Link</a></li>
				<li><a href="#">Some Link</a></li>
				<li><a href="#">Some Link</a></li>
			</ul>
		</li>
	</ul>
</nav>

JavaScript

$('#main-nav').navDesktop();


Mobile Navigation

About

Plugin is strictly for mobile so other plugins can be used for the desktop nav if needed. The clicking action that allows for opening/closing nav item is handled via the visibility of the 'open/close' button so the click so no clashing between desktop and mobile happen. Also so CSS can control it tighter as sometimes device width may dictate whether or not you'll see the desktop or mobile view.

Settings

OptionTypeDefaultDescription
enableBtnstring'#mobile-nav-btn'The selector to the mobile nav button to turn show the navigation.
ariaLabelstring'Toggle site navigation'The arial label for the enable button.
tgBtnTextstring'toggle menu'Copy to prefix the button that toggles the sub-menu of a list item.
insertBtnAfterstring'a'the element selector name for inserting the toggle button after.
slideDurationnumber400Duration for showing a sub menu item, CSS transistion should correspond.
outerElementstring or HTMLElementdocument.bodyElement to attach menuOpenCss class to.
cssPrefixstring'menu'The primary CSS class and prefix for all other derived elements. The BEM CSS naming convention is used for all derived elements.
menuBtnSkip() => : boolean | (li) => booleanFunction that takes the li as the parameter, which tests whether or not to skip adding a button adjacent to it's <a/> element. Ex. (in the mark-up) <li class="skip-li"> and the config the following: menuBtnSkip(li) { return li.classList.contains('skip-li')} in which it'd skip adding a button to that level in the nav.
menuBtnCssstring'i i-arrow-b'CSS class for the indicating element as to the sub menu open/closed status.
animateHeightbooleantrueAnimates the height of the list. Good if you want the <ul> to fade-in rather than scroll open (with corresponding CSS written of course).
afterNavItemOpenfunction($li) => {}Function to run after an nav item is opened.
afterNavItemClosefunction($li) => {}Function to run after a nav item is closed.
afterOpenfunction($element, outerElement, enableBtn) => {}Function to run after the nav is open.
afterClosefunction($element, outerElement, enableBtn) => {}Function to run after the nav is closed.
doTrapFocusbooleantrueTraps the focus to just the visible anchors and buttons within the navigation.
trapFocusElemstringnullselector string (or can be dom element) if we need to extend the trap focus slightly outside the main nav element.
stopPropagationbooleantrueStops the click from propagating up in the DOM from the nav element.
bkptEnablenumbernullOptionally specify when to enable the mobile navigation with screen width (in pixels). This will override whether or not the enableBtn is visible, which is the conditional that enables this menu to function.

Example

The following is an example html structure for this plugin:

HTML

<nav id="main-nav">
	<button class="mobile-nav-btn" id="mobile-nav-btn">
		<span></span>
	</button>
	<ul>
		<li><a href="#">Some Link</a>
			<ul>
				<li><a href="#">Some Link</a></li>
				<li><a href="#">Some Link</a></li>
				<li><a href="#">Some Link</a></li>
			</ul>
		</li>
	</ul>
</nav>

JavaScript

$('#main-nav').navMobile()


Parallax

Features

This plugin is for parallaxing page elements (and yes background images). Use the bgFill option and it'll magically expand to the height of its container if using a background image. It uses the translate3d property as its more efficient than using a top or left as well as requestAnimationFrame. Can be used to move elements either with a Y or X axis, also a Z axis for zooming (use perspective CSS prop on parent to work).

Settings

OptionTypeDefaultDescription
speednumber7Speed of the scroll. A negative amount will move it in the opposite direction.
zSpeednumber5Speed of the z-axis. A negative amount will move it in the opposite direction.
axisstring'y'Axis of movement, it can be 'y','x'.
zAxisbooleanfalseIf true used will utilize the z-axis.
cssPrefixnumber'parallax'CSS class name for styling purposes. Other derived CSS classes use the BEM naming convention.
scrollAxisnumber'y'The axis of which the parallax is based on.
relativeElemboolean | HTMLElement | stringfalseIf you need to bsae the parallaxing of one element relative to the offset of it's parent.
bgFillnumberfalseIf the parallaxing element is a background image, this adds extra height to ensure it fills the it's containing element.
rootMarginnumber| [number,number]0Delay the parallax effect relative to the viewport. Pass in an array [start,end] for tighter control.
scrollMaxPxStopnumber5000The max an item can scroll. Make this less should you want it to stop prior to exiting the screen. Good for when you have content that it shouldn't overlap.
zScrollMaxPxStopnumber2000Max an item can scroll regarding the z-axis.
minWidthnumbernullThe minimum width for the parallax effect to run.
maxWidthnumbernullThe maximum width for the parallax effect to run.

Example

The following structure should be used with this plugin:

HTML

<section class="container">
   
    <h2 id="section-parallax">Parallax</h2>
    <div class="parallax-area">
        <img class="parallax-area__bg parallax do-parallax"
            data-parallax-options="{speed: 20, bgFill: true, zAxis: true, rootMargin: 100}"
             src="https://picsum.photos/1920/760"
            srcset="https://picsum.photos/960/760 959w, https://picsum.photos/1920/760 960w"
            size="(max-width: 959px) 959px, 960px" 
            loading="lazy"
        />
    </div>
    <div>
        <h3>Randomized Movement</h3>
    </div>
    <div class="container parallax-tiles">
        <div class="parallax do-parallax"
            data-parallax-options="{speed: 10, bgFill: false, scrollMaxPxStop: 120}">
            <img loading="lazy" src="https://placehold.co/768" alt="Placeholder" />
        </div>

        <div class="parallax do-parallax"
            data-parallax-options="{speed:30, bgFill: false, scrollMaxPxStop: 220, axis: 'x'}">
            <img loading="lazy" src="https://placehold.co/768" alt="Placeholder" />
        </div>

        <div class="parallax do-parallax"
            data-parallax-options="{speed:-10, bgFill: false, scrollMaxPxStop: 120}">
            <img loading="lazy" src="https://placehold.co/768" alt="Placeholder" />
        </div>

        <div class="parallax do-parallax"
            data-parallax-options="{speed: -20, bgFill: false, scrollMaxPxStop: 180}">
            <img loading="lazy" src="https://placehold.co/768" alt="Placeholder" />
        </div>

        <div class="parallax do-parallax" data-parallax-options="{speed:-20, bgFill: false, axis: 'x'}">
            <img loading="lazy" src="https://placehold.co/768" alt="Placeholder" />
        </div>

        <div class="parallax do-parallax" data-parallax-options="{speed:-10, bgFill: false, axis: 'x', rootMargin: [200,0]}">
            <img loading="lazy" src="https://placehold.co/768" alt="Placeholder" />
        </div> 
    </div>
    <div>
        <h3>Scroll Horizontally</h3>
        <button class="btn" id="jsBtnSCrollHorizontal">Add space for horizontal scrolling</button>
    </div>
    <div class="parallax-area">
        <img class="parallax-area__bg parallax -do-parallax do-parallax--hz" 
            data-parallax-options="{speed: -10, axis: 'x', bgFill: true, scrollAxis: 'x'}"
            src="https://picsum.photos/1920/760"
            srcset="https://picsum.photos/960/760 959w, https://picsum.photos/1920/760 960w"
            size="(max-width: 959px) 959px, 960px" 
            loading="lazy"
        />
    </div>
</section>
$('.parallax-bg').parallax({
	speed:10,
	axis: 'y'
});


Scroll Spy

Features

Settings

OptionTypeDefaultDescription
cssPrefixstring'scroll-spy'CSS class name for styling purposes
observerOptionsIntersectionObserverInit{rootMargin: "0px", threshold: 1}Intersection observer options. By default this is set-up to work with an <h2 id="the-id"> with a threshold of 1 is most appropriate. This should be adjusted if your spying an entire section instead.
scrollBehavior'auto' | 'instant' | 'smooth'the type of scroll to move to a section with the scroll spy.
spyNavElems'a' | 'button'aElements to look at and highlight in the navigation that is being spied.
setActiveCssToLibooleantrueIf the spied element resides in a <li> attach the active class to that instead of the element
spyBodySelector'.scroll-spy-body'A selector to identify the section of the hightlighted elements that pair with the 'spyNavElems'
spyElemsstring'h2'String to identify which elements to see that have entered in thew viewport. The observer options (seen in observerOptions) are set-up to look at headings. As mentioned above, to look at sections please adjust the threshold from 1 to something that is more appropriate.
callbackScrollSpyCallBackundefinedCallback to tap into the entries being spied on.
type ScrollSpyCallBack = (topMostEntries: HTMLElement[], navEntries: HTMLElement[]) => void;

Example

The following is an example html structure for this plugin:

HTML

<!--Nav to Spy-->
<nav id="main-nav" class="main-nav">			 
    <ul>
        <li><a href="#section-parallax">Parallax</a></li>
        <li><a href="#section-tabs">Tabs</a></li>
        <li><a href="#section-collapse">Collapse</a></li>
        <li><a href="#section-toastr">Toastr</a></li>
        <li><a href="#section-modal">Modal</a></li>
        <li><a href="#section-selectEnhance">Select Box Enhance</a></li>
        <li><a href="#section-nav">Accessible Menu / Mobile and Desktop Nav</a></li>
        <li><a href="#section-lazyLoad">Lazy Load</a></li>
    </ul>
</nav>

<!--Body to spy that pairs with the nav-->

<div class="scroll-spy-body">

    <h2 id="section-parallax">Parallax</h2>
    <p>Vivamus sagittis lacus vel augue laoreet rutrum faucibus. Quae vero auctorem tractata ab fiducia dicuntur.</p>

    <h2 id="section-tabs">Tabs</h2>
    <p>Vivamus sagittis lacus vel augue laoreet rutrum faucibus. Quae vero auctorem tractata ab fiducia dicuntur.</p>
    <!-- and more ...-->
</div>

JavaScript

 $('#main-nav').scrollSpy({
        spyBody: '.scroll-spy-body',
        locationFilter: 'spy',
        observerOptions: {
            rootMargin: "80px 0px 0px",
            threshold: 1
        }
})



Select Enhance

Features

Plugin that allows for styled dropdowns for the <select> element. This dropdown is ADA accessible, featuring typing to select, proper roles and aria attributes. Can refresh the options list by calling static methods such as SelectEnhance.refreshOptions('select') or destroy it similiarly SelectEnhance.remove('select') (also with $('select').selectEnhance('remove')).

Settings

OptionTypeDefaultDescription
cssPrefixstring'select-enhance'CSS class name for styling purposes
cssListModiferstringnullValue that will serve as a modifier class to the list. Neccessary if the list dropdown is divergent from the rest of the site.
mobileNativebooleanfalseOff by default this doesn't render the stylized dropdowns for mobile devices.
emptyValAsPlaceholderbooleantrueif the value is empty, then render placeholder copy instead of the text value inside the option its pulling data from.
focusInFunction($element) => {}event when focusing in on the select box
focusOutFunction($element) => {}event when focusing out on the select box
beforeChangeFunction($element) => {}event to fire before the change event
afterChangeFunction($element) => {}event to fire after the change event
blurDurationnumber250the amount of time in milliseconds the blurring CSS effect lasts
typeAheadDurationnumber500the timeout in millisconds to when the type/search feature resets
observeSelectboxbooleantrueuses a MutationObserver to view changes on the <select> element or changes to the <options>
listAppendToSelectbooleanfalseUsed to append the list to the select wrap. This option can be used if the select box is inside something that has sticky or absolute position, where if the user scrolls, the list box looses register with the select. By default it appends to the document.body to ensure if the <select> is in an area with overflow hidden, it won't get clipped by the containing element with that property set.

Example

The following is an example of the <select> elements for this plugin:

HTML

<label for="select-1">Select 1</label>
    <select id="select-1">
        <optgroup label="one">
            <option value="1">First Option</option>
            <option value="2">Second Option</option>
            <option value="3">Third Option</option>
        </optgroup>
        <optgroup label="two">
            <option value="4">More Options</option>
            <option value="5">Choices For Days</option>
            <option value="6">Sixth One</option>
        </optgroup>
    </select>
    <label for="another-select">Select 2</label>
    <select id="another-select">
        <option value="one">One Option</option>
        <option value="two">Two Option</option>
        <option value="three">Three!</option>
    </select>

JavaScript

$('select').selectEnhance();


Tabs Plugin About

At some point we all need to be able to tab content. This one does it for you!

Features

  • Tabs within tabs, so tabs can be added inside other tabs if needed (which it will at some point),
  • hash to load not only a tab, but tabs in tabs as well!
    • i.e.: add this to the location #tab-id open multipe with an '=' sign so cool-tab=cooler-tab, or run with a filter as well so it can work in conjuction with other plugin's that use a hash

Settings

OptionTypeDefaultDescription
defaultContentnumber | 'none'0The order of the list item selected. Goes of course their appearance in the DOM. Passing in 'none' does as it sounds and hides them all by default.
tabsEventstring'click'Event to change the tabs content
cssPrefixstring'tab'The CSS that prefixes every relevant structural element contained within. Uses BEM convention.
locationFilterstringnullKey name of the param to be captured in the location URL. Example: YOUR_URL#tab=the-item-id.
loadLocationbooleantrueAdd in location hash parameters to load default tabs. #files=files-inner loading multiple is possible if many diffrent tabs. Also load tabs within tabs and such as well.
historyType'push'|'replace''push'If using using useLocationHash or a history of events, 'push' pushes a new state, and 'replace' replaces the current.
tabbingbooleantrueEnables tabbing with keyboard arrows. A tab list should only be focusable one at a time with the 'tab' key.
tabDirectionstring'horizontal'Typically tabs are 'horizontal' but may also go 'vertical'. They take either or as an option, otherwise it'll throw a console.warn to correct.
addIDtoPanelbooleantrueAdds an ID attribute to the panel for ADA compliance, but isn't necessary for its functionality.
ariaLabelbooleantrueAdds an 'aria-label' attribute to the panel for ADA compliance. Set to false if an equivalent exists in the mark-up.
tabChange(tabId: string, prevTabId: string, tabsList: Cash, tabsBody: Cash): void() => {}Function to run before the tab change, passed variables are the 'previous tab ID', 'tabs list', 'tabs body' elements.
onInit(tabsList: Cash, tabsBody: Cash): void() => {}Function to run after the the plugin intializes, passed variables are the 'tabs list', 'tabs body' elements.

Example

The following is an example html structure for this plugin:

HTML

<section class="container">
    <h2 id="section-tabs">Tabs</h2>
    <div class="tabs__container tabs-outer">
        <div class="inline-ul tabs__nav" role="menubar">
            <ul>
                <li><button data-href="#description"><span>Description</span></button></li>
                <li><button data-href="#files"><span>Files</span></button></li>
                <li><button data-href="#requirements"><span>Requirements</span></button></li>
                <li><button data-href="#instructions"><span>Instructions</span></button></li>
                <li><button data-href="#files2"><span>Additional Info</span></button></li>
                <li><button data-href="#related"><span>Related</span></button></li>
            </ul>
        </div>
        <div class="tabs__body">
            <div data-tab-id="description" class="tabs__panel">
                <div class="tabs__container tabs-inner inner-one">
                    <div class="inline-ul tabs__nav" role="menubar">
                        <ul>
                            <li><button data-href="#description-inner"><span>Description Inner</span></button></li>
                            <li><button data-href="#files-inner"><span>Files Inner</span></button></li>
                            <li><button data-href="#requirements-inner"><span>Requirements Inner</span></button></li>

                        </ul>
                    </div>
                    <div class="tabs__body">
                        <div data-tab-id="description-inner" class="tabs__panel">
                            <p><strong>Description Inner</strong> pellentesque habitant morbi tristique senectus et netus. Fabio vel iudice vincam,sunt in culpa qui officia. Curabitur blandit tempus ardua ridiculus sed magna. Petierunt uti sibi concilium totius Galliae in diem certam indicere.</p>
                        </div>
                        <div data-tab-id="files-inner" class="tabs__panel">
                            
                            <p>Non equidem invideo, miror magis posuere velit aliquet. Qui ipsorum lingua Celtae, nostra galli appellantur. Phasellus laoreet lorem vel dolor tempus vehicula. Plura mihi bona sunt, inclinet, amari petere vellent.</p>
                        </div>
                        <div data-tab-id="requirements-inner" class="tabs__panel">
                            
                            <ul>
                                <li>Something in a list item</li>
                                <li>Something in a list item</li>
                                <li>Something in a list item</li>
                            </ul>
                        </div>

                    </div>
                </div>
            </div>
            <div data-tab-id="files" class="tabs__panel">
                <p><strong>Description</strong> pellentesque habitant morbi tristique senectus et netus. Fabio vel iudice vincam, sunt in culpa qui officia. Curabitur blandit tempus ardua ridiculus sed magna. Petierunt uti sibi concilium totius Galliae in diem certam indicere.</p>
               
            </div>
            <div data-tab-id="requirements" class="tabs__panel">
                <p><strong>Description</strong> quis aute iure reprehenderit in voluptate velit esse. Quam diu etiam furor iste tuus nos eludet? Ambitioni dedisse scripsisse iudicaretur porkchops.</p>
                
            </div>
            <div data-tab-id="instructions" class="tabs__panel">
                <p><strong>Description</strong> pellentesque habitant morbi tristique senectus et netus. Fabio vel iudice vincam, sunt in culpa qui officia. Curabitur blandit tempus ardua ridiculus sed magna. Petierunt uti sibi concilium totius Galliae in diem certam indicere.</p>
            
            </div>
            <div data-tab-id="files2" class="tabs__panel">
                <p><strong>Description</strong> pellentesque habitant morbi tristique senectus et netus. Fabio vel iudice vincam, sunt in culpa qui officia. Curabitur blandit tempus ardua ridiculus sed magna. Petierunt uti sibi concilium totius Galliae in diem certam indicere.</p>
            </div>
            <div data-tab-id="related" class="tabs__panel">
                 
                <p>Nec dubitamus multa iter quae et nos invenerat. Integer legentibus erat a ante historiarum dapibus.
                    Curabitur est gravida et libero vitae dictum.</p>
            </div>
        </div>
    </div>
</section>

JavaScript

$(".tabs__container").tabs({
	onInit: (tabId, prevTabId, tabsList, tabsBody) =>{
		// do something ...
	},
	tabChange: (tabsList, tabsBody) =>{
		// do something to start
	}
});



Toastr

Little toastr messages for everyone, side of marmalade optional.

Features

Can set groups of toastr's with the cssGroupKey if there ever needs to be multiple toastr's at once in various positions.

Settings

OptionTypeDefaultDescription
durationnumber3000The duration in milliseconds the toastr message will appear for.
appendToHTMLElementdocument.bodyHTML element to append the toastr message to.
ariaLive: POLITENESS_SETTING'polite'Aria Live property messaging settings
animationDurationnumber500Amount of time the transitional css class will append to the class list of the element.
contentstring OR HTMLElement''Message text/HTML of the toastr.
outerCssstring'toastr'CSS class to the div container of the message.
enabledCssstring'toastr--enabled'CSS to show the toastr message
dismissCssstring'toastr--dismiss'CSS to dismiss the toastr message
btnDismissCssstring'toastr__btn-dismiss'CSS for the dismiss button element.
closeIconCssstring'ico i-close'Icon CSS to draw the 'X' or what have you to dismiss the toastr.
cssGroupKeystring'std'Key which is used to group together like Toastr messages. Additionally as a CSS concatenated prop, keep that in mind.
oneOnlybooleantruelaunches only one at a time.

Example

Add these clicks to buttons or other elements should they be applicable:

HTML

<h3>Toastr</h3>
<ul>
	<li><button id="toastr-1">Launch a Toastr</button></li>
	<li><button id="toastr-2">Launch a Toastr Two</button></li>
	<li><button id="toastr-3">Launch a Toastr Three</button></li>
	<li><button id="toastr-4">Launch a Toastr Four</button></li>
</ul> 

JavaScript

	// Example 1: standard way
    $('#toastr-1').toastr({
        content: 'Toast is good for breakfast',
        duration: 7000
    });
	
	// and you can make an update here which will use the same instance
	// note: any props that build the html elements cannot be updated
	// unless of course you destroy the instance and rebuild it.
	$('#toastr-1').toastr({ content: 'A new toast message'});


    // Example 2: extend perhaps in Cash then call on click
    const toastr1 = new $.toastr($('#toastr-2')[0] as HTMLElement, {
        content: 'Toast is good for breakfast',
        duration: 5000
    });
    const toastRandomMsgs = [
        'I boast about my toast.',
        'The hostess with the toastess',
        'toast is best, when its not burnt',
        'The fire is quite toasty',
        'Lets toast, to toast!'
    ]
    const randomToastMsg = () => {
        return toastRandomMsgs[Math.floor(Math.random() * toastRandomMsgs.length)]
    }

    $('#toastr-2').on('click',function(){
        setTimeout(() => {
            toastr1.setContent(randomToastMsg(),true)
        },2500)
    });

    // Example 3,4: somewhere else on the page
    $('#toastr-3').toastr({
        content: randomToastMsg(),
        duration: 5000,
        cssGroupKey: 'bottom'
    });

    $('#toastr-4').toastr({
        content: randomToastMsg(),
        duration: 5000,
        cssGroupKey: 'bottom'
    });

Release Notes

Version 6.0.0

  • Major changes to the SelectEnhance plugin: dropdown now appends to the body, resolving overflow issues. Not compatible with v5 CSS.
  • Fixed a bug in Parallax when used with jQuery.

Version 7.0.0

  • Migrated away from Cash Dom to a custom DOM library.
  • Updated smooth scrolling and naming conventions.
  • Refactored and introduced breaking changes to several plugins, warranting a major version bump.

Version 7.1.3

  • Addressed ADA issues on SelectEnhance plugin adding back more 'aria-' attributes

Keywords

accessible

FAQs

Package last updated on 31 Mar 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts