knockoutjs autocomplete live search with loading

knockoutjs autocomplete live search with ajax loading

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
<input data-bind="value: searchText, valueUpdate: 'afterkeydown'" placeholder="Search repos..." type="search" />
<span class="loading" style="display:none">loading</span>
<ul data-bind="foreach: repos,visible:repos().length>0" class="search_res">
      <li class="single_res">
      <a href="#" data-bind="attr:{'href':'#'+full_name},text:full_name"></a>
      </li>
</ul>

CSS

.search_res{
  background:white;
  display:block;
  list-style:none;
  margin:0;
  padding:0;
  border:1px solid black;
  max-height:400px;
  overflow-y:auto;
  position:absolute;
  width:80%;
}
.single_res{
  list-style:none;
  border-bottom:1px solid black;
  padding:5px 10px;
  display:block;
  height:200px;
  width:200px;
  border:1px solid red;
  
}
.search_res li:last-child{
  border-bottom:none;
}
.single_res a{
  color:gray;
}

JavaScript

var ViewModel = function () {
    var self = this;

    self.repos = ko.observableArray([]);

    self.searchText = ko.observable('').extend({
        rateLimit: {
            method: 'notifyWhenChangesStop',
            timeout: 400
        }
    });

    self.searchText.subscribe(getRepos);

    function getRepos(query) {
    	if(query!=""){
          $('.loading').fadeIn();
          if (query === "") {
              self.repos([]);
              return;
          }

           $.ajax({
          type: 'GET',
          url: 'https://api.github.com/search/repositories',
          data: {q:query},
          success: function(data) {
              self.repos(data.items);
               $('.loading').fadeOut();
          },
          dataType: 'json'
      });
    }else{
    	self.repos([]);
    }
    }
}

ko.applyBindings(new ViewModel);