[Code Review] Form builder

I ran it through Jslint

  • Assume a browser
  • Tolerate missing ‘use strict’ pragma
  • Tolerate many var statements per function

and this is the result


var form_values = ['form_preview', '', ''];
var undo_last = [];
var button_remover = '<a class="button_remove buttons" href="#" onclick="remove_field(this);return false;" >Remove field</a>';
var button_up = '<a class="button_up buttons" href="#" onclick="move_field(this.parentNode, this.parentNode.previousSibling);return false;" >Move up</a>';
var button_down = '<a class="button_down buttons" href="#" onclick="move_field(this.parentNode, this.parentNode.nextSibling.nextSibling);return false;" >Move down</a>';
var select_field = '<span class="checkbox checkbox_u" onmousedown="checked_box(this);" /></span>';
function form_create_input() {
	var newfield;
	var label = document.getElementById('label').value;
	var groupname = document.getElementById('groupname').value;
	var groupnamelegend = document.getElementById('groupnamelegend').value;
	var field_name = document.getElementById('field_name').value;
	var type = document.getElementById('type').value;
	var text_value = document.getElementById('text_value').value;
	var text_rows = document.getElementById('text_rows').value;
	var text_cols = document.getElementById('text_cols').value;
	var showinfo = document.getElementById('showinfo').value;
	var cb_groupname = document.getElementById('cb_groupname').value;
	var sel_opt = document.getElementById('sel_opt').value.split(', ');
	var cb_opt = document.getElementById('cb_opt').value.split(',');
	var form_preview = document.getElementById(form_values[0]).innerHTML;	
	var newlabel = '<label id="' + field_name + 'l" >';
	var options = '';	
	var cb = '<label><input type="checkbox" name="' + cb_groupname + '" value="selected" hidden="hidden" /></label>';
	var check = '';
	undo_last.unshift(form_preview);
	showinfo = '<span>' + showinfo + '</span>';
	switch (type) {
	case 'text' || 'password':
		document.getElementById(form_values[0]).innerHTML = form_preview + '<label id="' + field_name + 'l" ><span>' + label + '<p>' + showinfo + '</p></span><input type="' + type + '" id="' + field_name + '" name="' + field_name + '" value="' + text_value + '" />' + button_remover + button_up + button_down + select_field + '</label>';
		break;
	case 'textarea':
		document.getElementById(form_values[0]).innerHTML = form_preview + '<label id="' + field_name + 'l" ><span>' + label + '<p>' + showinfo + '</p></span><textarea id="' + field_name + '" >' + text_value + '</textarea>' + button_remover + button_up + button_down + select_field + '</label>';
		break;
	case 'select':
		for (i = 0; i < sel_opt.length; i++) { 
			options = options + '<option value="' + sel_opt[i] + '">' + sel_opt[i] + '</option>';
		} 
		document.getElementById(form_values[0]).innerHTML = form_preview + '<label id="' + field_name + 'l" ><span>' + label + '<p>' + showinfo + '</p></span><select id="' + field_name + '" >' + options + '</select>' + button_remover + button_up + button_down + select_field + '</label>';
		break;
	case 'checkbox':
		for (i = 0; i < cb_opt.length; i++) {
			var cb_value = cb_opt[i].split(':');
			check = '';
			if (cb_value[2] === 'c') {
				check = 'checked="checked" ';
			}			
			cb = cb + '<label><input type="checkbox" name="' + cb_groupname + '" value="' + cb_value[0] + '" ' + check + '/>' + cb_value[1] + '</label>';
		}
		document.getElementById(form_values[0]).innerHTML = form_preview + '<label id="' + field_name + 'l" ><span>' + label + '<p>' + showinfo + '</p></span><p id="' + field_name + '" >' + cb + '</p>' + button_remover + button_up + button_down + select_field + '</label>';
		break;
	}
}	
function revert_change() {
	if (undo_last[0] !== undefined) {
		document.getElementById(form_values[0]).innerHTML = undo_last[0];
		undo_last.splice(0, 1);
	}
}
function remove_field(id) {
	document.getElementById(form_values[0]).removeChild(id.parentNode);
}
function form_configurator(value, integer) {
	switch (integer) {
	case 0: 
		document.getElementById(form_values[0]).id = value.value;
		break;
	case 1: 
		document.getElementById(form_values[0]).action = value.value;
		break;
	case 2: 
		document.getElementById(form_values[0]).method = value.value;
		break;
	}
	form_values[integer] = value.value;
}
function move_field(node, direction) {
	document.getElementById(form_values[0]).insertBefore(node, direction);
}
function checked_box(checked) {
	if (checked.className === 'checkbox checkbox_u') {
		checked.className = 'checkbox checkbox_c';
	} else {
		checked.className = 'checkbox checkbox_u';
	}
}

I removed the for loop and replaced it for array.map


var form_values = ['form_preview', '', ''];
var undo_last = [];
var button_remover = '<a class="button_remove buttons" href="#" onclick="remove_field(this);return false;" >Remove field</a>';
var button_up = '<a class="button_up buttons" href="#" onclick="move_field(this.parentNode, this.parentNode.previousSibling);return false;" >Move up</a>';
var button_down = '<a class="button_down buttons" href="#" onclick="move_field(this.parentNode, this.parentNode.nextSibling.nextSibling);return false;" >Move down</a>';
var select_field = '<span class="checkbox checkbox_u" onmousedown="checked_box(this);" /></span>';
function form_create_input() {
	var newfield;
	var label = document.getElementById('label').value;
	var groupname = document.getElementById('groupname').value;
	var groupnamelegend = document.getElementById('groupnamelegend').value;
	var field_name = document.getElementById('field_name').value;
	var type = document.getElementById('type').value;
	var text_value = document.getElementById('text_value').value;
	var text_rows = document.getElementById('text_rows').value;
	var text_cols = document.getElementById('text_cols').value;
	var showinfo = document.getElementById('showinfo').value;
	var cb_groupname = document.getElementById('cb_groupname').value;
	var sel_opt = document.getElementById('sel_opt').value.split(', ');
	var cb_opt = document.getElementById('cb_opt').value.split(',');
	var form_preview = document.getElementById(form_values[0]).innerHTML;	
	var newlabel = '<label id="' + field_name + 'l" >';
	var options = '';	
	var cb = '<label><input type="checkbox" name="' + cb_groupname + '" value="selected" hidden="hidden" /></label>';
	var check = '';
	undo_last.unshift(form_preview);
	showinfo = '<span>' + showinfo + '</span>';
	switch (type) {
	case 'text' || 'password':
		document.getElementById(form_values[0]).innerHTML = form_preview + '<label id="' + field_name + 'l" ><span>' + label + '<p>' + showinfo + '</p></span><input type="' + type + '" id="' + field_name + '" name="' + field_name + '" value="' + text_value + '" />' + button_remover + button_up + button_down + select_field + '</label>';
		break;
	case 'textarea':
		document.getElementById(form_values[0]).innerHTML = form_preview + '<label id="' + field_name + 'l" ><span>' + label + '<p>' + showinfo + '</p></span><textarea id="' + field_name + '" >' + text_value + '</textarea>' + button_remover + button_up + button_down + select_field + '</label>';
		break;
	case 'select':
		sel_opt.map(function (i) { 
			options = options + '<option value="' + i + '">' + i + '</option>';
		}); 
		document.getElementById(form_values[0]).innerHTML = form_preview + '<label id="' + field_name + 'l" ><span>' + label + '<p>' + showinfo + '</p></span><select id="' + field_name + '" >' + options + '</select>' + button_remover + button_up + button_down + select_field + '</label>';
		break;
	case 'checkbox':
		cb_opt.map(function (i) {
			var cb_value = i.split(':');
			check = '';
			if (cb_value[2] === 'c') {
				check = 'checked="checked" ';
			}			
			cb = cb + '<label><input type="checkbox" name="' + cb_groupname + '" value="' + cb_value[0] + '" ' + check + '/>' + cb_value[1] + '</label>';
		});
		document.getElementById(form_values[0]).innerHTML = form_preview + '<label id="' + field_name + 'l" ><span>' + label + '<p>' + showinfo + '</p></span><p id="' + field_name + '" >' + cb + '</p>' + button_remover + button_up + button_down + select_field + '</label>';
		break;
	}
}	
function revert_change() {
	if (undo_last[0] !== undefined) {
		document.getElementById(form_values[0]).innerHTML = undo_last[0];
		undo_last.splice(0, 1);
	}
}
function remove_field(id) {
	document.getElementById(form_values[0]).removeChild(id.parentNode);
}
function form_configurator(value, integer) {
	switch (integer) {
	case 0: 
		document.getElementById(form_values[0]).id = value.value;
		break;
	case 1: 
		document.getElementById(form_values[0]).action = value.value;
		break;
	case 2: 
		document.getElementById(form_values[0]).method = value.value;
		break;
	}
	form_values[integer] = value.value;
}
function move_field(node, direction) {
	document.getElementById(form_values[0]).insertBefore(node, direction);
}
function checked_box(checked) {
	if (checked.className === 'checkbox checkbox_u') {
		checked.className = 'checkbox checkbox_c';
	} else {
		checked.className = 'checkbox checkbox_u';
	}
}

But if you still want Internet Explorer to also handle the code, you’ll need to allow for it only supporting up to version 1.3 of JavaScript.
Since array.map() is from version 1.6, the documentation page provides compatibility code to simulate its behaviour.

With the map code, you shouldn’t use i as the variable, because that implies that it will be a numerical indexing number. A variable called value should be more appropriate in that case there.

I have made many changes since I first posted this thread and would like to get, if possible, a new opinion on the code.

  1. I ran it in Jslint and got no errors
    [LIST]
  2. Assume a browser
  3. Allow multiple vars per function
  4. Tolerate missing 'strict
    [/LIST]
  5. Removed as many variables as I could from within the function.
  6. Ended up with only one global variable.
  7. Added the compatibility mode for
    [LIST]
  8. !Function.prototype.bind
  9. !Array.prototype.map
  10. !Array.prototype.indexOf
    [/LIST]

And this is the final code, I removed the compatibility code from here but I do have it in my script


var form_values = ['form_preview', '', ''];
function getTheData(id, property) {
	return document.getElementById(id)[property];
}
function fieldBeginningData(i) {
	if (i === 0) { 
		return getTheData(form_values[0], 'innerHTML') + '<div id="' + getTheData('field_name', 'value') + 'l" class="basic_input_div" ><label for="' + getTheData('field_name', 'value') + '">' + getTheData('label', 'value') + '<\\/label><span>' + getTheData('showinfo', 'value') + '<\\/span>';
	} else if (i === 1) {
		return getTheData(form_values[0], 'innerHTML') + '<div id="' + getTheData('field_name', 'value') + 'l" class="';
	}
}
function fieldEndData() {
	return '" >' + document.getElementById('confbuttons').innerHTML + '<\\/div><\\/div>';
}
function validateBeforeAdding(adding) {
	if (adding === 0) {
		if (form_values.indexOf(getTheData('field_name', 'value')) === -1) {
			form_values.push(getTheData('field_name', 'value'));
			document.getElementById('form_javascript_data').lang = getTheData('field_name', 'value');
			document.getElementById('form_javascript_data').innerHTML = '<div id="confbuttons" ><a onclick="removeElement(' + "'" + getTheData('field_name', 'value') + "'" + ');return false;" >Remove<\\/a><a onclick="moveElement(' + "'" + getTheData('field_name', 'value') + "l', 'up'" + ');return false;" >Move up<\\/a><a onclick="moveElement(' + "'" + getTheData('field_name', 'value') + "l', 'down'" + ');return false;" >Move down<\\/a><a class="checkbox checkbox_u" onclick="checkedClassChange(this);" /><\\/a><\\/div>';
		} else {
			window.alert('The id of every field should be unique, please verify it and try again, id ' + getTheData('field_name', 'value') + ' is already in use');
			document.getElementById('form_javascript_data').className = 'append_element_true';
		}
	}
}
function formCreateInput() {
	var options = '';	
	var cb = '<div id="' + getTheData('field_name', 'value') + 'l" class="radio_input_div"><p class="radio_checkbox_p" >' + getTheData('label', 'value') + '<\\/p><span class="radio_checkbox_span" >' + getTheData('showinfo', 'value') + '<\\/span>	<div class="radio_input_insidediv" >';
	var radio = '<div id="' + getTheData('field_name', 'value') + 'l" class="radio_input_div"><p class="radio_checkbox_p" >' + getTheData('label', 'value') + '<\\/p><span class="radio_checkbox_span" >' + getTheData('showinfo', 'value') + '<\\/span><div class="radio_input_insidediv" >';
	var check = '';	
	validateBeforeAdding(0);
	if (getTheData('form_javascript_data', 'className') === 'append_element_true') {
		document.getElementById('form_javascript_data').className = 'append_element_false';
		return false;		
	}
	switch (getTheData('type', 'value')) {
	case 'button':/**/
		document.getElementById(form_values[0]).innerHTML = fieldBeginningData(1) + 'button_field_div" ><button type="submit" id="' + getTheData('field_name', 'value') + '" >' + getTheData('label', 'value') + '<\\/button><div class="button_conf button_button_conf' + fieldEndData();
		break;
	case 'checkbox':/**/
		getTheData('cb_opt', 'value').split(',').map(function (value) {
			var cb_value = value.split(':');
			check = '';
			if (cb_value[2] === 'c') {
				check = 'checked="checked" ';
			}			
			cb = cb + '<input id="' + cb_value[0] + '" type="checkbox" name="' + getTheData('cb_groupname', 'value') + '" value="' + cb_value[0] + '" ' + check + '/><label for="' + cb_value[0] + '" >' + cb_value[1] + '<\\/label><br/>';
		});
		document.getElementById(form_values[0]).innerHTML = getTheData(form_values[0], 'innerHTML') + cb + '<\\/div><div class="button_conf checkbox_button_conf' + fieldEndData();
		break;
	case 'file':/**/
		document.getElementById(form_values[0]).innerHTML = fieldBeginningData(0) + '<input type="file" id="' + getTheData('field_name', 'value') + '" /><div class="button_conf file_button_conf' + fieldEndData();
		break;
	case 'hidden':/**/
		document.getElementById(form_values[0]).innerHTML = fieldBeginningData(1) + 'basic_input_div" ><label for="' + getTheData('field_name', 'value') + '">Hidden field<\\/label><span>With ID: ' + getTheData('field_name', 'value') + '<\\/span><span class="hidden_filler" ><\\/span><input value="' + getTheData('text_value', 'value') + '" name="' + getTheData('field_name', 'value') + '" type="hidden" id="' + getTheData('field_name', 'value') + '" /><div class="button_conf' + fieldEndData();
		break;	
	case 'password':/**/
		document.getElementById(form_values[0]).innerHTML = fieldBeginningData(0) + '<input type="password" id="' + getTheData('field_name', 'value') + '" value="' + getTheData('text_value', 'value') + '" /><div class="button_conf' + fieldEndData();
		break;
	case 'radio':/**/
		getTheData('cb_opt', 'value').split(',').map(function (value) {
			var cb_value = value.split(':');
			check = '';
			if (cb_value[2] === 'c') {
				check = 'checked="checked" ';
			}			
			radio = radio + '<input id="' + cb_value[0] + '" type="radio" name="' + getTheData('cb_groupname', 'value') + '" value="' + cb_value[0] + '" ' + check + '/><label for="' + cb_value[0] + '" >' + cb_value[1] + '<\\/label><br/>';
		});
		document.getElementById(form_values[0]).innerHTML = getTheData(form_values[0], 'innerHTML') + radio + '<\\/div><div class=" button_conf radio_button_conf' + fieldEndData();
		break;
	case 'reset':/**/
		document.getElementById(form_values[0]).innerHTML = fieldBeginningData(1) + 'basic_input_div" ><input id="' + getTheData('field_name', 'value') + '" class="basic_input_reset" type="reset" value="' + getTheData('label', 'value') + '" /><div class="button_conf reset_button_conf' + fieldEndData();
		break;
	case 'select':/**/
		getTheData('sel_opt', 'value').split(', ').map(function (value) { 
			options = options + '<option value="' + value + '">' + value + '<\\/option>';
		}); 
		document.getElementById(form_values[0]).innerHTML = fieldBeginningData(0) + '<select id="' + getTheData('field_name', 'value') + '" >' + options + '<\\/select><div class="button_conf select_button_conf' + fieldEndData();
		break;
	case 'submit': /**/
		document.getElementById(form_values[0]).innerHTML = fieldBeginningData(1) + 'button_field_div" ><button type="submit" id="button" >' + getTheData('field_name', 'value') + '<\\/button><div class="button_conf button_button_conf' + fieldEndData();
		break;	
	case 'text':/**/
		document.getElementById(form_values[0]).innerHTML = fieldBeginningData(0) + '<input type="text" id="' + getTheData('field_name', 'value') + '" value="' + getTheData('text_value', 'value') + '" /><div class="button_conf' + fieldEndData();
		break;
	case 'textarea':/**/
		document.getElementById(form_values[0]).innerHTML = fieldBeginningData(0) + '<textarea id="' + getTheData('field_name', 'value') + '" >' + getTheData('text_value', 'value') + '<\\/textarea><div class="button_conf textarea_button_conf' + fieldEndData();
		break;		
	}
}
function removeElement(id) {
	validateBeforeAdding();
	if (document.getElementById(id + 'l').parentNode.nodeName === 'FIELDSET' && document.getElementById(id + 'l').parentNode.getElementsByTagName('div').length === 2) {
		document.getElementById(form_values[0]).removeChild(document.getElementById(id + 'l').parentNode);
	} else {
		document.getElementById(id + 'l').parentNode.removeChild(document.getElementById(id + 'l'));
	}
	form_values.splice(form_values.indexOf(id), 1);
}
function formConfigurator(value, integer) {
	switch (integer) {
	case 0: 
		document.getElementById(form_values[0]).id = value.value;
		break;
	case 1: 
		document.getElementById(form_values[0]).action = value.value;
		break;
	case 2: 
		document.getElementById(form_values[0]).method = value.value;
		break;
	}
	form_values[integer] = value.value;
}
function moveElement(node, direction) {
	validateBeforeAdding();
	if (direction === 'up') {
		if (document.getElementById(node).previousSibling) {
			document.getElementById(node).parentNode.insertBefore(document.getElementById(node), document.getElementById(node).previousSibling);
		}
	} else if (direction === 'down') {
		if (!document.getElementById(node).nextSibling) {
			return false;
		}
		document.getElementById(node).parentNode.insertBefore(document.getElementById(node), document.getElementById(node).nextSibling.nextSibling);
	}
}
function checkedClassChange(checked) {
	if (checked.className === 'checkbox checkbox_u') {
		checked.className = 'checkbox checkbox_c';
	} else {
		checked.className = 'checkbox checkbox_u';
	}
}
function groupSelectedElements(els) {
	validateBeforeAdding();
	els = '<fieldset id="' + getTheData('groupname', 'value') + '" class="preview_div_style" ><legend>' + getTheData('groupnamelegend', 'value') + '<\\/legend>';
    Array.prototype.slice.call(document.getElementById(form_values[0]).getElementsByTagName('a')).map(function (value) {        
		if (value.className === 'checkbox checkbox_c') {
			value.className = 'checkbox checkbox_u';
			els = els + '<div id="' + value.parentNode.parentNode.id + '" class="' + value.parentNode.parentNode.className + '" >' + document.getElementById(value.parentNode.parentNode.id).innerHTML + '<\\/div>';
			document.getElementById(form_values[0]).removeChild(document.getElementById(value.parentNode.parentNode.id));
        }
	});
	document.getElementById(form_values[0]).innerHTML = els + '<\\/fieldset>' + getTheData(form_values[0], 'innerHTML');
}

It seems that the HTML structure of the web page has changed too. The old link to the test page doesn’t seem to be valid anymore, so do you have a link to an existing test page?

Still the same but I had not made the changes to it.

link

The link is the same but for some reason I was getting the old version, even after forcing refresh. The updated version is now appearing though.

What do you mean by memorizing all the codes?