2

I am trying to make an invoice where in product i have used autocomplete to fetch the product name and price from the database.

It's coming easily for the first row, but for the second row it's not working at all.

index.php

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script src="js/jquery-1.10.2.min.js"></script>
<script src="js/jquery-ui-1.10.4.custom.min.js" type="text/livescript"></script>
<link rel="stylesheet" href="syle/style.css" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"   type="text/javascript"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.1/jquery-ui.min.js" type="text/javascript"></script>
 <script type="text/javascript" src="js/main.js"></script>
<title>Untitled Document</title>
  <script>
  $(document).ready(function(){
var ac_config = {
    source: "autosuggest.php",
    select: function(event, ui){
        $(".menu_name").val(ui.item.menu_name);
        $(".menu_code").val(ui.item.menu_code);
        $(".menu_price").val(ui.item.menu_price);

        },
        minLength:1
        };
        $(".street").autocomplete(ac_config);
});

</script>
</head>

<body>
<form action="action.php" method="POST">

<table>
<tr>
<td>Invoice Number</td>
<td><input type="text" name="inv_no" id="inv_no" /></td>
</tr>
<tr>
<td>Invoice Date </td>
<td><input type="date" name="inv_date" id="inv_date" /></td>
</tr>
</table>

<table border="1" style="border-collapse:collapse">
<thead>
<tr>
<th>No</th>
<th>Product Name</th>
<th>Quantity</th>
<th>Price</th>
<th>Amount</th>
</tr>
</thead>
<tbody id="inv_detail">
<tr>
<th><b class="no">1</b></th>
<td><input type="text" class="street" class="menu_name"  name="p_name[]"  /></td>
<td><input type="text" name="qty[]" class="qty" /></td>
<td><input type="text" name="price[]" class="menu_price"  /></td>
<td align="right"><b class="amt"> </b></td>

</tr>
</tbody>
<tfoot>
<th colspan="6"><b class="total" value="add">0</b></th>
</tfoot>

</table>

</form>
<input type="button" id="click"  value="add"/>
</body>
</html>
<script type="text/javascript">
$.datepicker.setDefaults({
    changeMonth:true,
    changeYear:true,
    dateFormat:'yy/mm//dd'

    });
    $(function(){

    $('#click').click(function(){
       addnewrow();

    });

    $('#inv_detail').delegate('.p_name','change',function(){
        var p_name = $('.p_name:last').val();
        if(p_name !='')
        {
            addnewrow();
            }
            if($(this).val()== '' && $('.p_name').length > 1 && p_name == '')
            {
                $('.p_name:last').parent().parent().remove();   
                total();
            }

        });

        $('#inv_detail').delegate('.qty,.menu_price',function(){
            var tr = $(this).parent().parent();
            var qty = tr.find('.qty').val()-0;
            var menu_price = tr.find('.menu_price').val()-0;
            var amt = qty * menu_price;
            tr.find('.amt').html(amt);
            total();
            });

    $('input[type=date]').datepicker(); 
    $('body').delegate('input[type=date]',click,function(e)
    {
        $(this).datepicker();

        });



        function addnewrow()
        {
            var n = ($('#inv_detail tr').length-0)+1;
            var row ='<tr>'+
            '<th><b class="no">'+ n +'</b></th>'+   
            '<td><input type="text" name="p_name[]" class="menu_name"/></td>'+  
            '<td><input type="text" name="qty[]" class="qty"/></td>'+
            '<td><input type="text" name="price[]" class="menu_price"/></td>'+
            '<td allign="right"><b class="amt"></b></td>'+
            '</tr>';
            $('#inv_detail').append(row);
            }


    });
    function total(){

             var gg=0;
             $('.amt').each(function(i,el){
                 var amt = $(this).html()-0;
                 gg += amt;

            });
        $('.total').html(gg);
        }
</script>

action.php

<?php

$cn = mysql_connect('localhost','root','');
mysql_select_db('phpinvoice',$cn);
//if(isset($_post['submit']))
//{
    echo $sql="INSERT INTO inv (inv_no,inv_date)VALUES('{$_POST['inv_no']}','{$_POST['inv_date']}')";

$query=mysql_query($sql);
$id = mysql_insert_id();
$_p_name =  $_POST['p_name'];
$_qty =  $_POST['qty'];
$_price =  $_POST['price'];

for($i = 0;$i < count($_p_name);$i++)
{
    echo $sql1="INSERT INTO inv_detail SET
 inv_id='{$id}',
 p_name='$_p_name[$i]',
 qty='$_qty[$i]',
 price='$_price[$i]',



 ";
 $qyer=mysql_query($sql1);
header('Location:http://www.pingbd.com');
}


//}


?>   
Bas Peeters
  • 3,269
  • 4
  • 33
  • 49
  • a better description of your problems would help. Second row of what? What is happening, errros thrown etc. Not sure why you have posted insert db code either when you say problems are with autocomplete – charlietfl Dec 23 '14 at 06:28
  • when i click Add more second row appear... and auto complete is not working in there. –  Dec 23 '14 at 06:43
  • OH, I didn't even see all the code at bottom. You have to intialize autocomplete for new elements after you add them to the DOM. When the code is run on page load, it will only include elements that exist at that time – charlietfl Dec 23 '14 at 06:45
  • function addnewrow() { var n = ($('#inv_detail tr').length-0)+1; var row =''+ ''+ n +''+ ''+ ''+ ''+ ''+ ''; $('#inv_detail').append(row); } }); I have actually added my autocomplete classes in here... here new row is generated.Still no resoponse. :/ –  Dec 23 '14 at 06:53
  • yes but you have to call something like `$('#inv_detail tr:last .street').autocomplete(/* options*/)` after you instert the new row – charlietfl Dec 23 '14 at 07:00
  • can you please show me an example??i am very much new to this and i am lost... :'( –  Dec 23 '14 at 07:29
  • in add new row code, try what i gave you right after `$('#inv_detail').append(row);` – charlietfl Dec 23 '14 at 07:30
  • $('#inv_detail').append(row); } $('#inv_detail tr:last .street').autocomplete(); What do i have write in .autocomplete(In this field??) –  Dec 23 '14 at 07:36
  • if you expose `ac_config` can use that but will have to isolate all of the updates to only look in same row as autocomplete – charlietfl Dec 23 '14 at 07:39
  • I couldn't solve this problem :( –  Dec 23 '14 at 09:03

1 Answers1

0

Javascript and therefor JQuery make use of event handlers. For the browser to know which function to execute on any user action you want to handle, you need to bind an event handler.

The binding of events in the case of JQuery, so also in your case, is done when the javascript is executed, in this case at runtime. Any items added after the initial event binding wont have and event handler attached to them, and will therefor never execute a function.

To fix this, you need to add the same event handlers to any new element you add to your html, from which you want to run a function.

Example 1 (jsfiddle(DOT)net/jLrcx2q6/):

<button class="button">Show alert</button>

$(document).ready(function(){
    $(".button").click(function(){
        alert("test");
    });
});   

In this example (Example 1) when the page loads a click event is "binded" to the button, so when a user clicks it an alert pops up with the text "test".

Example 2 (http://jsfiddle.net/ceney0jg/):

<div id="example-wrapper">
    <button class="button">Show alert</button>
</div> 

$(document).ready(function(){
    $(".button").click(function(){
        alert("test");
        $("#example-wrapper").append('<button class="button">Show alert</button>');
    });
});  

In this example, when a user presses the button, again a popup will be shown with the text "test". However, what also happens is a new button will be added to the div (example-wrapper). After the button is added no event handler is "binded", so nothing will happen when the user presses the button.

Example 3 - The solution (jsfiddle.net/p8q4mfmv/):

<div id="example-wrapper">
    <button class="button">Show alert</button>
</div> 

$(document).ready(function(){
    $(".button").click(function(){
        addButton()
    });
}); 

function addButton()
{
     alert("test");
     $("#example-wrapper").append('<button class="button">Show alert</button>');   

     $(".button").click(function(){
        addButton()
     });
}

In your code, you have a function addnewrow(). This function adds a new table row. When your page is loaded,

$('#inv_detail').delegate('.p_name','change',function(){ 

adds an event handler to p_name. However, after the function addnewrow() is executed, a new table row is added, but the above event handler is never bound to the new element. Therefor the browser wont execute ANY code that you would want to be executed.

The solution would be to bind an event handler, for example like this:

function addnewrow()
{
    var n = ($('#inv_detail tr').length-0)+1;
    var row ='<tr>'+
    '<th><b class="no">'+ n +'</b></th>'+   
    '<td><input type="text" name="p_name[]" class="menu_name"/></td>'+  
    '<td><input type="text" name="qty[]" class="qty"/></td>'+
    '<td><input type="text" name="price[]" class="menu_price"/></td>'+
    '<td allign="right"><b class="amt"></b></td>'+
    '</tr>';
    $('#inv_detail').append(row);

    $('#inv_detail').delegate('.p_name','change',function(){
    var p_name = $('.p_name:last').val();
    if(p_name !='')
    {
        addnewrow();
        }
        if($(this).val()== '' && $('.p_name').length > 1 && p_name == '')
        {
            $('.p_name:last').parent().parent().remove();   
            total();
        }

    });

    $('#inv_detail').delegate('.qty,.menu_price',function(){
        var tr = $(this).parent().parent();
        var qty = tr.find('.qty').val()-0;
        var menu_price = tr.find('.menu_price').val()-0;
        var amt = qty * menu_price;
        tr.find('.amt').html(amt);
        total();
    });
}

This isn't very nice code, but I think it would work. You are better of using javascript files instead of inline javascript to make your code a bit more readable and seperate functionality from your view.

Also when writing software, you should always try to make functions do as little things as possible. A function in the best case scenario would only have 1 task.

To understand this a bit better, i suggest reading http://courses.cs.washington.edu/courses/cse403/96sp/coupling-cohesion.html

qvotaxon
  • 370
  • 5
  • 16
  • function addnewrow() { var n = ($('#inv_detail tr').length-0)+1; var row =''+ ''+ n +''+ ''+ ''+ ''+ ''+ ''; $('#inv_detail').append(row); } }); $(document).ready(function(){ $("#inv_detail").click(function(){ addnewrow(); }); not even close.. :'( –  Dec 23 '14 at 10:46
  • Please help us help you. What exactly did you do and what went wrong? Did you understand my examples? Your reply just contains a lot of code but no explanation. I will edit my answer, and hope i can help you further. – qvotaxon Dec 23 '14 at 14:49