Last active
April 20, 2018 15:58
-
-
Save robinbastien/2d95b6130f10e589249c to your computer and use it in GitHub Desktop.
jQuery Simple Modal
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*! | |
* jQuery.modal.js | |
* | |
* Creates a modal to use with images | |
* | |
* @author Robin Bastien <[email protected]> | |
* @version 1.0.1 | |
* | |
* @example | |
* $('.section--gallery').modal(); | |
* | |
* @example with parameters | |
$('.section--gallery').modal({ | |
attribute: 'data-modal', | |
class: 'modal__target', | |
close_button: '<i class="icon icon-close"></i>', | |
arrows: false, | |
arrow_next: '<i class="icon icon-arrow-right"></i>', | |
arrow_prev: '<i class="icon icon-arrow-left"></i>', | |
keycodes: true | |
}); | |
* | |
*/ | |
;(function($, window, document, undefined) { | |
/** | |
* Add the example function to the jQuery functions. | |
* | |
* @param Object options An object containing options for the plugin. | |
* @return Object Returns the jQuery object. | |
*/ | |
$.fn.modal = function(options) { | |
// The default options for the plugin. | |
var defaults = { | |
attribute: 'data-modal', // attribute to pull the URL from | |
class: 'modal__target', // what class should we append to these to make them modal targets? | |
close_button: true, | |
close_html: '<i class="icon icon--close"></i>', // the HTML used in the close button | |
arrows: false, | |
arrow_next: '<i class="icon icon--arrow-right"></i>', | |
arrow_prev: '<i class="icon icon--arrow-left"></i>', | |
keycodes: true | |
}; | |
var body = $('body'); | |
var modal_wrapper = false; | |
var modal_content = false; | |
var modal_overlay = false; | |
var modal_close = false; | |
var modal_structure = ''; | |
var $modal = $(this); | |
// Extend the options with all the defaults and overwrite any supplied | |
// options. | |
options = $.extend(defaults, options); | |
// If modal container doesn't exist... | |
if( !body.find('.modal__wrapper').length ) { | |
// Create the structure | |
modal_structure = '<div class="modal__wrapper"><div class="modal__overlay"></div><div class="modal">'; | |
// Add the close button? | |
if( options.close_button ) modal_structure += '<div class="modal__close">'+ options.close_html+'</div>'; | |
// Add the next/prev arrows? | |
if( options.arrows ) modal_structure += '<nav class="modal__arrows"><ul><li class="modal__arrow modal__arrow--prev">'+ options.arrow_prev+'</li><li class="modal__arrow modal__arrow--next">'+ options.arrow_next+'</li></ul></nav>'; | |
// Add the innards | |
modal_structure += '<div class="modal__content"></div></div><!--.modal--></div><!--.modal__wrapper-->'; | |
// Append it | |
body.append( modal_structure ); | |
modal_wrapper = body.find('.modal__wrapper'); | |
modal_content = body.find('.modal__content'); | |
modal_overlay = body.find('.modal__overlay'); | |
modal_close = body.find('.modal__close'); | |
if( options.keycodes ) document.addEventListener("keyup", keyEvents, false); | |
} | |
function keyEvents( event ) { | |
if(event.keyCode==27) closeModal(); | |
if(event.keyCode==37) nextImage(); | |
if(event.keyCode==39) prevImage(); | |
} | |
function openModal() { | |
modal_wrapper.addClass('is-active'); | |
} | |
function closeModal() { | |
modal_wrapper.removeClass('is-active'); | |
modal_content.html(''); | |
body.find('.modal__active').removeClass('modal__active'); | |
} | |
function nextImage() { | |
var active = $modal.find('.modal__active'); | |
if( active.length ) { | |
// Get index + 1 | |
var new_index = $modal.find('.' + options.class).index(active) + 1; | |
var new_image = $modal.find('.' + options.class + ':eq('+new_index+')'); | |
var set_content; | |
// Unset the active item | |
active.removeClass('modal__active'); | |
if( new_image.length ) { | |
new_image.addClass('modal__active'); | |
// Get the new content | |
set_content = new_image.attr( options.attribute ); | |
// Update the modal | |
setModalContent( set_content ); | |
} else { | |
// Set the first one as the active item | |
new_image = $modal.find('.' + options.class + ':first'); | |
new_image.addClass('modal__active'); | |
// Get the new content | |
set_content = new_image.attr( options.attribute ); | |
// Update the modal | |
setModalContent( set_content ); | |
} | |
} | |
} | |
function prevImage() { | |
var active = $modal.find('.modal__active'); | |
if( active.length ) { | |
// Get index + 1 | |
var new_index = $modal.find('.' + options.class).index(active) - 1; | |
var new_image = $modal.find('.' + options.class + ':eq('+new_index+')'); | |
if( new_image.length ) { | |
// Unset the active item | |
active.removeClass('modal__active'); | |
new_image.addClass('modal__active'); | |
// Get the new content | |
var set_content = new_image.attr( options.attribute ); | |
// Update the modal | |
setModalContent( set_content ); | |
} | |
} | |
} | |
function setModalContent( content ) { | |
modal_content.html( '<img src="' + content + '" class="modal__image">' ); | |
} | |
// Loop through each item that the plugin is attached to. | |
this.each(function() { | |
// Make it a single object | |
$(this).find('[' + options.attribute + ']').each( function() { | |
$(this).addClass(options.class); | |
}); | |
}); | |
// attach a click event | |
body.on('click', '.' + options.class, function( event ) { | |
// Reset default func | |
event.preventDefault(); | |
// Set Content | |
$this = $(this); | |
// If this has data-content, use that. Otherwise use itself | |
if( $this.attr(options.attribute) ) { | |
// Set as active | |
$this.addClass('modal__active'); | |
// Update content | |
setModalContent($this.attr(options.attribute)); | |
} else { | |
console.log('No modal attribute found on target element (' + options.attribute + ')'); | |
} | |
// Open er up | |
openModal(); | |
}); | |
// On Close click | |
body.on('click', '.modal__overlay, .modal__close', closeModal); | |
// Arrows Click | |
if( options.arrows ) { | |
// Next | |
body.on('click', '.modal__arrow--next', nextImage); | |
// Prev | |
body.on('click', '.modal__arrow--prev', prevImage); | |
} | |
// Return the object for chaining. | |
return this; | |
}; | |
})(jQuery, window, document); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* ========================================================================== | |
Modal | |
========================================================================== */ | |
.modal__wrapper { | |
display: none; | |
content: ''; | |
position: fixed; | |
visibility: hidden; | |
top: 0; | |
left: 0; | |
height: 100%; | |
width: 100%; | |
background-color: rgba(0,0,0,0); | |
z-index: -1; | |
-webkit-transition: background-color 0.6s ease-out; | |
transition: background-color 0.6s ease-out; | |
} | |
.modal__overlay { | |
height: 100%; | |
width: 100%; | |
position: absolute; | |
top: 0; | |
left: 0; | |
z-index: -1; | |
background-color: rgba(0,0,0,0); | |
pointer-events: none; | |
-webkit-transition: background-color 0.6s ease-out; | |
transition: background-color 0.6s ease-out; | |
} | |
.modal { | |
visibility: hidden; | |
width: auto; | |
height: auto; | |
padding: 2rem; | |
border-radius: 4px; | |
position: fixed; | |
top: 50%; | |
left: 50%; | |
background-color: #fff; | |
text-align: center; | |
z-index: 999; | |
-webkit-transform: translateX(-50%) translateY(-30%) scale(0.8); | |
transform: translateX(-50%) translateY(-30%) scale(0.8); | |
-webkit-transition: -webkit-transform 0.3s ease-out; | |
transition: transform 0.3s ease-out; | |
} | |
/* States */ | |
.modal__wrapper.is-active { | |
display: block; | |
z-index: 998; | |
} | |
.modal__wrapper.is-active .modal__overlay { | |
background-color: rgba(0,0,0,0.5); | |
visibility: visible; | |
z-index: 998; | |
pointer-events: all; | |
} | |
.modal__wrapper.is-active .modal { | |
visibility: visible; | |
-webkit-transform: translateX(-50%) translateY(-50%) scale(1); | |
transform: translateX(-50%) translateY(-50%) scale(1); | |
} | |
.modal__image { | |
max-height: 90vh; | |
max-width: 90vw; | |
width: auto; | |
} | |
.modal__close { | |
position: absolute; | |
right: -0.5rem; | |
top: -0.5rem; | |
background-color: white; | |
border-radius: 99px; | |
line-height: 1; | |
padding: 0.1rem; | |
font-size: 1.3rem; | |
cursor: pointer; | |
} | |
/* Modal Arrows */ | |
.modal__arrows { | |
position: absolute; | |
width: 100%; | |
left: 0; | |
bottom: -3rem; | |
} | |
.modal__arrows > ul { | |
list-style-type: none; | |
padding: 0; | |
margin: 0; | |
text-align: center; | |
} | |
.modal__arrow { | |
display: inline-block; | |
color: white; | |
font-size: 2rem; | |
cursor: pointer; | |
} | |
.modal__arrow--disabled { | |
cursor: not-allowed; | |
color: #bbb; | |
opacity: 0.7; | |
pointer-events: none; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment