jesica
jesica

Reputation: 685

jQuery/AJAX showing all loaders while typing any field

I use EasyAutocomplete

jQuery/AJAX showing all loaders while typing any field below is my example code and in the bottom has an example image like currently what happening.

My issue is while I type for job title then showing all loaders like city, on the other hand for the city input as same.

The question is how to show only this loader while I type for this like while I type for job title then want to show loader for job title input filed nor for the city, same as the city.

Perdon me if I didn't explain as well.

<form action="/search" accept-charset="UTF-8" method="get">
    <div class="row">
        <div class="col-md-6"> 
            <div class="job-search-field">

                <input type="text" name="key" id="key" placeholder="Keyword or Label like: Top,Mid,Entry" class="form-control" autocomplete="off">
                <i class="icofont icofont-user-search"></i>
                <div class="loader" style="display: none;"></div>
            </div>
        </div>

        <div class="col-md-6 p-l"> 
            <div class="city-field">
                <input type="text" name="city" id="city" placeholder="City" class="form-control" autocomplete="off">
                <i class="icofont icofont-location-pin"></i>
                <div class="loaderCity" style="display: none;"></div>

                <button type="submit" class="btn btn-default">Search</button>
            </div>
        </div>
    </div>
</form>

and the JS

$(function(){
    $(document).ajaxStart(function(){
        $(".loader").css("display", "block");
    });

    $(document).ajaxComplete(function(){
        $(".loader").css("display", "none");
    });
});

$(function(){
    $(document).ajaxStart(function(){
        $(".loaderCity").css("display", "block");
    });

    $(document).ajaxComplete(function(){
        $(".loaderCity").css("display", "none");
    });
});

example image

enter image description here

Upvotes: 0

Views: 301

Answers (4)

Krzysztof Janiszewski
Krzysztof Janiszewski

Reputation: 3854

Lets analyze your js code

$(function() {
  $(document).ajaxStart(function() {
    $(".loader").css("display", "block");
  });

  $(document).ajaxComplete(function() {
    $(".loader").css("display", "none");
  });
});

$(function() {
  $(document).ajaxStart(function() {
    $(".loaderCity").css("display", "block");
  });

  $(document).ajaxComplete(function() {
    $(".loaderCity").css("display", "none");
  });
});

$(document).ajaxStart(function()... means taht we bind an ajaxStart event to document. And you do it twice.

ajaxStart event fires every time

Whenever an Ajax request is about to be sent...

So when any Ajax request is about to be sent here is what happens:

Both events triggers (because they are the same) and this is executed:

$(".loader").css("display", "block");
$(".loaderCity").css("display", "block");

Exactly the same thing happens for ajaxComplete event.

When any Ajax request completes here is what happens:

$(".loader").css("display", "none");
$(".loaderCity").css("display", "none");

I hope you understand that (because that is what you did)

Now what is the solution?

Instead binding an ajaxStart or ajaxComplete events to document it is better to use beforeSend and complete callbacks.

Example

$.ajax({
  url: "your_url.com",
  ... //all other ajax settings and callbacks
  beforeSend: function( xhr ) {
    $(".loader").css("display", "block");
  },
  complete: function( xhr ) {
    $(".loader").css("display", "none");
  }
});

EDIT

Since you're using EasyAutocomplete you should follow this section.

There are listed events that you can use.

So do it like this (Example)

var options = {
  url: "resources/countries.json",
  getValue: "name",
  list: {
    onLoadEvent: function () {
      (".loader").css("display", "block");
    }
    onShowListEvent: function() {
      $(".loader").css("display", "none");
    }   
  }
};

$("#your-id").easyAutocomplete(options);

Upvotes: 1

com2ghz
com2ghz

Reputation: 2876

You should start your ajax request at a certain event like when the user is typing in the field with a debouncer(or use _.debounce(function, wait, [immediate]).

Some quick code so excuse my mistakes:

//When typing in the Keyword input field call the search function 
//after the last keyup event.
$("#key").keyUp(function(event) {
   debounce(search(inputElem), 300);
})

//Function that performs the ajax
function search(inputElem) {
  //From the input element, get the `.loader`
  inputElem.parent().find(".loader").show();
  $.ajax({
    url: "/search",
  }).done(function() {
    //Do something with the response
    //Hide the `.loader`
    inputElem.find(".loader").hide();
  });
}

//Debounce function that executes the given function after a certain time
function debounce(fn, bufferInterval) {
  var timeout;

  return function () {
    clearTimeout(timeout);
    timeout = setTimeout(fn.apply.bind(fn, this, arguments), bufferInterval);
  };

}

Upvotes: 0

Johan Tantyono
Johan Tantyono

Reputation: 1

Try to change $(document).ajaxComplete to $(document).ajaxStop

Hope this helps.

Upvotes: 0

jmsds
jmsds

Reputation: 225

You are calling ajaxStart() function for document, which means if any ajax is started in a page or document, then the inside code will execute. As per your code

$(function(){
    $(document).ajaxStart(function(){
        $(".loader").css("display", "block");
    });

    $(document).ajaxComplete(function(){
        $(".loader").css("display", "none");
    });
});

$(function(){
    $(document).ajaxStart(function(){
        $(".loaderCity").css("display", "block");
    });

    $(document).ajaxComplete(function(){
        $(".loaderCity").css("display", "none");
    });
});

The code

$(".loaderCity").css("display", "block");
$(".loader").css("display", "block");

will be executed simulataneously as both are called on document ajaxStart.

Instead, you can try individually hiding and showing the loader on your $.ajax codes.

// Ajax code for jobsearch.
$.ajax({
   url: 'yourURL',
   type: 'post',
   data: {parameter:data},
   beforeSend: function(){
    // Show image container
        $("#loader").show();
   },
   success: function(response){
       //Your Success code
    },
    complete:function(data){
        // Hide image container
        $("#loader").hide();
    }
 });

You can include the beforesend and complete function in your ajax calls for other inputs.

Hope this helps.

Upvotes: 0

Related Questions