2

my question is how can i clone , lets say a calculater element keeping all the bindings to events like add , mul , sub , etc working in all the other duplicates. i tried so many ways and nothing works.

            $("#newCalc").on( 'click' , function(){
            $('#calcObj').clone(true , true).insertAfter('#calcObj');});

the last one i left for now. but when i am adding in the new calc it adds in the old one , same with all the other clones.

this is my code(its my first time programming js so forgive me for the bad coding):

     
    $("#newCalc").on( 'click' , function(){
    new calculator();});
    
     
    /* Bind event with the corresponding functionality. */
    $("#clear").on('click', calculate.clear);
    $("#add").on('click', calculate.add);
    $("#multiply").on('click', calculate.mul);
    $("#subtract").on('click' , calculate.sub);
    $("#divide").on('click' , calculate.div);
    $("#settings").on('click', calculate.settings);
    $(".num").on('click', function(){ 
     $("#input").val(this.value);
    });
    $("#input").on('keyup', validateNumber);
    });
 
 
//var calculate = new calculator();

/* Let's only digits, 0-9, to be written on input box. */
function validateNumber() {

 if (isNaN($("#input").val())) {
    alert("Only numbers!!! try again :)");
    $("#input").val("");
 }
}


function calculator(){
 
 var empty = '';
 var order = counter;
 var el3_calc = "" + 
 '<table id="calcObj">' +
 '<th colspan="3">' +
 '<h1 id="calcHeadline"><b>Calculator</b></h1>' +
 '</th>' +
 '<tr>' +
 '<td colspan="3">'+
 '<input type="text" id = "input" class="calcIO" value="">'+
 '<input type="button" id ="add" value="+">'+
 '<input type="button" id ="multiply" value="x">' +
 '<input type="button" id ="subtract" value="-">' +
 '<input type="button" id ="divide" value="/">' +
 '<input type="text" id="result" readOnly="true" value="" class="calcIO"><br></td>' +
 '</tr>' +
 '<tr>'+
 '<td><input type="button" class ="num" value="1"></td>'+
 '<td><input type="button" class ="num" value="2"></td>'+
 '<td><input type="button" class ="num" value="3"><br></td>'+
 '</tr>'+
 '<tr>'+
 '<td><input type="button" class ="num" value="4"></td>'+
 '<td><input type="button" class ="num" value="5"></td>'+
 '<td><input type="button" class ="num" value="6"><br></td>'+
 '</tr>'+
 '<tr>'+
 '<td><input type="button" class ="num" value="7"></td>' +
 '<td><input type="button" class ="num" value="8"></td>' +
 '<td><input type="button" class ="num" value="9"><br></td>' +
 '</tr>' +
 '<tr>'+
 '<td><input type="button" id="newCalc" value = "AddCalc"></td>'+
 '<td><input type="button" class ="num" value="0"></td>'+
 '<td><input type="button" id="clear" value="Clear"></td>'+
 '</tr>'+
 '</table>';
 
 $("#third").append(el3_calc);



 counter += 1;
 
 this.add = function(){
  if($("#input").val() != empty && $("#result").val() == empty){
   
   $("#result").val($("#input").val());
  }
  else{
   $("#result").val(parseFloat($("#input").val()) + parseFloat($("#result").val()));
  }
  
  $("#input").val(empty);
 }
 
 this.mul = function() {
  if($("#input").val() != empty && $("#result").val() == empty){
   
   $("#result").val($("#input").val());
  }
  else{
   $("#result").val(parseFloat($("#input").val()) * parseFloat($("#result").val()));
  }
  
  $("#input").val(empty);
 }
 
 this.div = function(){
  if($("#input").val() != empty && $("#result").val() == empty){
   
  $("#result").val($("#input").val());
  }
  else{
   $("#result").val(parseFloat($("#result").val()) / parseFloat($("#input").val()));
  }
  
  $("#input").val(empty);
 }
 
 this.sub = function(){
  if($("#input").val() != empty && $("#result").val() == empty){
   
   $("#result").val($("#input").val());
  }
  else{
   $("#result").val(parseFloat($("#result").val()) - parseFloat($("#input").val()));
  }
  
  $("#input").val(empty);
 }

 this.clear = function() {
  $("#result").val(empty);
  $("#input").val(empty);
 }

}
dankor91
  • 33
  • 3

4 Answers4

0

you cant. You have to add new events as the elements are cloned, however..... If you use the $().delegate instead of on, they event handlers will be added automatically. Instead of using ids, use class names as your selector.

http://api.jquery.com/delegate/

Bindrid
  • 3,655
  • 2
  • 17
  • 18
  • hi thanks , i tried with delegate too but no success , can you give me an example of how would u implement it? – dankor91 Dec 12 '15 at 02:33
0

Put the event handlers this way, which will work for any of the clones (even if you create new element with id newCalc without cloning.

$(document).on( 'click', "#newCalc" , function() {

Note : Just as a recommendation, According to W3C convention, we shouldn't have multiple element with same id, Use a class instead for such purposes.

EDIT

I think you need to define the variable calculate properly. I assume you want to define it when #newCalc is clicked. So, you need to define the variable outside the function first (so that it can be accessible to other functions it is being called from) and then assign the value when the button is clicked. So it can be like this:

var calculate;
$(document).on( 'click', "#newCalc" , function() {
    calculate = new calculator();
});
0

Adjust the script links for your environment but this worked for me.

        <script src="Scripts/jquery-2.1.4.js" type="text/javascript"></script>
        <script src="Scripts/jquery-ui.js" type="text/javascript"></script>

        <script type="text/javascript">
            var counter = 1;
            $(document).ready(function(){
               $("table").delegate(".pickme", "click", function () {
                   $("tbody").append('<tr><td class="pickme">click me</td><td>Row '+(++counter) +'</td></tr>');
               });
               } );
        </script>
    </head>
    <body>

       <table>
           <tbody>
               <tr><td class="pickme">click me</td><td>Row 1:</td></tr>
           </tbody>
       </table>
    </body>
    </html>
Bindrid
  • 3,655
  • 2
  • 17
  • 18
0

Here is the complete modified one reducing your extra codes and should work. Just one important change, instead of cloning new item, get a new calculator calling the function and just use append (calculator function will return the calculator html which you should append to any div.

function calculator(){

    var empty = '';
    var order = counter;
    var el3_calc = "" + 
    '<table id="calcObj">' +
    '<th colspan="3">' +
    '<h1 id="calcHeadline"><b>Calculator</b></h1>' +
    '</th>' +
    '<tr>' +
    '<td colspan="3">'+
    '<input type="text" id = "input" class="calcIO" value="">'+
    '<input type="button" id ="add" value="+">'+
    '<input type="button" id ="multiply" value="x">' +
    '<input type="button" id ="subtract" value="-">' +
    '<input type="button" id ="divide" value="/">' +
    '<input type="text" id="result" readOnly="true" value="" class="calcIO"><br></td>' +
    '</tr>' +
    '<tr>'+
    '<td><input type="button" class ="num" value="1"></td>'+
    '<td><input type="button" class ="num" value="2"></td>'+
    '<td><input type="button" class ="num" value="3"><br></td>'+
    '</tr>'+
    '<tr>'+
    '<td><input type="button" class ="num" value="4"></td>'+
    '<td><input type="button" class ="num" value="5"></td>'+
    '<td><input type="button" class ="num" value="6"><br></td>'+
    '</tr>'+
    '<tr>'+
    '<td><input type="button" class ="num" value="7"></td>' +
    '<td><input type="button" class ="num" value="8"></td>' +
    '<td><input type="button" class ="num" value="9"><br></td>' +
    '</tr>' +
    '<tr>'+
    '<td><input type="button" id="newCalc" value = "AddCalc"></td>'+
    '<td><input type="button" class ="num" value="0"></td>'+
    '<td><input type="button" id="clear" value="Clear"></td>'+
    '</tr>'+
    '</table>';
    el3_calc = $(el3_calc);
    //$("#third").append(el3_calc); //remove this line

    counter += 1;
    var inputDiv = el3_calc.find("#input");
    var resultDiv = el3_calc.find("#result");

    this.calc = function(operator){
        var inputVal = inputDiv.val();
        var resultVal = resultDiv.val();
        if(inputVal != empty && resultVal == empty){
            resultDiv.val(inputVal);
       }
        else{
           var newVal;
           resultVal = parseFloat(resultVal);
           inputVal = parseFloat(inputVal);
           switch(operator) {
              case '+':
                newVal = resultVal +  inputVal;
                break;
              case '-':
                newVal = resultVal -  inputVal;
                break;
              case '*':
                newVal = resultVal *  inputVal;
                break;
              case '/':
                newVal = resultVal /  inputVal;
                break;
              default:
                break;
           }
           resultDiv.val(newVal);
       }

       inputDiv.val(empty);
    }

    this.clear = function() {
        inputDiv.val(empty);
        resultDiv.val(empty);
    }
    var calculate = this;
    el3_calc.find("#clear").on('click', calculate.clear);
    el3_calc.find("#add").on('click', function() {calculate.calc('+');});
    el3_calc.find("#multiply").on('click', function() {calculate.calc('*');});
    el3_calc.find("#subtract").on('click' , function() {calculate.calc('-');});
    el3_calc.find("#divide").on('click' , function() {calculate.calc('/');});
    el3_calc.find("#settings").on('click', calculate.settings);
    el3_calc.find(".num").on('click', function(){ 
         inputDiv.val(this.value);
    });
    el3_calc.find("#input").on('keyup', validateNumber);
    return el3_calc;
}

$(document).on( 'click', "#newCalc" , function() {
    mycal = new calculator();
    $('#third').append(mycal);
});
  • This is a very bad answer, never use eval unless you absolutely have to and even then, don't use it. – Mykybo Dec 13 '15 at 14:20
  • @Mykybo Can you pls explain the reason? – Tᴀʀᴇǫ Mᴀʜᴍᴏᴏᴅ Dec 13 '15 at 14:21
  • for example: http://stackoverflow.com/questions/86513/why-is-using-the-javascript-eval-function-a-bad-idea – Mykybo Dec 13 '15 at 14:23
  • @Mykybo, anyways, not a big deal, I will remove the eval real quick. Thanks. – Tᴀʀᴇǫ Mᴀʜᴍᴏᴏᴅ Dec 13 '15 at 14:24
  • 1
    hi thanks for the help , you couldnt see my code because i didn't paste all of it but considering what i pasted your answer really helped. the main issue is really i couldnt clone it and should have used this.main = $('#calcObj'+counter); and then just bind the methods this.main.find('.clear').click(function(){ that.clear();}); and so on. – dankor91 Dec 13 '15 at 14:50