2

enter image description hereI am experimenting with the following .js code that adds form field dynamically to a page for me :

var i=$('table tr').length;
$(".addmore").on('click',function(){
    addNewRow();
});

$(".addmany").on('click',function(){
    addNewRow();
    addNewRow();
});

$(document).on('keypress', ".addNewRow", function(e){
    var keyCode = e.which ? e.which : e.keyCode;
    if(keyCode == 9 ) addNewRow();
});
var addNewRow = function(){
    html = '<tr>';
    html += '<td><input class="case" id="caseNo_'+i+'" type="checkbox"/></td>';
    html += '<td><input type="text" data-type="productCode" name="data[InvoiceDetail]['+i+'][product_id]" id="itemNo_'+i+'" class="form-control autocomplete_txt" autocomplete="off"></td>';
    html += '<td><input type="text" data-type="productName" name="data[InvoiceDetail]['+i+'][productName]"  id="itemName_'+i+'" class="form-control autocomplete_txt" autocomplete="off"></td>';
    html += '<td><input type="text" name="data[InvoiceDetail]['+i+'][price]" id="price_'+i+'" class="form-control changesNo" autocomplete="off" onkeypress="return IsNumeric(event);" ondrop="return false;" onpaste="return false;"></td>';

    html += '<td><input type="text" name="data[InvoiceDetail]['+i+'][quantity]" id="quantity_'+i+'" class="form-control changesNo quanyityChange" autocomplete="off" onkeypress="return IsNumeric(event);" ondrop="return false;" onpaste="return false;">';
    html += '<input type="hidden" id="stock_'+i+'"/>';
    html += '<input type="hidden" id="stockMaintainer_'+i+'" name="data[InvoiceDetail]['+i+'][stockMaintainer]" />';
    html += '<input type="hidden" id="previousQuantity_'+i+'"/>';
    html += '<input type="hidden" id="invoiceDetailId_'+i+'"/>';
    html += '</td>';
    html += '<td><input type="text" id="total_'+i+'" class="form-control totalLinePrice addNewRow" autocomplete="off" onkeypress="return IsNumeric(event);" ondrop="return false;" onpaste="return false;"></td>';
    html += '<td><input type="checkbox" data-type="staged" name="data[InvoiceDetail]['+i+'][staged]"  id="staged_'+i+'" class="form-control autocomplete_txt" autocomplete="off"></td>';
    html += '</tr>';
    $('table').append(html);

    $('#caseNo_'+i).focus();

    i++;
}

It works perfectly, and I am able to add product lines in as needed.

HOWEVER, I would like to be able to add rows IN BETWEEN existing rows.
Does anyone know how I would do that?

Right now the code executes as below :

Apples
Bananas
Oranges

Add Row(button)

Apples
Bananas
Oranges
New Item

I want it to work like this when needed :

Apples
New Item
Bananas
Oranges

Possibly via a icon next to each row, that you click on to add a row above or below said item.

Sample of form :

<?php if(isset($invoice['InvoiceDetail'])&&!empty($invoice['InvoiceDetail'])){?>
                                    <?php foreach ( $invoice['InvoiceDetail'] as $key=>$item){?>
                                        <tr>
                                            <td> <input class="case" type="checkbox"/> </td>
                                            <td><input value="<?php echo isset($item['product_id']) ? $item['product_id']: ''; ?>" type="text" data-type="productCode" name="data[InvoiceDetail][<?php echo $key;?>][product_id]" id="itemNo_<?php echo $key+1?>" class="form-control autocomplete_txt" autocomplete="off"></td>
                                            <td><input value="<?php echo isset($item['productName']) ? $item['productName']: ''; ?>" type="text" data-type="productName" name="data[InvoiceDetail][<?php echo $key;?>][productName]" id="itemName_<?php echo $key+1?>" class="form-control autocomplete_txt" autocomplete="off"></td>
                                            <td><input value="<?php echo isset($item['price']) ? $item['price']: ''; ?>" type="number" name="data[InvoiceDetail][<?php echo $key;?>][price]" id="price_<?php echo $key+1?>" class="form-control changesNo" autocomplete="off" onkeypress="return IsNumeric(event);" ondrop="return false;" onpaste="return false;"></td>
                                            <td>
                                                <input value="<?php echo isset($item['quantity']) ? $item['quantity']: ''; ?>" type="number" name="data[InvoiceDetail][<?php echo $key;?>][quantity]" id="quantity_<?php echo $key+1?>" class="form-control changesNo quanyityChange" autocomplete="off" onkeypress="return IsNumeric(event);" ondrop="return false;" onpaste="return false;">
                                                <input value="<?php echo isset($item['quantityInStock']) ? $item['quantityInStock']: ''; ?>"  type="hidden" id="stock_<?php echo $key+1?>" autocomplete="off"/>
                                                <input value="0" type="hidden" id="stockMaintainer_<?php echo $key+1?>" name="data[InvoiceDetail][<?php echo $key;?>][stockMaintainer]" autocomplete="off"/>
                                                <input value="<?php echo isset($item['quantity']) ? $item['quantity']: ''; ?>" type="hidden" id="previousQuantity_<?php echo $key+1?>" autocomplete="off"/>
                                                <input value="<?php echo isset($item['id']) ? $item['id']: ''; ?>" type="hidden" id="invoiceDetailId_<?php echo $key+1?>" autocomplete="off"/>
                                            </td>
                                            <td><input value="<?php echo $item['price']*$item['quantity']; ?>" type="number" id="total_<?php echo $key+1?>" class="form-control totalLinePrice" autocomplete="off" onkeypress="return IsNumeric(event);" ondrop="return false;" onpaste="return false;"></td>
                                            <td><input type="checkbox" <?php if(isset($item['staged']) && $item['staged'] == 1) echo "checked=\"checked\""?> data-type="checkbox" name="data[InvoiceDetail][<?php echo $key;?>][staged]" id="staged_<?php echo $key+1?>" class="form-control autocomplete_txt" autocomplete="off"></td>

                                        </tr>
                                    <?php } ?>
                                <?php }else{?>
                                    <tr>
                                        <td><input class="case" type="checkbox"/></td>
                                        <td><input type="text" data-type="productCode" name="data[InvoiceDetail][0][product_id]" id="itemNo_1" class="form-control autocomplete_txt" autocomplete="off"></td>
                                        <td><input type="text" data-type="productName" name="data[InvoiceDetail][0][productName]" id="itemName_1" class="form-control autocomplete_txt" autocomplete="off"></td>
                                        <td><input type="number" name="data[InvoiceDetail][0][price]" id="price_1" class="form-control changesNo" autocomplete="off" onkeypress="return IsNumeric(event);" ondrop="return false;" onpaste="return false;"></td>
                                        <td>
                                            <input type="number" name="data[InvoiceDetail][0][quantity]" id="quantity_1" class="form-control changesNo quanyityChange" autocomplete="off" onkeypress="return IsNumeric(event);" ondrop="return false;" onpaste="return false;">
                                            <input type="hidden" id="stock_1" autocomplete="off"/>
                                            <input type="hidden" name="data[InvoiceDetail][0][stockMaintainer]" id="stockMaintainer_1" autocomplete="off"/>
                                            <input type="hidden" id="previousQuantity_1" autocomplete="off"/>
                                            <input type="hidden" id="invoiceDetailId_1" autocomplete="off"/>
                                        </td>
                                        <td><input type="number" id="total_1" class="form-control totalLinePrice addNewRow" autocomplete="off" onkeypress="return IsNumeric(event);" ondrop="return false;" onpaste="return false;"></td>
                                        <td><input value="1" type="checkbox" name="data[InvoiceDetail][0][staged]" id="staged_1" class="form-control autocomplete_txt" autocomplete="off"></td>                                 
                                        </tr>
                                <?php } ?>

enter image description here

Steven
  • 687
  • 1
  • 10
  • 27
  • 1
    JQuery DOM manipulation methods include more than just `append()`, may be you can peruse the manual. – mustaccio Aug 25 '15 at 00:34
  • @mustaccio I am a semi-ok web developer that is just now adding php/sql to my list of ongoing learning skills, would you please at least point to a good source for the manual, or learning materials? – Steven Aug 25 '15 at 00:35
  • They are on the same web site from which you downloaded jQuery. – mustaccio Aug 25 '15 at 00:37
  • @mustaccio Thank you for that direction, I will take a look, and hopefully find something that will allow me to do this :) – Steven Aug 25 '15 at 00:38
  • @mustaccio I RTFM, and all I could come up with was the fact that you can append, prepend, append to, or prepend to different elements. However, I do not see how that is helpful in prepending to a dynamic variable. I am using a in the id of each insert element that allows my above code to work, I imagine that I will have to somehow prepend to the $key item in order to make it work, but am unsure as to how to go about it.... – Steven Aug 25 '15 at 00:56
  • Instead of posting php - almost always entirely irrelevant to JavaScript in the client-side - please post a representative sample of your HTML (as seen by the browser, 'view source'). – David Thomas Aug 25 '15 at 01:24
  • Tip: You can opt for using `= $something_to_echo; ?>` instead of ``. Additionally you can make a quick php helper function to check issets: `function get_value($item, $key) { return (isset($item[$key])) ? $item[$key] : ''; }` and call it with `get_value($item, 'product_id');` – amurrell Aug 25 '15 at 01:50

1 Answers1

2

You could also consider making these rows sortable (with jQueryUI) so the user can decide to change the order later if that's important.

Otherwise think about this modification concept of your code:

var addNewRow = function(element, type) {
    var html = '<tr>' // etc ....

    (type == 'after') ? element.after(html) : element.append(html);

    $('#caseNo_'+i).focus();

    i++;
}

// Where ever you're doing this now..
addNewRow($('table'), 'append');

// maybe in click rule of (I am assuming - nested) icon in your TR, use .closest('tr') to get the element.
addNewRow($(this).closest('tr'), 'after');

To preserve numerical orders something like this:

var reOrder = function() {

    var table = $('table');
    table.children('tr').each(function(){
        var tr = $(this);
        var i = table.index(tr) + 1; // because index starts at 0
        tr.attr('data-some-attribute', 'new_value_'+i);
    }
};

OP wanted even more of the jQuery to see how it might all work together...

// Define Vars

var table = $('table'); // try to make this more specific of a selector../
var addRowButton = $('#specific-button');

// This function, with missing parts "etc" added in:
var addNewRow = function(element, type) {
    var html = '<tr>' // etc ....

    // don't forget to add the "add row button" html to this also

    (type == 'after') element.after(html) : element.append(html);

    $('#caseNo_'+i).focus();

    i++;
};

// Re Order table to preserve row numbering
var reOrder = function() {
    table.children('tr').each(function(){
        var tr = $(this);
        var i = table.index(tr) + 1; // because index starts at 0

        tr.attr('data-some-attribute', 'new_value_'+i);
    }
};


// You have 1 add row button:

addRowButton.click(function(){

    // Call to addNewRow
    addNewRow(table, 'append');

});

// I assume you'll nest your buttons to add a row below in your current row..
table.find('.add-row-button').click(function(){

    // Call to add row
    addNewRow($(this).closest('tr'), 'after');

    // Call to reOrder table
    reOrder();

});
amurrell
  • 2,383
  • 22
  • 26
  • the closest tr is dynamic(sample) : How would I find the closest element that $key+1 defines, even in prior saved inputs? – Steven Aug 25 '15 at 01:19
  • Checked out the sortable code, and it is pretty nifty, however on a ui level, the viability of sorting a blank line added to the bottom of the page(of dozens and dozens of items) clicking and dragging up a couple pages will not work :( – Steven Aug 25 '15 at 01:25
  • Ok, I read your first comment and am trying to make sense of it... still.. is your issue with making the new row have the correct `i` in jQuery or is the issue when you need to save it or load the page with PHP? – amurrell Aug 25 '15 at 01:26
  • yes, the issue is making the row have the correct i in jQuery, for instance, if the user ADDS 5 rows to the html table, numbered a1, a2, a3, a4, a5, and saves the form(to the sql database), how will I in jQuery load those values a1-a5, as well as be able to add a NEW a3 to take the place of the old one, and then reorder all the existing a.#'s to where they need to be.... – Steven Aug 25 '15 at 01:29
  • I changed the picture to reflect the row changes, and the problem with working with dynamic rows. – Steven Aug 25 '15 at 01:33
  • Ah so you need to preserve numerical order of the rows? A lot of these questions are answered by how you design your product. If you must save those rows - you may want to think - do you need to reload your table after a save with ajax? how are you saving now? is that with ajax? if so, will you have a way to "update" a row? – amurrell Aug 25 '15 at 01:36
  • Basically if you decide that when a user adds a new row in the middle of them, to save... it's not that hard to use jQuery to determine which point in its index the row is in and change your attributes accordingly. – amurrell Aug 25 '15 at 01:38
  • Thats what I am looking for to do, I just do not know how to edit the jQuery accordingly. I looked at the manual, and all I could find out was how to append or prepend to table elements, not how to append or prepend to the dynamic values stored in the existing rows... – Steven Aug 25 '15 at 01:40
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/87845/discussion-between-steven-and-amurrell). – Steven Aug 25 '15 at 01:46