This code is not live, but for brevity I'll write as though it is.
When a user clicks any element with the class name js-modalOpen
, for example:
<span class="js-modalOpen" data-modal="signup">Sign up</span>
A modal appears. The contents of that modal's dialog are determined by data-modal
. All modal contents live as snippets in my framework's static/html/
directory. My first concern is that I'm calling the methods and then binding their behavior to the target elements. Somehow it makes sense to me, but I've rarely seen it in production. Thus:
Modal.modalOpenListener();
Would call
var Modal = (function ($, SCRIPT_ROOT, CSRF_TOKEN) {
methods = {};
methods.modalOpenListener = function() {
$(".js-modalOpen").on("click", function() {
// Some names for loading snippets
var snippetType = $(this).attr("data-modal");
var snippet = SCRIPT_ROOT + "/static/html/" + snippetType + "_modal_snippet.html";
$(".modal").toggle();
$(".modal").addClass("visible");
document.body.style.overflow = "hidden";
dialogContentsLoad(snippetType, snippet);
});
}
return methods;
})(jQuery, SCRIPT_ROOT, CSRF_TOKEN);
The general structure of the code follows this pattern within the module. I'm concerned chiefly about
- Security (I'm bad at this)
- Modularity
I'll paste the whole code base I currently have for the sake of anyone brave enough to wade through it.
var Modal = (function ($, SCRIPT_ROOT, CSRF_TOKEN) {
methods = {};
// TODO:
// 1. Write a function that gathers the values of the input
// so that if the user accidentally closes the modal, the
// values remain when it's reopened.
// 2. Write a function the stops the ability to tab into
// the main web page when the modal is open
// 3. If a given form field IS NOT ".js-required" and IS empty,
// don't serialize that part, so it gets ignored in error
// checking
var dialogContentsLoad = function(snippetType, snippet) {
$(".dialogContents").load(snippet, function() {
// If there's a form in the dialog, do this (".length" because
// jQuery will simply return an empty array if there's not matching
// element)
if ($(".dialog").find("form").length) {
var formType = snippetType;
var form = formType + "Form";
// All modal fields will have a tabindex of "0"
$("input").first().attr("tabindex", "0").focus();
$("input[name='_csrf_token']").val(CSRF_TOKEN);
// This should probably be taken out of this function...right?
$("input").on("focus", function() {
$(this).css("background-color", "#2b2b2b")
});
$("input").on("blur", function() {
$(this).css("background-color", "#4b4b4b")
});
formSubmitListener(form, formType, CSRF_TOKEN);
}
});
}
var formSubmitListener = function(form, formType, CSRF_TOKEN) {
var destinationURL = SCRIPT_ROOT + "/" + formType + "_action";
$("#" + form).bind("submit", function(e) {
e.preventDefault();
$.ajax({
type: "POST",
data: $("#" + form).serialize(),
url: destinationURL,
success: function(resp) {
if (resp != "0") {
errors = $.parseJSON(resp);
console.log(errors['emptyFields']);
$("." + form + "Errors").empty();
if (!$.isEmptyObject(errors.emptyFields)) {
$("." + form + "Errors").append("Please fill out all required fields.")
for (error in errors.emptyFields) {
$("input[name='" + errors.emptyFields[error] + "Signup']").css("background-color", "#f22166");
}
}
delete errors.emptyFields;
console.log(errors);
for (error in errors) {
$("." + form + "Errors").append(errors[error]);
}
} else {
location.reload(false);
}
}
});
});
}
methods.modalOpenListener = function() {
$(".js-modalOpen").on("click", function() {
var snippetType = $(this).attr("data-modal");
var snippet = SCRIPT_ROOT + "/static/html/" + snippetType + "_modal_snippet.html";
$(".modal").toggle();
$(".modal").addClass("visible");
document.body.style.overflow = "hidden";
dialogContentsLoad(snippetType, snippet);
});
}
methods.modalCloseListener = function() {
$(document).on("keyup", function(e) {
if (e.keyCode == 27 && $(".modal").hasClass("visible")) {
$(".modal").toggle();
$(".modal").removeClass("visible");
document.body.style.overflow = "visible";
}
});
$(".js-modalClose").on("click", function(e) {
if (e.target == this) {
$(".modal").toggle();
$(".modal").removeClass("visible");
document.body.style.overflow = "visible";
}
});
}
return methods;
})(jQuery, SCRIPT_ROOT, CSRF_TOKEN);
I appreciate any input I can get on this.