Reputation: 2500
The title isn't very descriptive but I couldn't find a better one. Feel free to edit it.
Basically what I'm looking for is the best way to do the following:
When the user clicks "Add New Item", a new row is added with an indentical text box and drop down as above. The options I can think of are the following:
<script language="html">
tags to define the templates).What do you suggest? I'm not completely satisfied with any of the above solutions.
Upvotes: 2
Views: 3441
Reputation: 253318
While I realise you already have an accepted answer, I thought I'd offer a plain JavaScript means of achieving the same:
function closest(el, tag) {
if (!el || !tag) {
return false;
}
else {
var curTag = el.tagName.toLowerCase();
return curTag == tag.toLowerCase() && curTag !== 'body' ? el : closest(el.parentNode, tag);
}
}
function addRow(el) {
if (!el) {
return false;
}
else {
var tr = closest(el, 'tr').previousElementSibling,
newRow = tr.cloneNode(true);
tr.parentNode.insertBefore(newRow, tr.nextSibling);
}
}
document.getElementById('add').onclick = function() {
addRow(this);
}
Revised the above a little, to add a simple shim to cope with those browsers that don't implement previousElementSibling
:
function closest(el, tag) {
if (!el || !tag) {
return false;
}
else {
var curTag = el.tagName.toLowerCase();
return curTag == tag.toLowerCase() && curTag !== 'body' ? el : closest(el.parentNode, tag);
}
}
function prevElementSiblingShim(el) {
if (!el) {
return false;
}
else {
var prevSibling = el.previousSibling;
return prevSibling.nodeType == 1 ? prevSibling : prevElementSiblingShim(prevSibling);
}
}
function addRow(el) {
if (!el) {
return false;
}
else {
var par = closest(el, 'tr'),
tr = par.previousElementSibling || prevElementSiblingShim(par),
newRow = tr.cloneNode(true);
tr.parentNode.insertBefore(newRow, tr.nextSibling);
}
}
document.getElementById('add').onclick = function() {
addRow(this);
}
References:
cloneNode()
.insertBefore
.nextSibling
.nodeType
.parentNode
.previousElementSibling
Compatibility.previousSibling
.tagName
.toLowerCase()
.Upvotes: 1
Reputation: 101604
Assuming the super-simple approach and that your format is in a table:
<table>
<tr>
<td><input type="text" name="item_name" placeholder="item name" /></td>
<td><select name="item_type"><option value="" selected="selected">Type</option></select></td>
</tr>
<tr>
<td><input type="text" name="item_name" placeholder="item name" /></td>
<td><select name="item_type"><option value="" selected="selected">Type</option></select></td>
</tr>
<tr>
<td colspan="2" id="add">+ Add new item</td>
</tr>
</table>
You can use the following:
$('#add').on('click',function(e){
var $this = $(this);
var $newRow = $this.closest('table').find('tr:first').clone();
$newRow.find(':input').val('');
$newRow.insertBefore($this.parent());
});
Broken down:
$this.closest('table')
).clone()
).find(':input').val('')
)$newRow.insertBefore(...)
)You can also take the template approach, but that's really up to you and how much control you'd like over the output.
Upvotes: 1
Reputation: 24086
If you're already using a framework like jquery or sencha on your page, you might as well make use of it.
Otherwise, i'd keep it as simple as possible. This does't look like a very important core functionality, so don't create something that requires extra https requests or even entire libraries to be loaded. Cloning or generating the html might not look elegant, but it'll be:
Don't create something that's overkill for somerhing as trivial as this.
Upvotes: 1
Reputation: 114367
Inserting HTML from a string into the DOM is the most efficient way. Unless you're inserting hundreds at once, it doesn't really matter.
Upvotes: 0