Skip to content

Instantly share code, notes, and snippets.

@tommycoppers
Last active August 29, 2015 14:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tommycoppers/a13cfc4894d6d3687011 to your computer and use it in GitHub Desktop.
Save tommycoppers/a13cfc4894d6d3687011 to your computer and use it in GitHub Desktop.
;(function($, window, document, namespace){
var modalData = 'modal';
$.fn.modal = function(options) {
return this.each(function() {
if (!$(this).data(modalData)) {
$(this).data(modalData, new Modal(this, options));
}
});
};
function Modal (modal, options) {
// Defaults for the module
var defaults = {
triggers : null, // String of elements: elements that trigger 'showModal' on click
hideBtns : '.js-close-modal', // String of elements: elements that trigger 'hideModal' on click
onShow: null, // Callback when $triggers are clicked
onClose: null // Callback when hideBtns are clicked
};
// Settings are defaults extended by options
var settings = $.extend(defaults,options);
// Constants
var $document = $(document),
$body = $('body'),
modalStatus = 'modal-open',
classModalContainer = '.modal-container',
classModal = '.modal',
escapeEvent = 'keyup.escapeModal';
// Catch vars
var $modal,
$hideBtns,
$triggers;
// Scoping
function scopeElements () {
$modal = $(modal);
if (settings.triggers) {
$triggers = $(settings.triggers);
}
if (settings.hideBtns) {
$hideBtns = $modal.find(settings.hideBtns);
}
}
function getModal () {
return $modal;
}
// Event Delegating
function bindEvents () {
$hideBtns.on('click.hideModal', function(){
cancelModal();
});
if ($triggers){
$triggers.on('click.showModal', function(){
triggerModal();
});
}
}
function bindCancelEvents () {
// Hitting the ESC key
$document.on(escapeEvent, function (event) {
if (event.keyCode === 27) {
cancelModal();
}
});
// Clicking Outside
outsideClick.bind($modal.find(classModal), cancelModal);
}
function unbindCancelEvents () {
$document.off(escapeEvent);
outsideClick.unbind();
}
function outsideClick () {
function OutsideClick () {
var eventNamespace = 'mousedown.outside';
function bindClick (exclusions, callback) {
var $exclusions = $(exclusions);
$(document).on(eventNamespace, function (e) {
if($(e.target).closest($exclusions).length === 0 && !$(e.target).is($exclusions)){
e.stopPropagation();
callback && callback();
unbindClick();
}
});
}
function unbindClick () {
$(document).off(eventNamespace);
}
return {
bind: bindClick,
unbind: unbindClick
};
}
return new OutsideClick();
}
// Show and Hide Modals
function showModal (callback) {
// Is there already an open modal?
if ($(classModalContainer).is(':visible')) {
hideOtherModals();
}
// Display js
$body.addClass(modalStatus);
$modal.appendTo($body).show();
// Bind all events associated with cancelling
bindCancelEvents();
// Callbacks
callback && callback();
}
function hideModal (callback) {
// Strip the modal's status class and hide the modal
$body.removeClass(modalStatus);
$modal.hide();
// Unbind all events associated with canceling
unbindCancelEvents();
// Callbacks
callback && callback();
}
function triggerModal () {
showModal(settings.onShow);
}
function cancelModal () {
hideModal(settings.onClose);
}
function hideOtherModals () {
unbindCancelEvents();
$(classModalContainer).filter(':visible').hide();
}
function updateModal (options) {
settings = $.extend(settings,options);
}
// Initialize
scopeElements();
bindEvents();
// Expose
return {
show: showModal,
hide: hideModal,
update: updateModal,
element: getModal()
};
}
namespace.modalManager = (function(){
function ModalManager () {
function listModals () {
return $('*').filter(function(){
return $(this).data(modalData);
});
}
return {
list: listModals
};
}
return new ModalManager();
})();
})(window.jQuery, window, document, window.namespace || {});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment