Quick JS Modal with callback

by Miega

HTML

<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<div class="col-md-12">
  <button id="default" class="btn btn-primary">Default Modal</button>
  <button id="callback" class="btn btn-primary">Modal with custom callback</button>
</div>
<script>
  "use strict";
  $(document).ready(function() {

    $("#default").on("click", function() {
      var defaultModal = new raModal({
        content: '<div>You clicked on the default button.</div>',
        closeButton: false
      });
      defaultModal.open();
    });
    $("#callback").on("click", function() {
      var callbackModal = new raModal({
        content: '<div>You clicked on the Callback button. This shows the popup, but has a custom callback funtion, called when the user clicks OK and/or Close.</div>',
        onOK: function() {
          okCallback('4');
        }, //only use the name of the function
        onClose: closeCallback,
        closeButtonText: "Close"
      });
      callbackModal.open();
    });

  });

  function closeCallback() {
    console.log("Successfully triggered the CLOSE callback.");
  }

  function okCallback(num) {
    console.log("Successfully triggered the OK callback with the number: " + num);
  }

</script>

CSS

/* raModal Base CSS */

@import url(https://fonts.googleapis.com/css?family=Open+Sans);
.ra-overlay {
  position: fixed;
  z-index: 9998;
  top: 0;
  left: 0;
  opacity: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, .33);
}

.ra-modal {
  font-family: "Open Sans", sans-serif;
  position: absolute;
  z-index: 9999;
  top: 50%;
  left: 50%;
  opacity: 0;
  width: 94%;
  padding: 24px 20px;
  /*Keeps modal always centered regardless of screen size on all broswers*/
  -webkit-transform: translate(-50%, -50%);
  -moz-transform: translate(-50%, -50%);
  -ms-transform: translate(-50%, -50%);
  -o-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
  border-radius: 5px;
  background: #fff;
  box-shadow: 8px 8px 10px #888888;
}

.ra-title {
  font-family: "Open Sans", sans-serif;
  font-size: 18px;
  font-weight: 600;
  margin-top: 1px;
  margin-bottom: 10px;
  background-color: #cccccc;
  text-align: center;
  border-radius: 8px;
}

.ra-content {
  font-family: "Open Sans", sans-serif;
  margin-bottom: 20px;
}

.ra-modal.ra-open.ra-anchored {
  top: 20px;
  /*Keeps modal always centered regardless of screen size on all broswers*/
  -webkit-transform: translate(-50%, 0);
  -moz-transform: translate(-50%, 0);
  -ms-transform: translate(-50%, 0);
  -o-transform: translate(-50%, 0);
  transform: translate(-50%, 0);
}


/*When opened, make the modal and overlay elements visible*/

.ra-modal.ra-open {
  opacity: 1;
}

.ra-overlay.ra-open {
  opacity: 1;
}


/* OK Button */

.ra-ok {
  font-family: "Open Sans", sans-serif;
  font-size: 16px;
  font-weight: 500;
  line-height: 13px;
  position: relative;
  padding: 5px 7px 7px 7px;
  margin-right: 3px;
  float: right;
  cursor: pointer;
  color: #fff;
  border: 0;
  outline: none;
  background: #8c8c8c;
}

.ra-ok:hover {
  background: #505050;
}


/* Close Button */

.ra-close {
  font-family: "Open Sans", sans-serif;
  font-size: 16px;
  font-weight: 500;
  line-height: 13px;
  position:...

JavaScript

"use strict";
(function() {

  // Make the constructor
  window.raModal = function() {

    // Create global element references
    this.closeButton = null;
    this.modal = null;
    this.overlay = null;

    // Define option defaults
    var defaults = {
      autoOpen: false,
      className: "modalClass",
      modalTitle: "Button Clicked!",
      okButton: true,
      closeButton: true,
      closeButtonText: "Close",
      content: "",
      maxWidth: 500,
      minWidth: 280,
      minHeight: 200,
      maxHeight: 800,
      overlay: true,
      onOK: null,
      onClose: null
    }

    // Create options by extending defaults with the passed in arugments
    if (arguments[0] && typeof arguments[0] === "object") {
      this.options = extendDefaults(defaults, arguments[0]);
    }
    if (this.options.autoOpen === true) this.open();

  }

  //Public Methods
  raModal.prototype.open = function() {
    // Build out raModal
    buildOut.call(this);

    // Initialize event listeners
    initializeEvents.call(this);

    //force recalcuation of modal height using the window's height
    window.getComputedStyle(this.modal).height;

    this.modal.className = this.modal.className +
      (this.modal.offsetHeight > window.innerHeight ?
        " ra-open ra-anchored" : " ra-open");
    this.overlay.className = this.overlay.className + " ra-open";
  }

  raModal.prototype.close = function() {
    // Store the value of this
    var c = this;

    // Remove the open class name to make it non-viewable (in case other functions are happening at the same time)
    this.modal.className = this.modal.className.replace(" ra-open", "");
    this.overlay.className = this.overlay.className.replace(" ra-open", "");

    //Remove the nodes from the DOM (will cease to exist)
    c.modal.parentNode.removeChild(c.modal);

    if (c.overlay.parentNode) {
      c.overlay.parentNode.removeChild(c.overlay);
    }
  }

  //Private Methods (only called by the plugin itself)

  function...