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

@superkoders/modal

v2.1.1

Published

Fancybox like modal

Downloads

734

Readme

Modal window/popup which main purpose is to open as image galery. But it can handle also other type of content like Youtube, Vimeo or HTML5 videos, iframes, custom HTML content or HTML content from some existing element on the page. It can recognize type of media from the source url. If it is not possible to recognize media type, default type is iframe. You can force media type by medium parameter (see examples below).

Installing

Using npm

$ npm install @superkoders/modal

Using yarn

$ yarn add @superkoders/modal

How to use

There are two methods exported: initModal and createModal. First one adds click listeners to each element in given context which matches modalSelector option (by default '[data-modal]'). It returns array of modal instances created. Second one is for creating custom modal instance.

initModal: (options: SKModalOptions) => SKModal[]

import { initModal } from '@superkoders/modal';

// use default options
initModal();

// or set some custom options
initModal({
	customWrapperClass: 'my-custom-modal',
	closeOnBgClick: true,
});

How to create modal triggers in your HTML code

The easiest way is to do it with an a tag using its href attribute as an url for modal.

<a href="https://www.youtube.com/watch?v=RhMYBfF7-hE" data-modal>Open Youtube video in the modal</a>

If you want to use some other element like button, you need to specify url in the data-modal attribute.

<button data-modal='{"url": "https://www.youtube.com/watch?v=RhMYBfF7-hE"}'>Open Youtube video in the modal</button>

createModal: (items: SKModalItem | SKModalItem[], options?: Partial<SKModalOptions>) => SKModal

In this case, there are no triggers which open modal. Once you create an instance, you need to open it by yourself. Also you need to pass modal items, where only mandatory property is url. In our example below the modal will have two items, first is some image, second is some video.

import { createModal } from '@superkoders/modal';

const items = [
	{
		url: 'url/to/some/image.jpg'
	},
	{
		url: 'url/to/some/video.mp4'
	}
]

// create instance
const customModal = createModal(items, {
	customWrapperClass: 'my-custom-modal',
	closeOnBgClick: true,
});

// open modal
customModal.methods.open();

// go to next slide
customModal.methods.next();

// close modal
customModal.methods.close();

Documentation

Modal options SKModalOptions

These options you can adjust during initialization.

context: Element | Document

Context element, in which to search for modal items (triggers)
Default value: document

parentElement: Element

Element, which is used as a parent for modal element in DOM
Default value: document.body

modalSelector: string

Element selector, which is used for modal triggers
Default value: '[data-modal]'

closeSelector: string

Element selector, which is used to close the modal
Default value: '.js-modal-close'

customWrapperClass: string

Custom CSS class, which is added to the modal element
Default value: undefined

infinite: boolean

It determines if modal items are shown in a loop
Default value: false

closeOnBgClick: boolean

It determines if modal will close after background click
Default value: undefined

plugins: SKModalPlugin[]

Plugins array to initialize
Default value: undefined

hideNav: boolean

It determines if the navigation (arrows, bullets) is hidden or not
Default value: undefined

customData: any

Any data which you can use for example in plugins
Default value: undefined

closeIcon: string

String which represents an icon for close button, it can be also HTML code
Default value: '&#x000D7;'

prevIcon: string

String which represents an icon for previous button, it can be also HTML code
Default value: '&#x02190;'

nextIcon: string

String which represents an icon for next button, it can be also HTML code
Default value: '&#x02192;'

loadIcon: string

String which represents an icon for loader, it can be also HTML code
Default value: '<span class="b-modal__loader-icon"><span>&#x021BA;</span></span>'

removeOnClose: boolean

It determines if modal element will be removed from DOM after close
Default value: false

enableFocusTrap: boolean

Enables or disables focus trap. Default value: true

focusTrapOptions: FocusTrapOptions

Focus trap custom options. See Focus trap package page for more info Default value:

{
	allowOutsideClick: true,
}

useSwipe: boolean

Enables or disables swipe slide change on touch devices. Default value: true

ariaLabel: string

Modal title for assistive technologies. Default value: undefined

buildStructure: (modal: Element, fragments: SKModalFragments) => void

Method which builds the modal HTML structure, not really necessary to change if you use grid for CSS
Default value:

(modal, {
	ariaLabel,
	header,
	titleElem,
	descElem,
	content,
	prevElem,
	nextElem,
	navElem,
	loader,
	bg,
}) => {
	const wrapper = document.createElement('div');
	wrapper.classList.add('b-modal__wrapper');

	if (ariaLabel) {
		modal.setAttribute('aria-labelledby', ariaLabel.id);
		modal.appendChild(ariaLabel);
	}

	wrapper.appendChild(header);
	wrapper.appendChild(titleElem);
	wrapper.appendChild(descElem);
	wrapper.appendChild(content);
	wrapper.appendChild(prevElem);
	wrapper.appendChild(nextElem);
	wrapper.appendChild(navElem);
	modal.appendChild(wrapper);
	modal.appendChild(loader);
	modal.appendChild(bg);
}

headerTpl: (options?: SKModalOptions) => string

Method for header template
Default value:

(options) => `
	<button type="button" class="b-modal__close ${ModalClasses.CLOSE}">
		<span class="b-modal__close-text u-vhide">Close</span>
		${options.closeIcon}
	</button>
`

titleTpl: (text: string) => string

Method for title template
Default value:

(text: string) => `<h3>${text}</h3>`

descTpl: (text: string) => string

Method for description template
Default value:

(text: string) => `<p>${text}<p>`

prevTpl: (options?: SKModalOptions) => string

Method for previous button template
Default value:

(options) => `<button type="button" class="b-modal__prev-btn ${ModalClasses.PREV_TRIGGER}">${options.prevIcon}</button>`

nextTpl: (options?: SKModalOptions) => string

Method for next button template
Default value:

(options) => `<button type="button" class="b-modal__next-btn ${ModalClasses.NEXT_TRIGGER}">${options.nextIcon}</button>`

navTpl: (items: SKModalItem[]) => string

Method for navigation (bullets) template
Default value:

(items) =>
	items
		.map((_item, index) => `<span class="b-modal__nav-item ${ModalClasses.NAV_TRIGGER}" data-modal-index="${index}"></span>`)
		.join('')

loaderTpl: (options?: SKModalOptions) => string

Method for loader template
Default value:

(options) => `<span class="b-modal__loader-icon"><span>${options.loadIcon}</span></span>`

imageLoader: (src: string) => Promise<Node>

Method which is used for loading images
Default value:

(src) => {
	return new Promise((resolve, reject) => {
		let img = new Image();
		img.addEventListener('load', () => resolve(img));
		img.addEventListener('error', () => {
			reject(new Error(`Failed to load image with src: ${src}`));
		});
		img.draggable = false;
		img.src = src;
	});
}

fetchLoader: (url: string, element?: Element) => Promise<string>

Method which is used for fetching content from a server
Default value:

async (url) => await fetch(url).then((response) => response.text())

onModalOpen: (event?: Event, data?: { id: number }) => void

Handler, which runs after modal is opened
Default value: undefined

onModalClose: (event?: Event, data?: { id: number }) => void

Handler, which runs after modal is closed
Default value: undefined

onModalContentLoaded: (event?: Event, data?: { modal: SKModal }) => void

Handler, which runs after modal content is loaded
Default value: undefined

onModalSlideChanged: (event?: Event, data?: { page: number }) => void

Handler, which runs after modal slide has changed
Default value: undefined

Modal items (SKModalItem)

All these parameters is possible to add to data-modal attribute. In case of createModal, these are properties of the modal item object.

url: string | string[]

Media url. In case of images, it can be an array. Then more images are shown on one slide.

medium: ModalMedium

Media type. Posible values in ModalMedium enum exported from @superkoders/modal

title: string

Text, which will appear in modal title

desc: string

Text, which will appear in modal description

gallery: string

Gallery key, which is used for grouping items into one modal. If it is undefined, each modal uses its own popup.

modalClass: string

CSS class which will be aplied for modal wrapper element, when modal is opened.

[key: string]: any

It is possible to add more custom parameters, which can be used in plugins for example.

Plugins (SKModalPlugin)

Plugins enable another modal customization. It has these three parameters:

init: (modal: SKModal) => void

Init method

destroy: (modal: SKModal) => void

Destroy method, it runs after modal redraw (if reInitOnRedraw is set to true) or after modal destroy

reInitOnRedraw: boolean

It determines, if plugin should be reinitialized after modal redraw.

Plugin example

my-plugin.js

export const myPlugin = {
	init: (modal) => {
		// do some stuff like add event listeners or add some elements to DOM
	},
	destroy: (modal) => {
		// use when you need to remove some listeners or remove some elements from DOM
	},
	reInitOnRedraw: true,
}

modal.js

import { initModal } from '@superkoders/modal';
import { myPlugin } from './my-plugin.js';

initModal({
	plugins: [myPlugin]
});

Version 2.0 major changes

  1. The wrapper element is now a dialog element. It has better accessibility. You can check browser support here. If you need to support browser wich don't support dialog element, you can use older version (1.7.0).
  2. scroll-lock npm package has been removed. We prefer to use CSS pure solution. It can be done by adding scrollbar-gutter: stable on html element and overflow: clip on body element. For this purpose, class is-modal-open is added to body when dialog is opened. If you prefer to use scroll-lock, you can use older version (1.7.0)
  3. The dialog element comes with its own focus trap functionality. This however did not meet our requirements, so we are still using focus-trap npm package for this. If you prefer to use native dialog focus trap functionality, you can disable focus trap with enableFocusTrap option (set it to false).

Troubleshooting

@superkoders/modal uses some functionality from @superkoders/sk-tools. If you are already using @superkoders/sk-tools on your project, check if the version is at least 1.4.0. If not, you need to update the package.