I recently had to do this for a project. Here's the code. Modify for your use.
<table cellpadding="0" cellspacing="0" width="100%">
<thead>
<tr id="table_buttons">
<td width="45px"> </td>
<th width="40px" align="left">Item #</th>
<th align="left" style="padding:0">Item Name</th>
<th align="left" style="padding:0">Quantity</th>
<th align="left">Cost</th>
<th align="left">Extended Cost</th>
<th align="left" style="padding:0">Price</th>
<th align="left">Extended Price</th>
<th align="left" width="55px">Margin</th>
</tr>
</thead>
<tbody>
<tr id="copy_this_row" style="display:none;" number="0">
<td>
<a href="#" class="row_up"><img src="<?php echo url::base(FALSE); ?>media/images/up_arrow.png" style="vertical-align:middle" /></a>
<a href="#" class="row_down"><img src="<?php echo url::base(FALSE); ?>media/images/down_arrow.png" style="vertical-align:middle" /></a><br /><br />
<a href="#" class="row_delete"><img src="<?php echo url::base(FALSE); ?>media/images/trash.png" style="vertical-align:middle" /></a>
</td>
<td field="item_number"></td>
<td style="padding:0"><input type="text" class="text small" style="width:150px;" name="item[]" autocomplete="off" class="item_name" /><textarea name="description[]" style="width:200px !important; height:50px"></textarea><input type="hidden" name="item_id[]" /></td>
<td style="padding:0"><input type="text" class="text small" style="width:50px;" name="qty[]" value="1" autocomplete="off" /></td>
<td field="cost"></td>
<td field="extended_cost"></td>
<td style="padding:0"><input type="text" class="text small" style="width:50px;" name="price[]" autocomplete="off" /></td>
<td field="extended_price"></td>
<td field="margin"></td>
</tr>
<tr id="copy_before_this">
<td colspan="3">
<div class="tableactions">
<input type="button" class="submit tiny" value="Add Line Item" id="add_row" /> <!-- <input type="button" class="submit tiny" value="Add Product" /> <input type="button" class="submit tiny" value="Add Service" />-->
</div><!-- .tableactions ends --></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody></table>
jQuery:
$('.row_up').bind('click', function(){
$(this).parent().parent().insertBefore($(this).parent().parent().prev());
check_row_buttons();
return false;
});
$('.row_down').bind('click', function(){
$(this).parent().parent().insertAfter($(this).parent().parent().next());
check_row_buttons();
return false;
});
$('.row_delete').bind('click', function(){
$(this).parent().parent().fadeOut(250, function(){
$(this).remove();
check_row_buttons();
update_totals();
});
return false;
});
function new_row(item_name,item_id,description,quantity,price){
var insert_this = $('#copy_this_row');
var number = $('*[number]:last').attr('number');
number++;
var new_insert = insert_this.clone(true);
new_insert.removeAttr('id');
new_insert.fadeIn();
new_insert.insertBefore('#copy_before_this').attr('number',number);
check_row_buttons();
auto_comp();
if(item_name){
$('tr[number='+number+']>td>input[name=item\\[\\]]').val(item_name);
item_info(item_id,number);
}
if(description){
$('tr[number='+number+']>td>textarea[name=description\\[\\]]').val(description);
}
if(quantity){
$('tr[number='+number+']>td>input[name=qty\\[\\]]').val(quantity);
}
if(price){
$('tr[number='+number+']>td>input[name=price\\[\\]]').val(price);
}
}
$('#add_row').bind('click', function(){
new_row();
});
function check_row_buttons(){
$('.row_up').show();
$('.row_down').show();
$('.row_delete').show();
$('.row_up:eq(1)').hide();
$('.row_down:last').hide();
if($('.row_delete').size() == 2){
$('.row_delete').hide();
}
}
check_row_buttons();
This snippit also includes the ability to add rows, which can easily be removed.
Mainly pay attention to the $('.row_up') and $('.row_down') to see how to move the rows around using jquery and an image/object with class row_up and row_down -- This concept will help you write a custom solution for your project