Skip to content

Instantly share code, notes, and snippets.

@learner-long-life
Created January 14, 2015 03:09
Show Gist options
  • Save learner-long-life/b70753208c9e9f23b773 to your computer and use it in GitHub Desktop.
Save learner-long-life/b70753208c9e9f23b773 to your computer and use it in GitHub Desktop.
// First, checks if it isn't implemented yet.
// from http://stackoverflow.com/questions/610406/javascript-equivalent-to-printf-string-format
if (!String.prototype.format) {
String.prototype.format = function() {
var args = arguments;
return this.replace(/{(\d+)}/g, function(match, number) {
return typeof args[number] != 'undefined'
? args[number]
: match
;
});
};
}
// Define an assert method, from https://gist.github.com/kaheglar/1042463
$.assert = function(condition, msg) {
if (!condition) {
$.error(msg);
}
};
/*
* Function for .each iterator to convert an
* input object into an HTML form input tag of the right type,
* with the class .input
*/
function createFormInput(index, value) {
if (!value || !value.type || (value.required == undefined) || !value.name) {
return;
}
// Create the formatted string for the div, with classname == value.name
var divString = '<div class="{0}"></div>'.format(value.name)
$('form').append(divString)
var className = "."+value.name;
// Create the required string
var requiredString = value.required ? 'required' : '';
// Create and add the legend string to the div
var legendString = '<legend>{0}</legend>'.format(value.name)
$(className).append(legendString)
// Handle text inputs
if (value.type === "text") {
var inputString = '<input class="input" type="text" name="{0}" {1}></input>'.format(
value.name, requiredString);
$(className).append(inputString)
// Handle radio group inputs
} else if (value.type === "radioGroup") {
var baseString = '<input class="input" type="radio" name="{0}" value="{1}">{2}</input>';
for (var i = 0; i < value.choices.length; i++) {
var choice = value.choices[i];
var inputString = baseString.format(
value.name, choice.value, choice.label);
$(className).append(inputString);
}
// Handle select inputs
} else if (value.type === "select") {
var baseString = '<option value={0}>{1}</option>';
var selectString = "<select class='input' id={0} name={0} {1}></select>".format(
value.name, requiredString);
$(className).append(selectString);
for (var i = 0; i < value.options.length; i++) {
var option = value.options[i];
var inputString = baseString.format(option.value, option.text);
$("select#"+value.name).append(inputString);
}
$(className).append("</select>");
// Select the newly added object and make it unselected (blank default)
$("#"+value.name).prop("selectedIndex", -1);
}
// Add a red asterisk as a visual reminder that a field is required
if (value.required) {
$(className).append('<span class="asterisk">&#10033;</span>');
}
}
function ajaxPostSuccess(msg) {
if (msg) {
//alert("Successfully submitted!");
} else {
alert("Unknown error !");
}
}
function sendJSON(actionURL, sendData) {
$.ajax({
type: "POST",
url: actionURL,
dataType: "json",
success: ajaxPostSuccess,
data: sendData
}).error(function() {
console.error("Some error occurred while posting the Ajax request.");
});
}
function serializeInputs(formInputs) {
var object = {};
function serializeInput(index, input) {
var inputName = $(input).attr('name');
$.assert(inputName !== undefined);
// Handle radio buttons differently
if ($(input).attr('type') === 'radio') {
var radioString = 'input[name={0}]:checked'.format(inputName);
var radioChecked = $(radioString);
// Only add a key-value pair if exactly one radio button was checked
if (radioChecked.length === 1) {
object[inputName] = $(radioChecked[0]).val();
}
} else {
var value = $(input).val();
if (value.length > 0) {
object[inputName] = $(input).val();
}
}
}
$.each(formInputs, serializeInput);
return object;
}
/*
* Handler function to parse Ajax response with dynamic form content.
*/
function createForm(obj) {
var action = obj.action;
// As a test, we can set the form action to the given URL
// but we actually want to replace the default form submission behavior
// to be an Ajax request instead.
//$('form').attr('action', action);
var inputs = obj.inputs;
$.each(inputs, createFormInput);
// This doesn't appear to work (the keys are correct, but all the values are blank)
// var sendData = $("form").serializeArray();
var form = $('form');
var submitButton = $('input[type="submit"]');
var anyError = false;
// Helper function, defined in this scope to get access to anyError
// TODO There is probably a better way to do this.
function validateInput(index, inputTag) {
// Convert to a jQuery object
inputTag = $(inputTag);
var inputName = inputTag.attr("name");
// Create a new CSS class for the error message that is based on the
// original input's name
var errorName = "error-" + inputName;
// Handle both the case of empty text inputs, and empty select inputs
if (inputTag.attr("required") &&
((!inputTag.val()) || (inputTag.val().length === 0) || (inputTag.prop("selectedIndex") === -1))) {
// If an input is required and there is no text, add an error message
var errorString = '<p id="{0}">Required field!</p>'.format(
errorName);
// Append it to the div with the right class matching this input name
// only if there is not already an error message.
if ($("#"+errorName).length === 0) {
$('.'+inputName).append(errorString);
}
anyError = true;
// Exit the function now, so we don't just remove the error we just
// added below.
return;
}
// If there exists an error message, and there is no longer an error
// (guaranteed in this branch), then remove the error message
if ($("#"+errorName).length !== 0) {
$("#"+errorName).remove();
}
}
// Make sure there is exactly one form on the page, and we have it
$.assert(form.length === 1);
form.submit(function(event){
event.preventDefault();
anyError = false;
// Iterate through all the form elements (".input") and if they are required,
// make sure their value is not empty
$.each($('.input'), validateInput);
if (anyError) {
// If there is any error, exit now and do not send JSON request.
return;
}
var sendData = serializeInputs($('.input'));
sendJSON(action, sendData);
// After we send JSON, remove our form elements so that we can
// tell something happened.
form.remove();
var successString = '<p>Successfully submitted AJAX post: {0}</p>'.format(
JSON.stringify(sendData));
$('body').append(successString);
});
}
$.ajax({
url : 'http://bennysidelinger.com/formModel.php',
type : "GET",
crossDomain: true,
dataType: 'json',
success: function(data){
console.log(data);
createForm(data);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment