{"id":21418144,"url":"https://github.com/stamat/modally","last_synced_at":"2025-09-01T00:39:54.749Z","repository":{"id":57300297,"uuid":"202222866","full_name":"stamat/modally","owner":"stamat","description":"Simple ES6 nested modals","archived":false,"fork":false,"pushed_at":"2024-01-28T12:04:07.000Z","size":978,"stargazers_count":9,"open_issues_count":4,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-04-29T09:02:10.849Z","etag":null,"topics":["dialog","es6","esm","modal","modal-dialogs","modal-window","nested","popup"],"latest_commit_sha":null,"homepage":"https://stamat.github.io/modally/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stamat.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2019-08-13T20:58:21.000Z","updated_at":"2024-04-29T09:02:10.849Z","dependencies_parsed_at":"2024-01-28T13:17:07.150Z","dependency_job_id":"c0fb47df-42f7-45b2-9d19-c5fafe2aa802","html_url":"https://github.com/stamat/modally","commit_stats":null,"previous_names":["stamat/modally","stamat/jquery.modally"],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stamat%2Fmodally","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stamat%2Fmodally/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stamat%2Fmodally/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stamat%2Fmodally/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stamat","download_url":"https://codeload.github.com/stamat/modally/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225951419,"owners_count":17550384,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dialog","es6","esm","modal","modal-dialogs","modal-window","nested","popup"],"created_at":"2024-11-22T19:19:11.783Z","updated_at":"2024-11-22T19:19:12.309Z","avatar_url":"https://github.com/stamat.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🪟 Modally [![npm version](https://img.shields.io/npm/v/modally)](https://www.npmjs.com/package/modally)\n\n\u003e Your trusty nested modal ally\n\nIf there are many different variations of the same functionality, the rule says it's easy to make. And the same goes for web modal dialogues - they are super easy to make.\n\nI created this web modal dialog library as a repo cause I wrote the same code for every project that required modals, over and over again throughout the years, just because it's trivial and I needed \"5 minutes\" to make it. It's not 5 minutes of course, it never is. \n\n**Life is short - make reusable code!**\n\n[DEMO HERE ⤻](http://stamat.github.io/modally/)\n\n![Imgur](https://imgur.com/Zzg3FDx.png)\n\n## Features\n* **Simplest one yet** - almost everything is automatic (or at least it should be 😅)\n* **Nested** - automatic detection of the order or parent, no need for additional coding\n* **ESM and IIFE** - use it as a module or as a script\n* **HTML auto-wrapped**\n* **State body classes**\n* **Vertically centered** - doesn't need to be, but it can be\n* **Scroll blocking** \n* **Video embeddable** - automatic Vimeo, Youtube and HTML Video embeds with autoplay\n* **Image lightbox** - automatic image lightbox\n* **ESC closable**\n* **Hash change detection** - automatic modal open on hash change\n* **Infinitely customizable** - go f**king wild 🎉\n* **Framework agnostic** - no dependencies, fully native! You can use it with jQuery if you want to, `$(selector).modally(options)` a plugin is available if jQuery is present if you use this library as an IIFE script.\n\n## Installation\n\n### NPM\n\n```bash\nnpm i modally\n```\n\n### Yarn\n\n```bash\nyarn add modally\n```\n\nUse it as a module\n```javascript\nimport Modally from 'modally';\n```\n\nOr as an IIFE script, Modally will be available as a global class, or as a jQuery plugin if jQuery is present `$(selector).modally(options)`\n\n\n### CDN\nAs iife files\n```html\n\u003cscript src=\"https://unpkg.com/modally/dist/modally.min.js\"\u003e\u003c/script\u003e\n\u003clink href=\"https://unpkg.com/modally/dist/modally.min.css\" rel=\"stylesheet\"\u003e\n```\n\nOr as a remote module\n```javascript\nimport Modally from 'https://unpkg.com/modally';\n```\n\n## Usage\n\nModally works with IDs. You need to apply a unique ID to each modal. If you are creating a modal from an existing element, it's ID will be used. If you are creating a modal with dynamic content (advanced usage), you need to provide an ID.\n\n// TODO: OPENING AND CLOSING MODALS target=\"_modal:open:modal-id\" target=\"_modal:close:modal-id\" explained\n// TODO: explain Modally class and the indexing of modals\n// TODO: Document the `selector` option, make a distinction between modally options and modal options\n\n### Quick Start\n\n```html\n\u003cdiv id=\"your-content\" hidden\u003e\u003ch1\u003eHello world!\u003c/h1\u003e\u003c/div\u003e\n\u003ca href=\"#your-content\" target=\"_modal\"\u003e\u003c/a\u003e\n```\n\n```javascript\nconst modally = new Modally();\n\n//turns your content into a modal, wraps it nicely\nmodally.add('your-content');\n```\n\n### Youtube and Vimeo modals\n\n```javascript\nconst modally = new Modally();\n\n//creates a video modal which looks for data-video and opens a Youtube or Vimeo embed within your modal\nmodally.add('your-video-modal', {video: true});\n```\n```html\n\u003ca href=\"#your-video-modal\" target=\"_modal\" data-video=\"https://www.youtube.com/watch?v=u9QJo5fBADE\"\u003eYoutube\u003c/a\u003e\n\n\u003cbutton type=\"button\" target=\"_modal:open:your-video-modal\" data-video=\"https://vimeo.com/243244233\"\u003eVimeo\u003c/button\u003e\n```\n\n### Image lightbox\n\n```javascript\nconst modally = new Modally();\n\n//creates an image modal which looks for data-image and opens an image within your modal\nmodally.add('your-image-modal', {image: true});\n```\n```html\n\u003ca href=\"#your-image-modal\" target=\"_modal\" data-image=\"https://picsum.photos/800/600\" data-width=\"800\" data-height=\"600\"\u003eImage\u003c/a\u003e\n\n\u003ca href=\"#your-image-modal\" target=\"_modal\" data-image=\"https://picsum.photos/600/800\" data-width=\"600\" data-height=\"800\"\u003eImage 2\u003c/a\u003e\n```\n\n### Advanced Usage\n\n```javascript\nconst modally = new Modally();\nmodally.add('advanced-example');\n\ndocument.addEventListener('modally:open:advanced-example', function(e) {\n\tconsole.log(e.detail); // Modal instance, contains template, target, element (if any), options, etc.\n\tconsole.log(e.detail.target); // Target element, the one that triggered the modal open. If it exists that is, otherwise it is undefined. So in the case of this example it will be the \u003ca\u003e element with href=\"#advanced-example\"\n\te.detail.template.querySelector('.modally-content').innerHTML = 'Hello world!';\n});\n```\n```html\n\u003ca href=\"#advanced-example\" target=\"_modal\"\u003e\u003c/a\u003e\n```\n\n## Properties\n\nProperty | Default | Accepts | Description\n-------- | ------- | ------- | -----------\n**landing** | `document.body` | string selector or element | where to append the modal window\n**disableScroll** | true | boolean | Whether to disable scrolling on the body when modal is open\n**scrollToTop** | true | boolean | Whether to scroll to top modal content upon opening a modal\n**maxWidth** | 'none' | 'none' or number | Defines maximum width of the modal window, just like max-width css property\n**classes** | '' | string | Additional classes to add to the modal window\n**verticalAlign** | 'middle' | 'middle' or 'top' or 'bottom' | Vertical orientation of the modal window, like vertical-align css property\n**closeParent** | false | boolean | Whether to close the parent modal window, parent window is automatically selected if a modal open is triggered within another modal\n**closeOthers** | false | boolean | Wether to close all other opened modals upon opening this modal\n**enableHashChange** | true | boolean | Whether to open a modal on hash change\n**closeOthersOnHashChange** | false | boolean | Whether to close all other opened modals upon opening a modal on hash change\n**updateHash** | false | boolean | Whether to update the hash when opening a modal. If set to true, the hash will be updated to the modal ID and the data attributes will be added to the hash as well in case of a video or image modal\n**video** | false | boolean | For creating a video modal\n**image** | false | boolean | For creating an image \"lightbox\" modal\n**autoplay** | true | boolean | Whether video modal should autoplay\n**template** | default modally template :point-down: | HTML string or element | Template of the modal window\n\nOptions can also be assigned via data attributes if you are creating a modal from an element. Attributes are named using the following pattern: `modally-\u003coption-name\u003e`, like so:\n\n```html\n\u003cdiv id=\"hello-world\" modally-max-width=\"800\" modally-vertical-align=\"top\"\u003e\n\t\u003ch1\u003eHello world!\u003c/h1\u003e\n\u003c/div\u003e\n```\n\n```javascript\nconst modally = new Modally();\nmodally.add('hello-world');\n```\n\n### Default template\n\n```html\n\u003cdiv class=\"modally-wrap\"\u003e\n\t\u003cdiv class=\"modally-table\"\u003e\n\t\t\u003cdiv class=\"modally-cell\"\u003e\n\t\t\t\u003cdiv class=\"modally-underlay modally-close\"\u003e\u003c/div\u003e\n\t\t\t\u003cdiv class=\"modally\" role=\"dialog\" aria-modal=\"true\"\u003e\n\t\t\t\t\u003cbutton tabindex=\"1\" aria-label=\"Close\" class=\"modally-close modally-close-button\"\u003e\u0026times;\u003c/button\u003e\n\t\t\t\t\u003cdiv class=\"modally-content\"\u003e\u003c/div\u003e\n\t\t\t\u003c/div\u003e\n\t\t\u003c/div\u003e\n\t\u003c/div\u003e\n\u003c/div\u003e\n```\n\n## Events\n\nEvent | Description\n----- | -----------\n**modally:added** | modal was created\n**modally:open** | modal is being opening\n**modally:opened** | modal is opened\n**modally:close**  | modal is being closed\n**modally:closed** | modal is closed\n\nModally events are named using the following pattern: `namespace:action` where namespace is `modally` and action is one of the above. Or `namespace:action:modal-id` where modal-id is the ID of the modal that is being opened/closed or added.\n\nAll events are dispatched on the `document` object and contain a `detail` property with the modal instance.\n\nYou can listen to a specific event of a specific modal via it's ID, by creating a listener to the event name consisted of the namespace + action + modal ID, like so:\n\n```javascript\ndocument.addEventListener('modally:open:your-modal-id', function(e) {\n\tconsole.log(e.detail); // Modal instance, contains template, target, element (if any), options, etc.\n});\n```\n\nor you can tune to all events of all modals and then check for the modal ID like so:\n\n```javascript\ndocument.addEventListener('modally:open', function(e) {\n\tif (e.detail.id === 'your-modal-id') {\n\t\tconsole.log(e.detail); // Modal instance, contains template, target, element (if any), options, etc.\n\t}\n});\n```\n\nEvents without the modal ID (namespace + action only) are dispatched on the `element` that is used for modal creation and becomes it's content (if it exists of course) and on `template` element as well.\n\n## Tested with :heart:\n\n[![BrowserStack](https://imgur.com/wfYoxvC.png)](https://www.browserstack.com/)\n\n## License\nMIT License\n\n-------\n\nP.S. Here is an oxymoron for you: I'm one of these people who if they have the time to make something they don't use other people's code, not to have to spend time extending it if god forbids it happens to be needed. Life's not so short now, huh?\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstamat%2Fmodally","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstamat%2Fmodally","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstamat%2Fmodally/lists"}