Adding successive input fields - best practices?

J

J Y

Hi,

I'm writing a Rails app that uses some Javascript to allow users to
click a button to add more input fields to the page. I have the code
working, but it's very unelegant, with the HTML forms packed into the
Javascript code.

I don't want to do any server-side stuff for something this simple.
I'd like to be able to put most of the HTML somewhere in a hidden div,
but can't think of a way to make that work, since I need to increment
the index of the "name" field for each new input field.

What is the best practice for doing this? Surely not the way I have
done it.

A snippet of my code is below.

function add_new_link_fields(new_count){
new_fields = '<li><span class="newlink_label">New link:</span><span
class="field_label">URL:</span><span class="r"><input id="site_url"
type="text" name="site[' + new_count + ']"/></span></li><li><span
class="field_label">Title:</span><span class="r"><span
class="r1"><input id="site_title" type="text" name="site[' + new_count
+ '][title]"/></span><span class="r2">Tags: <input id="site_tag_list"
type="text" name="site[' + new_count + '][tag_list]"/></span></span></
li><li><span class="field_label">Description:</span><span
class="r"><input type="text" id="site_description" name="site[' +
new_count + '][description]"><span class="controls" id="controls' +
new_count + '"></span></span></li>';
saved_values = Form.getElements('ajax_submit_form')
$('new_link_fields').innerHTML += new_fields
if (new_count > 1) {
// Restore saved values
for (i in saved_values) {
e = saved_values
if (e.value && e.type != 'submit') {
$('ajax_submit_form').elements[e.name].value = e.value
}
}

old_count = new_count - 1;
$('controls' + old_count).innerHTML = "";
$('in_place_create_submit_button').value = "Add links";
}
$('controls' + new_count).innerHTML = $('controls_source').innerHTML;
}
 
T

Tom Cole

Hi,

I'm writing a Rails app that uses some Javascript to allow users to
click a button to add more input fields to the page.  I have the code
working, but it's very unelegant, with the HTML forms packed into the
Javascript code.

I don't want to do any server-side stuff for something this simple.
I'd like to be able to put most of the HTML somewhere in a hidden div,
but can't think of a way to make that work, since I need to increment
the index of the "name" field for each new input field.

What is the best practice for doing this?  Surely not the way I have
done it.

A snippet of my code is below.

function add_new_link_fields(new_count){
        new_fields = '<li><span class="newlink_label">New link:</span><span
class="field_label">URL:</span><span class="r"><input id="site_url"
type="text" name="site[' + new_count + ']"/></span></li><li><span
class="field_label">Title:</span><span class="r"><span
class="r1"><input id="site_title" type="text" name="site[' + new_count
+ '][title]"/></span><span class="r2">Tags: <input id="site_tag_list"
type="text" name="site[' + new_count + '][tag_list]"/></span></span></
li><li><span class="field_label">Description:</span><span
class="r"><input type="text" id="site_description" name="site[' +
new_count + '][description]"><span class="controls" id="controls' +
new_count + '"></span></span></li>';
        saved_values = Form.getElements('ajax_submit_form')
        $('new_link_fields').innerHTML += new_fields
        if (new_count > 1) {
                // Restore saved values
                for (i in saved_values) {
                        e = saved_values
                        if (e.value && e.type !='submit') {
                                $('ajax_submit_form').elements[e.name].value = e.value
                        }
                }

                old_count = new_count - 1;
                $('controls' + old_count).innerHTML = "";
                $('in_place_create_submit_button').value = "Add links";
        }
        $('controls' + new_count).innerHTML = $('controls_source').innerHTML;

}


Well assuming you didn't have the forms packed into the javascript
code:

<form id="myForm" action="..." method="...">
<input type="button" onclick="addInput();"/>
...
</form>

The the javascript:

function addInput() {
var form = document.getElementById("myForm");
var newInput = document.createElement("input");
newInput.type = "text";
var newId = "input" + form.elements.length;
newInput.id = newId;
newInput.name = newId;
form.appendChild(newInput);
}

This will create new input elements with name and ids of the type
"inputX" with each new input field being one index larger than the
previous.

HTH
[/QUOTE]
 
J

J Y

I'm writing a Rails app that uses some Javascript to allow users to
click a button to add more input fields to the page. I have the code
working, but it's very unelegant, with the HTML forms packed into the
Javascript code.
I don't want to do any server-side stuff for something this simple.
I'd like to be able to put most of the HTML somewhere in a hidden div,
but can't think of a way to make that work, since I need to increment
the index of the "name" field for each new input field.
What is the best practice for doing this? Surely not the way I have
done it.
A snippet of my code is below.
function add_new_link_fields(new_count){
new_fields = '<li><span class="newlink_label">New link:</span><span
class="field_label">URL:</span><span class="r"><input id="site_url"
type="text" name="site[' + new_count + ']"/></span></li><li><span
class="field_label">Title:</span><span class="r"><span
class="r1"><input id="site_title" type="text" name="site[' + new_count
+ '][title]"/></span><span class="r2">Tags: <input id="site_tag_list"
type="text" name="site[' + new_count + '][tag_list]"/></span></span></
li><li><span class="field_label">Description:</span><span
class="r"><input type="text" id="site_description" name="site[' +
new_count + '][description]"><span class="controls" id="controls' +
new_count + '"></span></span></li>';
saved_values = Form.getElements('ajax_submit_form')
$('new_link_fields').innerHTML += new_fields
if (new_count > 1) {
// Restore saved values
for (i in saved_values) {
e = saved_values
if (e.value && e.type != 'submit') {
$('ajax_submit_form').elements[e.name].value = e.value
}
}

old_count = new_count - 1;
$('controls' + old_count).innerHTML = "";
$('in_place_create_submit_button').value = "Add links";
}
$('controls' + new_count).innerHTML = $('controls_source').innerHTML;

Well assuming you didn't have the forms packed into the javascript
code:

<form id="myForm" action="..." method="...">
<input type="button" onclick="addInput();"/>
...
</form>

The the javascript:

function addInput() {
var form = document.getElementById("myForm");
var newInput = document.createElement("input");
newInput.type = "text";
var newId = "input" + form.elements.length;
newInput.id = newId;
newInput.name = newId;
form.appendChild(newInput);

}

This will create new input elements with name and ids of the type
"inputX" with each new input field being one index larger than the
previous.

HTH


Thank you! This is exactly what I was looking for... I have been
programming in Basic, C, PHP, and Rails for close to 10 years now, but
Javascript is still such a mystery to me. Do you have any sites to
recommend to me for a crash tutorial in Javascript? I see so many
pages out there that are more focused on quick copy/paste scripts for
script kiddies, not programmers.

Also, your example makes perfect sense to me, but my form is quite a
bit more complicated. How would I go about incrementing the index on
a form of this size? Ideally, I'd like to keep the styled form hidden
in HTML and then only copy/edit its properties in Javascript to keep
separation between presentation and logic, but I'm having trouble
figuring out how to navigate the DOM to edit the nodes nested so deep.

<span id="form_source" style="visibility: hidden; position:
absolute;">
<li>
<span class="newlink_label">New link:</span>
<span class="field_label">URL:</span>
<span class="r">
<input id="site_url" type="text" name="site[0][url]" />
</span>
</li>
<li>
<span class="field_label">Title:</span>
<span class="r">
<span class="r1">
<input id="site_title" type="text" name="site[0][title]" />
</span>
<span class="r2">Tags:
<input id="site_tag_list" type="text" name="site[0][tag_list]" />
</span>
</span>
</li>
<li>
<span class="field_label">Description:</span>
<span class="r">
<input type="text" id="site_description" name="site[0]
[description]" />
<span class="controls" id="controls0"></span>
</span>
</li>
</span>

JY
[/QUOTE][/QUOTE]
 
P

pr

J said:
I'm writing a Rails app that uses some Javascript to allow users to
click a button to add more input fields to the page. I have the code
working, but it's very unelegant, with the HTML forms packed into the
Javascript code.
[...]
<form id="myForm" action="..." method="...">
<input type="button" onclick="addInput();"/>
...
</form>

The the javascript:

function addInput() {
var form = document.getElementById("myForm");
var newInput = document.createElement("input");
newInput.type = "text";
var newId = "input" + form.elements.length;
newInput.id = newId;
newInput.name = newId;
form.appendChild(newInput);

}
[...]
Thank you! This is exactly what I was looking for... I have been
programming in Basic, C, PHP, and Rails for close to 10 years now, but
Javascript is still such a mystery to me. Do you have any sites to
recommend to me for a crash tutorial in Javascript? I see so many
pages out there that are more focused on quick copy/paste scripts for
script kiddies, not programmers.

Yes. And those sites tend to contain some very outdated code too. MDC is
but do hang around this said:
Also, your example makes perfect sense to me, but my form is quite a
bit more complicated. How would I go about incrementing the index on
a form of this size? Ideally, I'd like to keep the styled form hidden
in HTML and then only copy/edit its properties in Javascript to keep
separation between presentation and logic, but I'm having trouble
figuring out how to navigate the DOM to edit the nodes nested so deep.
[...]

Here's one way of doing it. This script removes and stores an HTML div
containing your fields, placing it in an object. The object creates a
reference to any nodes that will require updating later. The object's
insert() method modifies these nodes using a fresh index number and
appends a clone of the original div to the container that once held it.

It is an efficient choice because
a. it only has to navigate once to the nodes it must update each time
b. cloneNode() is a heap quicker than createElement().

........................

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head><title>inserting html blocks</title>
<script type="text/javascript">
var fields;

function HTMLBlock(el) {
var instance = 1, elementNames = [], i, item, container;

/* remove source element */
container = el.parentNode;
container.removeChild(el);

/* cache input elements' name attributes */
for (i = 0; item =
el.getElementsByTagName("input").item(i); i++) {
elementNames = item.getAttributeNode("name");
}

/* method to modify and insert a clone of the original element */
this.insert = function () {
for (var i = elementNames.length; i--; ) {
/* replace digits with instance # */
elementNames.nodeValue =
elementNames.nodeValue.replace(/\d+/, instance);
}
instance++;
container.appendChild(el.cloneNode(true));
};
}

function createHTMLBlock(id) {
var d = document, el;

/* test browser supports the methods we'll be using */
if (d.getElementById && (el = d.getElementById(id)) &&
el.getElementsByTagName && el.cloneNode &&
el.getAttributeNode) {
/* ... etc. */
return new HTMLBlock(el); // yes
}
return null; // no
}

function addHTML() {
if (fields) {
fields.insert();
}
}
</script>
</head>
<body>
<p>[content]</p>
<p><input type="button" onclick="addHTML()"
value="Add Fields">
</p>
<div id="new_link_fields">
<div id="form_source">
<!-- span would be illegal for this purpose -->
<ul> <!-- don't forget one of these -->
<li>
<span class="newlink_label">New link:</span>
<span class="field_label">URL:</span>
<span class="r">
<!-- life would be easier if you ditched the array-style
name attributes and used a suffix. I've left them
for now -->
<input type="text" name="site[0]" />
</span>
</li>
<li>
<span class="field_label">Title:</span>
<span class="r">
<span class="r1">
<!-- mostly you don't need ids _and_ names, so I've
removed ids -->
<input type="text" name="site[0][title]" />
</span>
<span class="r2">Tags:
<input type="text" name="site[0][tag_list]" />
</span>
</span>
</li>
<li>
<span class="field_label">Description:</span>
<span class="r">
<input type="text" name="site[0][description]" />
<span class="controls"></span>
</span>
</li>
</ul>
</div>
</div>
<script type="text/javascript">
/* remove the HTML and set up the object down here, before
anything's displayed */
fields = createHTMLBlock("form_source");
</script>
</body>
</html>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top