Skip to content

Instantly share code, notes, and snippets.

@rachelbaker
Created April 14, 2014 18:17
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 rachelbaker/10671070 to your computer and use it in GitHub Desktop.
Save rachelbaker/10671070 to your computer and use it in GitHub Desktop.
/* ---------------------------------------------------------------------
Modal Base JavaScript
Target Browsers: All
Author: Rachel Baker
------------------------------------------------------------------------ */
// Namespace Object
var APP = APP || {};
// Pass reference to jQuery and Namespace
(function($, APP) {
"use strict";
// DOM Ready Function
$(function() {
APP.TheModal = new APP.Modal();
APP.TheModal.init();
});
/* ---------------------------------------------------------------------
Modal Base
Author: Rachel Baker
------------------------------------------------------------------------ */
APP.Modal = (function() {
var Modal = function() {
this.$modalOverlay = null;
this.$modalWrapper = null;
this.$modalContent = null;
this.$modalClose = null;
this.$body = null;
this.modalOffset = {};
this.$currentContent = null;
};
Modal.MODAL_OVERLAY_ID = 'js-modalOverlay';
Modal.MODAL_WRAPPER_ID = 'js-modalWrapper';
Modal.MODAL_CONTENT_ID = 'js-modalContent';
Modal.MODAL_CLOSE_ID = 'js-modalClose';
Modal.prototype.init = function() {
this.$body = $('body');
this.ensureModalExistance();
this.setOffsets();
};
Modal.prototype.enableClose = function() {
var self = this;
this.$modalClose.on('click', function(e) {
e.preventDefault();
self.closeModal();
});
this.$modalOverlay.on('click', function(e) {
e.preventDefault();
self.closeModal();
});
$(document).on('keyup', function(e) {
if (e.keyCode == 27) {
self.closeModal();
}
});
};
Modal.prototype.disableClose = function() {
this.$modalClose.off('click');
this.$modalOverlay.off('click');
$(document).off('keyup');
};
Modal.prototype.ensureModalExistance = function() {
// add modal overlay
if (!this.$modalOverlay) {
// see if it's in the DOM
var $modalOverlay = $('#' + Modal.MODAL_OVERLAY_ID);
// if so, set instance variable for $modalOverlay
if ($modalOverlay.length) {
this.$modalOverlay = $modalOverlay;
// or add the markup to the DOM and set $modalOverlay
} else {
var modalOverlayMarkup = this.getModalOverlayMarkup();
$modalOverlay = $(modalOverlayMarkup);
this.$body.append($modalOverlay);
this.$modalOverlay = $modalOverlay;
}
}
// add modal wrapper
if (!this.$modalWrapper) {
// see if it's in the DOM
var $modalWrapper = $('#' + Modal.MODAL_WRAPPER_ID);
// if so, set instance variable for $modalWrapper
if ($modalWrapper.length) {
this.$modalWrapper = $modalWrapper;
// or add the markup to the DOM and set $modalWrapper
} else {
var modalWrapperMarkup = this.getModalWrapperMarkup();
$modalWrapper = $(modalWrapperMarkup);
this.$body.append($modalWrapper);
this.$modalWrapper = $modalWrapper;
}
}
// ensure modal content is set
if (!this.$modalContent) {
// at this point, it has to be in the DOM
this.$modalContent = $('#' + Modal.MODAL_CONTENT_ID);
}
// ensure modal close is set
if (!this.$modalClose) {
// at this point, it has to be in the DOM
this.$modalClose = $('#' + Modal.MODAL_CLOSE_ID);
}
};
Modal.prototype.getModalOverlayMarkup = function() {
var markup = '<div class="modalOverlay" id="' + Modal.MODAL_OVERLAY_ID + '" style="display: none;"></div>';
return markup;
};
Modal.prototype.getModalWrapperMarkup = function() {
var markup = '<div class="modalWrapper" id="' + Modal.MODAL_WRAPPER_ID + '" style="display: none;">';
markup += '<a href="#" class="modalClose" id="' + Modal.MODAL_CLOSE_ID + '">Close</a>';
markup += '<div class="modalContent" id="' + Modal.MODAL_CONTENT_ID + '"></div>';
markup += '</div>'; // END: .modalWrapper
return markup;
};
Modal.prototype.getModalContentMarkup = function() {
var markup = '';
return markup;
};
Modal.prototype.getModalCloseMarkup = function() {
var markup = '<a href="#" class="icon icon_close">Close</a>';
return markup;
};
Modal.prototype.setOffsets = function() {
var $modalWrapper = this.$modalWrapper;
// set top offset from vertical padding
var paddingTop = parseInt($modalWrapper.css('padding-top'), 10);
var paddingBottom = parseInt($modalWrapper.css('padding-Bottom'), 10);
this.modalOffset.top = (paddingTop + paddingBottom) / 2;
// set left offset from horizontal padding
var paddingRight = parseInt($modalWrapper.css('padding-right'), 10);
var paddingLeft = parseInt($modalWrapper.css('padding-left'), 10);
this.modalOffset.left = (paddingRight + paddingLeft) / 2;
};
Modal.prototype.showModal = function($content) {
var dfd = new $.Deferred();
var self = this;
self.$currentContent = $content;
// add content to modal
this.$modalContent.html($content);
// make sure height and width are reset to zero
// and margins are set based off of padding
this.$modalWrapper.css({
'width': 0,
'height': 0,
'margin-left': -self.modalOffset.left,
'margin-top': -self.modalOffset.top
});
// fade in overlay
this.$modalOverlay.fadeIn('500', function() {
// hide content
self.$modalContent.fadeTo(0, 0);
self.$modalWrapper.fadeIn('250', function() {
self.enableClose();
self.$modalContent.fadeTo(250, 1);
self.resize(function () {
dfd.resolve();
});
// set content height to 100% so that it scales as the modal resizes
$content.height('100%');
});
});
return dfd.promise();
};
Modal.prototype.resize = function(onComplete) {
var $content = this.$currentContent;
var content = $content.get(0);
// reset height so we can get accurate measurements
$content.height('');
// measure height
var height = Math.min(content.scrollHeight, $(window).height() - this.modalOffset.top - 200);
// constrain if it is too tall so we can measure the width properly
$content.height(height);
// measure width
var width = content.scrollWidth;
// half values to position the modal
var halfWidth = Math.ceil(width / 2);
var halfHeight = Math.ceil(height / 2);
// throw it in the oven
this.$modalWrapper.animate(
{
'width': width,
'height': height,
'margin-left': -(halfWidth + this.modalOffset.left),
'margin-top': -(halfHeight + this.modalOffset.top)
},
500,
onComplete
);
};
Modal.prototype.closeModal = function() {
var self = this;
this.$modalWrapper.fadeOut('250', function() {
self.$currentContent.detach();
self.$currentContent = null;
self.$modalOverlay.fadeOut('500', function() {
self.disableClose();
});
});
};
Modal.prototype.renderModal = function() {
};
return Modal;
}());
}(jQuery, APP));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment