4

I'm having a quite tough problem and I'm not sure how to approach it. I have a few textboxes in a row and I need to fill in these textboxes. Every time a textbox is filled, I grab the value and make an Ajax call that uses the value. The response determines whether or not that very textbox is colored red or green(using the Jquery css() function).

Now here's the problem. Let's say I have 5 textboxes in a row. Let's say I type 1-tab, 2-tab, 2-tab, 1-tab, 1-tab. All of this very fast. 1-tab, for example, means I type 1 followed by the Tab button to move to the next textbox. I realized that if I go too fast, some of the textboxes don't get updated and their colors do not change. I assumed this is due to the ajax taking some time to process.

I thought about the problem and came up with an idea that might solve the problem. That is add a delay after each Ajax call and then tab to the next. I search around S.O and found this solution. However, it's not really working for me(basically it breaks and the JS doesn't work at all).

Here's a snippet of my AJAX. I stripped it down and removed the unnecessary pieces of code.

$( ".myTextbox" ).keyup(function() {
        //Defining my variables here

        $.ajax({    
            //Perform First Ajax request

            $.ajax({   
                //Perform Second Ajax Request
            });  

        });
});

Here's the solution I tried using what I found from S.O, but it doesn't work.

var timer = null;
$( ".myTextbox" ).keyup(function() {
        clearTimeout(timer);

        timer = setTimeout(
            function(){
                .ajax({    
                //Perform First Ajax request                        
                    $.ajax({   
                        //Perform Second Ajax Request
                    });                  
                });
            }, 200);
        //Defining my variables here
});

Now, there are 2 options:

  1. My logic is wrong about delaying the tab key. Could there be some better logic to overcome my initial problem?

  2. I'm using the solution posted above wrongly.

Hope to get some constructive answers.

Thanks.

EDIT: Here's the full code, upon request.

$( ".getqty" ).keyup(function() {
    var split = this.id.split(":");
    var color = split[0];
    var size = split[1];
    var prodID = split[2];
    var $this = $(this);
    var value = $this.val();
    var stock = 0;
    var price = split[3];
    var originalProd = split[4];
    var dataStock = $this.attr("data-stock");
    if(value.length > 0){
        value = parseInt(value);
    }else{
        value = "";
    }

    $.ajax({    //create an ajax request 
        type: 'POST',
        url: 'includes/add.php',             
        dataType: 'html',   //expect html to be returned   
        data:'color='+color+'&size='+size+'&prodID='+prodID+'&qty='+value+'&originalProd='+originalProd+'&dataStock='+dataStock,     
        success: function(response){   
            if(response == "breakOut"){              
                   $this.css('background-color', '#F87171').css('border', '1px solid #B42C2C');  
                   $("#"+originalProd+"-"+color).text("Not enough in stock.").css('color', '#B42C2C');   
                   $("#"+originalProd+"-totalPrice").text("");
            }else{
                stock = response;
                if((value > 0 && value <= stock) || (value > 0 && dataStock == 'yes')){
                        $this.css('background-color', '#66CF66').css('border', '1px solid #277230');                        
                }else{
                    $this.css('background-color', '#fff').css('border', '1px solid #ccc');
                }   

                var count = 0;
                $("."+color+"-" + originalProd).each(function(){
                        if($(this).val() == 0){
                            count = count + 0;
                        }else{
                            count = count + parseFloat($(this).val(), 10);
                        }
                });

                //Single Item Total
                if(count > 0){
                    var totalPrice = (price * count).toFixed(2);
                    $("#"+originalProd+"-"+color).text(count + " - " + totalPrice.toString().replace(/\./g, ',') + " Eur").css('color', '#CCC');
                }else{
                    $("#"+originalProd+"-"+color).text("");
                }


                $.ajax({    //create an ajax request
                    type: 'POST',
                    url: 'includes/cart.php',             
                    dataType: 'html',   //expect html to be returned   
                    success: function(response){                   
                        if(response > 0){
                            $("#cart_price").text("Cart: "+response.toString().replace(/\./g, ',')+ " Eur");
                        }else{
                            $("#cart_price").text("Cart:0,00 Eur");
                        }                            
                    },
                    error:function (xhr, ajaxOptions, thrownError){
                    // alert(thrownError);
                    }
                });  
                if(pathname == 'mycart.php'){
                    location.reload();
                }                  
            }
        },
        error:function (xhr, ajaxOptions, thrownError){
         //alert(thrownError);
        }
    });
Community
  • 1
  • 1
nTuply
  • 1,364
  • 19
  • 42
  • Why don't you show us the code so we can figure out why it does not work. Sounds like maybe you have globals and each request overrides them. – epascarello Dec 29 '15 at 14:41
  • @epascarello The code is quite long. I updated it with the current code. – nTuply Dec 29 '15 at 14:46

2 Answers2

1

You should use the change event instead of keyup. From the docs:

The keyup event is sent to an element when the user releases a key on the keyboard. It can be attached to any element, but the event is only sent to the element that has the focus.

When you press tab your elements will change focus quickly and maybe the keyup event will not be fired for that input text with the right value content.

So try:

$( ".getqty" ).change(...)

Update: Since the change event just fires when the input text loses focus, you could write instead:

$( ".getqty" ).on('input', function() {
  var $this = $(this);
  var value = $this.val();

  if (value.length > 0) {
    value = parseInt(value);
  }
  else {
    value = "";
  }

  $.ajax({
    type: 'POST',
    url: 'data.txt',             
    dataType: 'text', 
    success: function(response){   
      $this.css('background-color', '#66CF66').css('border', '1px solid #277230');                        

      $.ajax({
        type: 'POST',
        url: 'data.txt',             
        dataType: 'text', 
        success: function(response){                   
          $("#cart_price").text("Cart: "+response.toString().replace(/\./g, ',')+ " Eur");                          
        },
        error:function (xhr, ajaxOptions, thrownError){
          console.log(thrownError);
        }
      });                 
    },
    error: function (xhr, ajaxOptions, thrownError){
     console.log(thrownError);
    }
  });
});

Or with pure javascript event listeners:

var elemList = document.getElementsByClassName('getqty');
for (var i = 0; i < elemList.length; i++) {
  elemList[i].addEventListener('input', function(e) {
    var $this = $(e.target);
    var value = $this.val();

    if (value.length > 0) {
      value = parseInt(value);
    }
    else {
      value = "";
    }

    $.ajax({
      type: 'POST',
      url: 'data.txt',             
      dataType: 'text', 
      success: function(response){   
        $this.css('background-color', '#66CF66').css('border', '1px solid #277230');                        

        $.ajax({
          type: 'POST',
          url: 'data.txt',             
          dataType: 'txt', 
          success: function(response){                   
            $("#cart_price").text("Cart: "+response.toString().replace(/\./g, ',')+ " Eur");                          
          },
          error:function (xhr, ajaxOptions, thrownError){
            console.log(thrownError);
          }
        });                 
      },
      error: function (xhr, ajaxOptions, thrownError){
       console.log(thrownError);
      }
    });
  });
}
Felipe T.
  • 637
  • 1
  • 8
  • 14
  • This is a great option. It actually works this way. However, the current box is not updated unless I move to the next(which is the point of `change()`). So in that case once I reach the last textbox(from my example in the OP), it won't do any changes to the textbox unless I click somewhere on the page. – nTuply Dec 29 '15 at 16:44
  • I didn't get it. The change event is fired every time the value of your input text changes. You don't need to change boxes to trigger this event. – Felipe T. Dec 29 '15 at 16:49
  • Currently that's not what's happening with change. Everytime I put a value in the textbox, nothing changes, but when I press tab to another textbox, then the color works. – nTuply Dec 29 '15 at 16:50
  • The catch is here: "For select boxes, checkboxes, and radio buttons, the event is fired immediately when the user makes a selection with the mouse, but for the other element types the event is deferred until the element loses focus." – nTuply Dec 29 '15 at 16:56
  • True. You could use pure javascript addEventListener('input' ...) will work exactly like you need. So you use addEventListener and wrap the e.target element in a jquery object once you are inside the triggered function. – Felipe T. Dec 29 '15 at 17:00
  • I'm pretty new to JS in general, care to put it in an answer as an update to your current one? I would really appreciate it :-) – nTuply Dec 29 '15 at 17:07
  • Excellent. Works exactly as I wanted. Thanks a lot :-) – nTuply Dec 29 '15 at 17:29
0

You can try this to delay on keyup

$('input').keyup(function() {
    delay(function(){
      alert('Time elapsed!');
    }, 1000 );
});
Amar Singh
  • 5,464
  • 2
  • 26
  • 55
  • Does that mean it takes 1 second for the 'Time elapsed!' to appear? So, in that case, let's say I place all my ajax and variables inside the delay, will they get executed instantly and then delay for 1 second or delay for 1 second and then execute the ajax? – nTuply Dec 29 '15 at 16:35
  • @nTuply : you can use this http://stackoverflow.com/a/1909490/5336818 for your ajax – Amar Singh Dec 29 '15 at 16:57
  • This is what I tried initially. See second snippet in my code above. – nTuply Dec 29 '15 at 17:01