<commit_before>define(function(require) {
  'use strict';

  var ClassNames = require('classnames');
  var Constants = require('backend/modules/Constants');
  var Searcher = require('backend/modules/Searcher');
  var TabManager = require('modules/TabManager');
  var React = require('react');

  const SEARCH_TIMEOUT = 400;

  var SearchbarContainer = React.createClass({
    getInitialState: function() {
      return {
        keyword: '',
        isSearching: false,
        selectedIndex: -1,
        searchTracks: []
      };
    },

    _searchTimer: null,

    _onSubmit: function(event) {
      event.preventDefault();
    },

    _onInputChange: function(event) {
      var keyword = event.target.value;
      this.setState({
        keyword: keyword
      });

      window.clearTimeout(this._searchTimer);
      this._searchTimer = window.setTimeout(() => {
        this._showLoader(true);
        Searcher.search(keyword, 10, false).then((tracks) => {
          // we have to reset selectedIndex for each search
          this.setState({
            searchTracks: tracks,
            selectedIndex: -1
          });
        }, (error) => {
          console.log(error);
        }).then(() => {
          this._showLoader(false);
        });
      }, SEARCH_TIMEOUT);
    },

    _onKeyDown: function(event) {
      var key = Constants.KEY_MAP[event.keyCode];
      switch (key) {
        case 'ARROW_UP':
          event.preventDefault();
          this._handleArrowKey('up');
          break;

        case 'ARROW_DOWN':
          event.preventDefault();
          this._handleArrowKey('down');
          break;

        case 'ESC':
          this._closeAutoCompleteList();
          break;

        case 'ENTER':
          this._doSelctAutoCompleteItem();
          break;
      }
    },

    _onBlur: function() {
      this._closeAutoCompleteList();
    },

    _showLoader: function(show) {
      if (show) {
        this.setState({
          isSearching: true
        });
      }
      else {
        this.setState({
          isSearching: false
        });
      }
    },

    _doSelctAutoCompleteItem: function() {
      var keyword;

      // If users don't want to select options from AutoComplete list,
      // we will directly use the keyword from input and revoke the
      // search request
      if (this.state.selectedIndex === -1) {
        window.clearTimeout(this._searchTimer);
        keyword = this.state.keyword;
      }<commit_msg>fixed #184, add small delay for onBlur to avoid cleaning up states too<commit_after>define(function(require) {
  'use strict';

  var ClassNames = require('classnames');
  var Constants = require('backend/modules/Constants');
  var Searcher = require('backend/modules/Searcher');
  var TabManager = require('modules/TabManager');
  var React = require('react');

  const SEARCH_TIMEOUT = 400;

  var SearchbarContainer = React.createClass({
    getInitialState: function() {
      return {
        keyword: '',
        isSearching: false,
        selectedIndex: -1,
        searchTracks: []
      };
    },

    _searchTimer: null,

    _onSubmit: function(event) {
      event.preventDefault();
    },

    _onInputChange: function(event) {
      var keyword = event.target.value;
      this.setState({
        keyword: keyword
      });

      window.clearTimeout(this._searchTimer);
      this._searchTimer = window.setTimeout(() => {
        this._showLoader(true);
        Searcher.search(keyword, 10, false).then((tracks) => {
          // we have to reset selectedIndex for each search
          this.setState({
            searchTracks: tracks,
            selectedIndex: -1
          });
        }, (error) => {
          console.log(error);
        }).then(() => {
          this._showLoader(false);
        });
      }, SEARCH_TIMEOUT);
    },

    _onKeyDown: function(event) {
      var key = Constants.KEY_MAP[event.keyCode];
      switch (key) {
        case 'ARROW_UP':
          event.preventDefault();
          this._handleArrowKey('up');
          break;

        case 'ARROW_DOWN':
          event.preventDefault();
          this._handleArrowKey('down');
          break;

        case 'ESC':
          this._closeAutoCompleteList();
          break;

        case 'ENTER':
          this._doSelctAutoCompleteItem();
          break;
      }
    },

    _onBlur: function() {
      // TODO - need a better fix here
      // We need a small timeout here to make sure when users click on the item,
      // we will search tracks before cleaning up internal states
      window.setTimeout(() => {
        this._closeAutoCompleteList();
      }, 100);
    },

    _showLoader: function(show) {
      if (show) {
        this.setState({
          isSearching: true
        });
      }
      else {
        this.setState({
          isSearching: false
        });
      }
    },

    _doSelctAutoCompleteItem: function() {
      var keyword;

      // If users don't want to select options from AutoComplete list,
      // we will directly use the keyword from input and revoke the
      // search request
      if (this.state.selectedIndex === -1) {
        window.clearTimeout(this._searchTimer);
        keyword = this.state.keyword;
      }
{'fraction_non_alphanumeric': 0.11954858454475899, 'fraction_numerical': 0.004208110175975516, 'mean_word_length': 1.9948453608247423, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1454604', 'n_tokens_mistral': 1471, 'n_tokens_neox': 1442, 'n_words': 330}