Moving stuff around

I have created a script to create form fields with javascript, each field has a button to remove it but I want to make available a way to move the fields around so they are ordered even after the field was created so if i have

form
label for x input x
label for y input y
label for z input z
form

how could I make it so the user is able to move them around to which ever order they like?

This is my current code however is not finished.


<html>
<head>
<style type="text/css" >
p, h1, form, button{border:0; margin:0; padding:0;}
#form_create {
	margin:0 auto;
	width:500px;
	padding:14px;
	}
#form_create label{
	display:block;
	font-weight:bold;
	text-align:right;
	width:140px;
	float:left;
	}
#form_create input {
	float:left;
	font-size:12px;
	padding:4px 2px;
	border:solid 1px #aacfe4;
	width:200px;
	margin:2px 0 20px 10px;
	}
#form_create select{
	float:left;
	font-size:12px;
	padding:4px 2px;
	border:solid 1px #aacfe4;
	width:200px;
	margin:2px 0 20px 10px;
	}
#form_create textarea{
	float:left;
	padding:4px 2px;
	margin:2px 0 20px 10px;
	}
#form_create button {
	clear:both;
	margin-left:150px;
	width:125px;
	height:31px;
	background:#666666 url(img/button.png) no-repeat;
	text-align:center;
	line-height:31px;
	color:#FFFFFF;
	font-size:11px;
	font-weight:bold;
	}
#form_create span{
color:#666666;
display:block;
font-size:11px;
font-weight:normal;
text-align:right;
width:140px;
}
#form_create p{
font-size:11px;
color:#666666;
margin-bottom:20px;
border-bottom:solid 1px #b7ddf2;
padding-bottom:10px;
}
</style>
<style type="text/css" >
p, h1, form, button{border:0; margin:0; padding:0;}
#form_preview {
	margin:0 auto;
	width:600px;
	padding:14px;
	}
#form_preview label{
	clear:both;
	display:block;
	font-weight:bold;
	text-align:right;
	width:140px;
	float:left;
	}
#form_preview input{
	float:left;
	font-size:12px;
	padding:4px 2px;
	border:solid 1px #aacfe4;
	width:200px;
	margin:2px 0 20px 10px;
	}
#form_preview select{
	float:left;
	font-size:12px;
	padding:4px 2px;
	border:solid 1px #aacfe4;
	width:200px;
	margin:2px 0 20px 10px;
	}
#form_preview button {
	clear:both;
	margin-left:150px;
	width:125px;
	height:31px;
	background:#666666 url(img/button.png) no-repeat;
	text-align:center;
	line-height:31px;
	color:#FFFFFF;
	font-size:11px;
	font-weight:bold;
	}
#form_preview span{
color:#666666;
display:block;
font-size:11px;
font-weight:normal;
text-align:right;
width:140px;
}
#form_preview p{
font-size:11px;
color:#666666;
margin-bottom:20px;
border-bottom:solid 1px #b7ddf2;
padding-bottom:10px;
}
#form_preview div {
    background: black;    
    float: left;    
    height: 25px;
    margin-top: 3px;
    margin-left: 5px;
}
#form_preview div a, a:link, a:visited, a:active{
    text-decoration:none;
}
#form_preview div span{
	color: red;
	font-size: 14px;
    font-weight: bold;
	margin-left:auto;
	margin-right:auto;
	text-align:center;
	padding-top:4px;
	}
</style>
<script type="text/javascript" >
function oc(a){
	var o = {};
	for(var i=0;i<a.length;i++){
		o[a[i]]='';
		}
	return o;
	}
var fields_array = new Array();
var fields_array_counter = 0;
var input_a = new Array('button', 'checkbox', 'file', 'hidden', 'password', 'radio', 'reset', 'submit', 'text')
var last_created_1 = '';
var last_created_2 = '';
var last_created_3 = '';
var last_created_4 = '';
var last_created_5 = '';
var last_created_counter = 1;
var groupname_a = new Array();
var groupname_counter = 0;
function form_create_input(){
	var label = document.getElementById('label').value;
	var label_loc = document.getElementById('label_loc').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 form_preview = document.getElementById('form_preview').innerHTML;
	var button_remover = '<div id="' + field_name + 'button_remove" ><a href="#" onclick="remove_field(' + "'" + field_name + "'" + ')" ><span ><<== Remove field</span></a></div>';
	last_created_5 = last_created_4;
	last_created_4 = last_created_3;
	last_created_3 = last_created_2;
	last_created_2 = last_created_1;
	last_created_1 = form_preview;
	if (groupname != ''){
		groupname_a[groupname_counter] = document.getElementById('groupname').value;
		groupname_counter ++;
		}
	if (type in (oc(input_a))){
		var newfield = '<input type="' + type + '" id="' + field_name + '" />';
		if (label != ''){
			var newlabel = '<label id="' + field_name + 'l" for"' + field_name + '" >' + label + '</label>';
			}
		else{var newlabel = ''}
		if (newlabel != ''){
			if (label_loc == 1){
				newfield = newlabel + newfield;
				}
			}
		}
	fields_array[fields_array_counter] = new Array(groupname, groupnamelegend, newfield);
	fields_array.sort();
	fields_array_counter ++;
	last_created_counter = 1;
	this_fieldset = '';
	document.getElementById('form_preview').innerHTML = form_preview + newfield + button_remover;
	}	
function revert_change(){
	if (last_created_counter == 1){
		document.getElementById('form_preview').innerHTML = last_created_1;
		last_created_counter ++;
		}
	else if (last_created_counter == 2){
		document.getElementById('form_preview').innerHTML = last_created_2;
		last_created_counter ++;
		}
	else if (last_created_counter == 3){
		document.getElementById('form_preview').innerHTML = last_created_3;
		last_created_counter ++;
		}
	else if (last_created_counter == 4){
		document.getElementById('form_preview').innerHTML = last_created_4;
		last_created_counter ++;
		}
	else if (last_created_counter == 5){
		document.getElementById('form_preview').innerHTML = last_created_5;
		last_created_counter ++;
		}
	else {
		alert('Sorry can´t undo, use the red x on the field that you like to delete.');
		}
	}
function remove_field(id){
	var parent = document.getElementById('form_preview');
	var label = document.getElementById(id + 'l');
	var field = document.getElementById(id);
	var button = document.getElementById(id + 'button_remove');
	parent.removeChild(label);
	parent.removeChild(field);	
	parent.removeChild(button);	
	}
function format_comma(){
	var textarea = document.getElementById('sel_check_opt').input;
	
	}
</script>
</head>
<body>
<form id="form_create" >
<fieldset name="input" ><legend>New field creator</legend>
<p>Leave empty any part that does not apply to your field.</p>
<label for="label">Text label<span>Text describing field</span></label><input type="text" id="label" />
<label for="label_loc">Text label possition:<span>Before or after the text?</span></label><select id="label_loc" /><option value="1" >Before</option><option value="2" >After</option></select>
<label for="groupname">Group name<span>No spaces.</span></label><input type="text" id="groupname" /><br/>
<label for="groupnamelegend">Group name:<span>Group name to display</span></label><input type="text" id="groupnamelegend" />
<label for="field_name">Unique name<span>For the field, no spaces</span></label><input type="text" id="field_name" />
<label for="type">Type to add:<span>The type of field to add</span></label>
<select id="type" >
<option value="button" >button</option>
<option value="checkbox" >checkbox</option>
<option value="file" >file</option>
<option value="hidden" >hidden</option>
<option value="password" >password</option>
<option value="radio" >radio</option>
<option value="reset" >reset</option>
<option value="select" >select</option>
<option value="submit" >submit</option>
<option value="text" >text</option>
<option value="textarea" >textarea</option>
</select>
<label for="sel_check_opt">Options<span>For select and checkbox.</span></label><textarea id="sel_check_opt" cols="25" rows="5" >Type them like this: option_1, option_2, option_3, etc</textarea>
<button type="submit" onclick="form_create_input(); return false;" >Add</button><br/><br/>
<button type="submit" onclick="revert_change(); return false;" >Undo Last</button>
</fieldset>
</form>
<div id="form_preview" >
</div>
</body>
</html>

Are you wanting to use up/down buttons/links or are you wanting the user to drag/drop them?

I don´t mind if is drag and drop or up and down buttons, however I do need the markup to be correct, by the way this is the structure I`m using:


<label for="value1">value1<span>some value</span></label><input type="text" id="value1" />
<label for="value2">value2<span>some value</span></label><input type="text" id="value2" />
<label for="value3">value3<span>some value</span></label><input type="text" id="value3" />
<label for="value4">value4<span>some value</span></label><input type="text" id="value4" />
<label for="value5">value5<span>some value</span></label><input type="text" id="value5" />

So I would need to move a whole block from the label to the input field.
I was thinking that to start I should be wrapping every block inside something else so the block is easier to move but don´t really have an idea on how to start.

If you wrap the label around the input as well, you won’t need the explicit association, and it is the label itself that can then just be dealt with.

Only if someone is using IE6 will the label not be associated with the field, which these days given its age and the many problems that IE6 has, is an acceptable compromise.

Did you intend to leave out the name attribute, which will result in those fields not being submitted? In case you do want them to be submitted, I’ve added a name attribute to the field.


<label>value1<span>some value</span><input type="text" name="value1" /></label>

I forgot the name and did not know I could wrap the label around the field, I will do that, any ideas on how I can go about moving the fields?

Typically the insertBefore() method can be used to move an element from one place to another.

I am trying to make it work, but I need the id of the access to the previous element right?

If so I was trying to get it this way:

function moveup(thefunctionfiring) {
	var nodetomove = thefunctionfiring.parentNode;
	var previousnode = nodetomove.previousSibling;
	alert(previousnode.id);
	alert(nodetomove.id);
    }

Where thefunctionfiring will be the the element that fired the function which is inside the label tag so I have a structure like this

<label><input/><button onclick=“moveup(this)” ></label>

with that function I was able to get the id of the label so I can then select it and move it but I cannot get the id of the previous label where the selected label will be placed before, do I actually need the previous node id or there is an easier way of doing this?

No, you don’t need the id. A variable reference to the element itself can be all that you need.

unfortunately I don´t have any reference to the item so I have to create it, I already checke the insertBefore() method and it works for wjhat I need, but I am having a hard time getting it to work without knowing or having any reference to the previous node is there an easy way to get a reference to it?

okay, I got it to work like this:

function moveup(node) {
	var nodetomove = node.parentNode;
	var previousnode = nodetomove.previousSibling;
	document.getElementById('form').insertBefore(nodetomove, previousnode);
    }

However I have to do 2 clicks, it seems to be using some sort of white space

To find the element that is the previousSibling, you can use a while loop that keeps going until you have an element


previousnode = nodetomove.previousSibling;
while (previousNode && previousNode.nodeType !== 1) {
    previousnode = previousnode.previousSibling;
}

This will walk on over anything that is not an HTML element, until you either get to one, or there are no other previous siblings to go to.
You can see the types of nodes at the nodeType page.

Sorry but I don´t quite understand how that works, in the example you compare previousNode && previousNode.nodeType !== 1 what does the 1 stand for? is it the html tag?

By the way thank you for the insertBefore() tip, that did what I was looking for.

Not just any HTML tag, but specifically an Element Node. The nodeType page I linked to before shows you all of the different possible values that nodeType can give. Modern web browsers have a Node object so that you can compare the result from nodeType with Node.ELEMENT_NODE, but since Internet Explorer doesn’t have the Node object the standard practice is to use the equivalent number for the node type instead. Type number 1 is an Element Node, whereas type number 3 is a Text Node.

With the code, if the node is not an Element Node, that being 1, you know that you still haven’t yet reached an Element Node and so you need to continue onwards until you get to one.

Okay, now I understand, thank you for all your help.