commit ffbfc08b31178e722b41c078ac4bd1a645103e15 Author: José Luis Garrido Labrador Date: Sat Aug 29 19:45:15 2020 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ccb2c80 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +package-lock.json \ No newline at end of file diff --git a/LICENCE b/LICENCE new file mode 100644 index 0000000..d39d0d0 --- /dev/null +++ b/LICENCE @@ -0,0 +1,7 @@ +Copyright 2020 José Luis Garrido-Labrador + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..fd49b61 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +Modalizer.js +== diff --git a/doc/index.html b/doc/index.html new file mode 100644 index 0000000..c9fa687 --- /dev/null +++ b/doc/index.html @@ -0,0 +1,387 @@ + + + + Modalizer.js - Examples + + + + + + + + + + + +
+
+
+
+

Modalizer.js

+
Lightweight extension over bootstrap's modals to improve of the control, animations and visualization of modal windows.
+
Licensed under MIT, created by José Luis Garrido-Labrador
+
+
+
+

Examples

+
+
+
+
+

Defaults modals

+
+
+ +
+
+ +
+
+ +
+
+ +
+
+

Optionable modals

+
+
+ +
+
+

Modal over modal

+
+
+ +
+
+
+
+

Custom animated modals

+
+ +
+
+ +
+

Customize with
Animate.css

+
+
+
+
+

Getting starting

+
+
+
+
+
+
+

Installation

+

Via npm

+
$ npm install modalizer.js
+

or add it directly using a CDN:

+
<link rel="stylesheet" href="https://future/modalizer.min.css"/>
+<script src="https://future/modalizer.min.js"></script>
+

Basic usage

+
Launch modal
+

Add class modalinit and modal's identifier in data-modal attribute to a <a>, <buttom> or any else HTML element.

+

Add class modalizer to the modal div

+

Example:

+
<a class="modalinit" data-modal="standart" href="#"> Click to open</a>
+
+<div class="modal modalizer fade" id="standart" tabindex= "-1" role="dialog">
+    ...
+</div>
+
Close a modal
+

Add class closemodal to a <a>, <buttom> or any else HTML element inside a modal div.

+

Example:

+
<div class="modal modalizer fade" id="standart" tabindex= "-1" role="dialog">
+    ...
+    <button class="closemodal">Close</button>
+    ...
+</div>
+
Animate a modal
+

Use a Animate.css animation for open and close animation

+

Add data-animate-in and data-animate-out with Animate.css animation (without animate__), remove class fade and add class animate__animated in modal

+

Example:

+
<div class="modal modalizer animate__animated" id="standart" tabindex= "-1" role="dialog" data-animate-in="zoomIn" data-animate-out="zoomOut">
+    ...
+</div>
+

Optionable modals

+

A optionable modal is that have multiple submodals inside and the user can navigate it between their.
To transform a modal into an optionable you need to add the modal-optionable class and assign a data-stack to it.
It is necessary create a instance of MOD_Stack with the same name in the javascript

+

Example:

+
<div class="modal modalizer fade modal-optionable" data-stack="defaultStack" id="standart" tabindex= "-1" role="dialog">
+    ...
+</div>
+<script>
+    const defaultStack = new MOD_Stack();
+</script>
+
Create submodals
+

+ The submodals are the modal-dialog with role="document" and have full compatibility with classes for modal-dialog in Bootstrap like centered or scrollable. +
Any submodal, except the first, must have the style attribute display: none. +

+

To navigate between submodals exists two classes: nextaction and beforeaction to apply to a <a>, <button> or any alse HTML element.
+ Also, it is necessary to add the attribute data-next with the identifier of the next submodal. If this attribute is not there then the modal will end. +
In the case of going backwards, the highest submodal in the stack will go. If the stack is empty then the modal will be closed. +
In addition, to enable the animation between submodals it is necessary add class animate__animated in the submodal.

+

Example

+
<div class="modal modalizer fade modal-optionable" data-stack="defaultStack" id="standart" tabindex= "-1" role="dialog">
+    <div class="modal-dialog animate__animated" id="first_submodal" role="document">
+        ...
+        <button class="beforeaction">Before</button>
+        <button class="nextaction" data-next="last_submodal">Next</button>
+        ...
+    </div>
+    <div class="modal-dialog animate__animated" id="last_submodal" role="document" style="display: none">
+        ...
+        <button class="beforeaction">Before</button>
+        <button class="nextaction">Next</button>
+        ...
+    </div>
+</div>
+

Fullscreen modal

+

For a fullscreen modal it is necessary add the class fullscreento the divs with classes modal-dialog, modal-content, modal-header and modal-footer. To make it only for mobile screens you have to add -sm to fullscreen

+ +
+
+ +
+
+
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..46703ed --- /dev/null +++ b/package.json @@ -0,0 +1,33 @@ +{ + "name": "modalizer.js", + "version": "1.0.0", + "description": "Lightweight extension over bootstrap's modals to improve of the control, animations and visualization of modal windows.", + "main": "dist/js/modalizer.js", + "style": "dist/css/modalizer.css", + "scripts": { + "test": "echo \"No test specified\" && exit 0" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/jlgarridol/modalizerjs.git" + }, + "keywords": [ + "bootstrap", + "modals", + "animation", + "navigation", + "css", + "javascript" + ], + "author": "Jose Luis Garrido-Labrador", + "license": "MIT", + "bugs": { + "url": "https://github.com/jlgarridol/modalizerjs/issues" + }, + "homepage": "https://github.com/jlgarridol/modalizerjs#readme", + "dependencies": { + "animate.css": "^4.1.0", + "bootstrap": "^4.5.2", + "jquery": "^3.5.1" + } +} diff --git a/src/modalizer.css b/src/modalizer.css new file mode 100644 index 0000000..4acc169 --- /dev/null +++ b/src/modalizer.css @@ -0,0 +1,103 @@ +/*! + * Modalizer.js v1.0.0 modalizerjs.jlgarridol.com + * Copyright 2011-2020 José Luis Garrido-Labrador + * Licensed under MIT (https://github.com/jlgarridol/modalizerjs/blob/main/LICENSE) + */ +body { + overflow-x: hidden; + overflow-y: scroll !important; +} + +.modal{ + padding-right: 0px !important; +} + +.modal-backdrop.show{ + display: none; +} + +.MOD_supreme-container.modal-open{ + filter:blur(.5rem); +} + + +.modal-content{ + border: 0px !important; +} + +.modal-optionable{ + z-index: 3000000000; + background-color: rgba(0,0,0,0.5); + padding: 0 !important; +} + +.modal-optionable > .modal-dialog { + --animate-duration: 0.5s; +} + +.modal-optionable .modal-dialog { + -webkit-transform: translate(0); + -moz-transform: translate(0); + transform: translate(0); +} + +.modal-dialog.fullscreen { + width: 100% !important; + height: 100% !important; + max-height: -moz-fit-content !important; + min-height: -moz-fit-content !important; + max-height: fit-content !important; + min-height: fit-content !important; + + margin: 0 !important; + padding: 0 !important; + max-width:none !important; + background-color: var(--white); + opacity: 1; + +} + +.modal-content.fullscreen { + height: auto !important; + min-height: 100% !important; + border-radius: 0 !important; +} + +.modal-header.fullscreen { + border-bottom: 1px solid #9ea2a2 !important; +} + +.modal-footer.fullscreen { + border-top: 1px solid #9ea2a2 !important; +} + +@media (max-width: 576px) { + + .modal-dialog.fullscreen-sm { + width: 100% !important; + height: 100% !important; + max-height: -moz-fit-content !important; + min-height: -moz-fit-content !important; + max-height: fit-content !important; + min-height: fit-content !important; + margin: 0 !important; + padding: 0 !important; + max-width:none !important; + + } + + .modal-content.fullscreen-sm { + height: auto !important; + min-height: 100% !important; + max-height: 100% !important; + border-radius: 0 !important; + } + + .modal-header.fullscreen-sm { + border-bottom: 1px solid #9ea2a2 !important; + } + + .modal-footer.fullscreen-sm { + border-top: 1px solid #9ea2a2 !important; + } +} \ No newline at end of file diff --git a/src/modalizer.js b/src/modalizer.js new file mode 100644 index 0000000..ed22d2c --- /dev/null +++ b/src/modalizer.js @@ -0,0 +1,279 @@ +/*! + * Modalizer.js v1.0.0 modalizerjs.jlgarridol.com + * Copyright 2011-2020 José Luis Garrido-Labrador + * Licensed under MIT (https://github.com/jlgarridol/modalizerjs/blob/main/LICENSE) + */ + +let MOD_howManyModals = 0; +let MOD_modalz = 9999; +let MOD_animate = ""; +let MOD_oc = null; + +let MOD_optionable = null; +let MOD_actioned = false; + +if (typeof $().modal != 'function') { + // jQuery is not loaded + console.error("Bootstrap modals not loaded") +}else{ + $(document).ready(function(){ + /** + * Launch modals + */ + $(".modalinit").each(function(){ + $(this).click(function(){ + let btn = $(this); + let modal = $("#"+btn.data('modal')); + if(modal.length != 0) + launchModal(modal); + }) + }); + + /** + * Add funcionalitiy for all nextaction blocks + */ + $(".nextaction").each(function(){ + $(this).click(function(){ + let btn = $(this); + let stack = eval(MOD_CURRENTMODAL.peek().data('stack')); + let nexttext = btn.data('next') || ""; + let dialog = btn.closest("div.modal-dialog"); + MOD_optionable = {dialog: dialog, nexttext: nexttext, stack: stack, next:true}; + MOD_actioned = true; + boostrapAnimation(dialog, "fadeOutLeftBig"); + + }); + }); + + /** + * Add funcionalitiy for all nextaction blocks + */ + $(".beforeaction").each(function(){ + $(this).click(function(){ + let btn = $(this); + let stack = eval(MOD_CURRENTMODAL.peek().data('stack')); + let before = stack.pop() + let dialog = btn.closest("div.modal-dialog"); + MOD_optionable = {before: before, dialog: dialog, next:false}; + MOD_actioned = true; + boostrapAnimation(dialog, "fadeOutRightBig"); + }); + }); + + // Finish animation for modal dialog + $(".modal-dialog.animate__animated").each(function(){ + $(this).on('animationend', function(e) { + if (MOD_optionable != null && MOD_actioned){ + MOD_actioned = false; + MOD_optionable.dialog.hide(); + + if(MOD_optionable.next){ + MOD_optionable.stack.push(MOD_optionable.dialog.attr("id")); + if(MOD_optionable.nexttext != ""){ + let next = $("#"+MOD_optionable.nexttext); + boostrapAnimation(next, "fadeInRightBig"); + next.show(); + }else{ + resetmodals(); + } + }else{ + if(MOD_optionable.before != null){ + let before = $("#"+MOD_optionable.before) + boostrapAnimation(before, "fadeInLeftBig"); + before.show(); + }else{ + MOD_optionable.dialog.show(); + resetmodals(); + } + } + + } + + }) + }) + + // Add a show and bs function for each modal + $(".modal.modalizer").each(function(){ + $(this).on("show.bs.modal", function(){ + let it = $(this); + + if(!it.hasClass("modal-optionable")){ + // If modal is already open don't add in how_manyModals + $("#MOD_supreme-container").addClass("modal-open"); + it.css("z-index", ++MOD_modalz); + } + }); + + $(this).on("hide.bs.modal", function(e){ + e.preventDefault(); + let it = $(this); + var animation = it.data("animate-out") || null; + if(animation != null){ + it.addClass("animate__"+animation); + } + MOD_animate = animation; + MOD_oc = it; + it.removeClass("show"); + MOD_modalz--; + + if($('.modal[style*="display: block"]').length > 1){ + $("#MOD_supreme-container").addClass("modal-open"); + }else{ + $("#MOD_supreme-container").removeClass("modal-open"); + $("body").removeClass("modal-open"); + } + + }); + }) + + // Close modal function + $(".closemodal").each(function(){ + $(this).click(function(){ + let modal = $(this).closest("div.modal"); + modal.modal("hide"); + resetmodals(); + }); + }); + + //Finished animation + $(".modal.modalizer.animate__animated").each(function(){ + $(this).on('animationend', function(e) { + let it = $(this); + if (MOD_animate != null) + it.removeClass("animate__"+MOD_animate); + if(MOD_oc != null){ + MOD_oc.css("display","none"); + if (MOD_oc.hasClass("modal-optionable")){ + afterresetmodal(MOD_oc); + } + } + MOD_oc = null; + MOD_animate = null; + }) + }); + + $("#MOD_supreme-container").click(function(e){ + e.preventDefault(); + }) + + }); + +} + + +function boostrapAnimation(modal, animation){ + var cls = modal.attr("class").split(" "); + cls.pop(); + cls.push("animate__"+animation); + modal.attr("class", cls.join(" ")); +} + +function launchModal(modal){ + var animation = modal.data("animate-in") || null; + if(animation != null){ + modal.addClass("animate__"+animation); + } + if(modal.hasClass("show")){ + modal.removeClass("show"); + setTimeout(function() { + modal.css("z-index", ++MOD_modalz); + modal.addClass("show"); + }, 500); + }else{ + setCurrentModal(modal); + if(!modal.hasClass("modal-optionable")) + MOD_howManyModals++; + modal.modal("show"); + } + modal.css("display","block"); + setTimeout(function(){ + if(animation != null){ + modal.removeClass("animate__"+animation); + } + }, 1000); + $("#MOD_supreme-container").addClass("modal-open"); + +} + +function resetmodals(){ + let curmodal = MOD_CURRENTMODAL.pop(); + curmodal.modal("hide"); +} + +function afterresetmodal(curmodal){ + let stack = eval(curmodal.data('stack')); + if(stack != null){ + stack.clean(); + } + let loop = 0; + let anim = curmodal.data('animate-in') || null; + curmodal.children('div').each(function(){ + let modal = $(this); + boostrapAnimation(modal, "fadeInRight"); + if(loop == 0){ + modal.css("display", ""); + if(anim != null) + boostrapAnimation(modal, anim) + }else{ + modal.css("display", "none"); + } + loop++; + }); +} + +function setCurrentModal(modal){ + MOD_CURRENTMODAL.push(modal); +} + +// Utils + +class MOD_Stack { + constructor(){ + this.items = []; + } + + push(element) + { + // push element into the items + this.items.push(element); + } + + pop() + { + // return top most element in the stack + // and removes it from the stack + // Underflow if stack is empty + if (this.isEmpty()) + return null; + return this.items.pop(); + } + + peek() + { + // return the top most element from the stack + // but does'nt delete it. + return this.items[this.items.length - 1]; + } + + isEmpty() + { + // return true if stack is empty + return this.items.length == 0; + } + + clean(){ + this.items = []; + } + +} + +function removeItemOnce(arr, value) { + var index = arr.indexOf(value); + if (index > -1) { + arr.splice(index, 1); + } + return arr; +} + +// Current modal stack +const MOD_CURRENTMODAL = new MOD_Stack(); \ No newline at end of file