<commit_before>; /* Wikipedia scraping. (C) 2012 David Byard.  Released under AGPLv3.  See LICENSE. */ ;

namespace = window.namespace || {};
namespace.util = namespace.util || {};

namespace.util.getWikipediaLinks = (function() {
  function processPageText(language, pageName, pageText, recursion, successCallback, failureCallback) {
    // Recursion?
    var redirectMatchIndex = pageText.toLowerCase().indexOf('#redirect');
    var redirectMatch = /#redirect *\[\[(.+?)\]\]/ig.exec(pageText);
    if (redirectMatch != null) {
      console.log('Following redirect', redirectMatch[1]);
      if (recursion > 3) {
        failureCallback('Recursion limit hit fetching page');
      } else {
        getWikipediaLinks(language, redirectMatch[1], recursion + 1, successCallback, failureCallback);
      }
    // Extract all links
    } else {
      var uniqueMatches = [];
      var popularityMap = {};
      var matches = pageText.match(/\[\[[^:/]*?\]\]/g);
      if (matches != null) {
        for (var i = 0; i < matches.length; i++) {
          var match = matches[i].substr(2, matches[i].length - 4).toLowerCase();  // chop off brackets, lower case
          var pipePosition = match.indexOf('|');
          if (pipePosition != -1) {
            match = match.substr(0, pipePosition);
          }
          if (popularityMap[match] == undefined) {
            popularityMap[match] = 1;
            uniqueMatches.push(match);
          } else {
            popularityMap[match] ++;
          }
        }
        uniqueMatches.sort(function(a, b) {
          return popularityMap[b] - popularityMap[a];
        });
        successCallback(uniqueMatches);
      } else {
        successCallback([]);
      }
    }
  }

  function processPageResponse(language, pageName, pageData, recursion, successCallback, failureCallback) {
    // Extract page text
    if (pageData.query && pageData.query.pages) {
      for (var pageId in pageData.query.pages) {
          var pageProperties = pageData.query.pages[pageId];
          if (pageProperties.revisions && pageProperties.revisions[0] && pageProperties.revisions[0]['*']) {
            var pageText = pageData.query.pages[pageId].revisions[0]['*'];
            processPageText(language, pageName, pageText, recursion, successCallback, failureCallback);
            return;
          }
      }
    }

    // No page text
    successCallback([]);
  }

  function getWikipediaLinks(language, pageName, recursion, successCallback, failureCallback) {
    var url = 'http://'
      + language
      + '.wikipedia.org/w/api.php?format=json&action=query&titles='
      + encodeURIComponent(pageName)
      + '&prop=revisions'
      + '&rvprop=content';
    $.ajax(url, {
        dataType: 'jsonp',
        success: function(data) {
          processPageResponse(language, pageName, data, recursion, successCallback, failureCallback);
        },
        error: function() {
          failureCallback('fetch problem for ' + pageName);
        }
      });
  }

  return function(language, pageName, successCallback, failureCallback) {
    return getWikipediaLinks(language, pageName, 0, successCallback, failureCallback)
  }
})();<commit_msg>Log redirects better<commit_after>; /* Wikipedia scraping. (C) 2012 David Byard.  Released under AGPLv3.  See LICENSE. */ ;

namespace = window.namespace || {};
namespace.util = namespace.util || {};

namespace.util.getWikipediaLinks = (function() {
  function processPageText(language, pageName, pageText, recursion, successCallback, failureCallback) {
    // Recursion?
    var redirectMatchIndex = pageText.toLowerCase().indexOf('#redirect');
    var redirectMatch = /#redirect *\[\[(.+?)\]\]/ig.exec(pageText);
    if (redirectMatch != null) {
      console.log('**WARN** Following redirect: ' + pageName + ' --> ' + redirectMatch[1]);
      if (recursion > 3) {
        failureCallback('Recursion limit hit fetching page');
      } else {
        getWikipediaLinks(language, redirectMatch[1], recursion + 1, successCallback, failureCallback);
      }
    // Extract all links
    } else {
      var uniqueMatches = [];
      var popularityMap = {};
      var matches = pageText.match(/\[\[[^:/]*?\]\]/g);
      if (matches != null) {
        for (var i = 0; i < matches.length; i++) {
          var match = matches[i].substr(2, matches[i].length - 4).toLowerCase();  // chop off brackets, lower case
          var pipePosition = match.indexOf('|');
          if (pipePosition != -1) {
            match = match.substr(0, pipePosition);
          }
          if (popularityMap[match] == undefined) {
            popularityMap[match] = 1;
            uniqueMatches.push(match);
          } else {
            popularityMap[match] ++;
          }
        }
        uniqueMatches.sort(function(a, b) {
          return popularityMap[b] - popularityMap[a];
        });
        successCallback(uniqueMatches);
      } else {
        successCallback([]);
      }
    }
  }

  function processPageResponse(language, pageName, pageData, recursion, successCallback, failureCallback) {
    // Extract page text
    if (pageData.query && pageData.query.pages) {
      for (var pageId in pageData.query.pages) {
          var pageProperties = pageData.query.pages[pageId];
          if (pageProperties.revisions && pageProperties.revisions[0] && pageProperties.revisions[0]['*']) {
            var pageText = pageData.query.pages[pageId].revisions[0]['*'];
            processPageText(language, pageName, pageText, recursion, successCallback, failureCallback);
            return;
          }
      }
    }

    // No page text
    successCallback([]);
  }

  function getWikipediaLinks(language, pageName, recursion, successCallback, failureCallback) {
    var url = 'http://'
      + language
      + '.wikipedia.org/w/api.php?format=json&action=query&titles='
      + encodeURIComponent(pageName)
      + '&prop=revisions'
      + '&rvprop=content';
    $.ajax(url, {
        dataType: 'jsonp',
        success: function(data) {
          processPageResponse(language, pageName, data, recursion, successCallback, failureCallback);
        },
        error: function() {
          failureCallback('fetch problem for ' + pageName);
        }
      });
  }

  return function(language, pageName, successCallback, failureCallback) {
    return getWikipediaLinks(language, pageName, 0, successCallback, failureCallback)
  }
})();<|endoftext|>


<commit_before>/*
* Copyright (c) 2016-present, Ken Hibino.
* Licensed under the MIT License (MIT).
* See https://kenny-hibino.github.io/react-places-autocomplete
*/

import React from 'react';
import PropTypes from 'prop-types';
import debounce from 'lodash.debounce';
import { compose, pick } from './helpers';

// transform snake_case to camelCase
const formattedSuggestion = structured_formatting => ({
  mainText: structured_formatting.main_text,
  secondaryText: structured_formatting.secondary_text,
});

class PlacesAutocomplete extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      suggestions: [],
      userInputValue: props.value,
    };

    this.debouncedFetchPredictions = debounce(
      this.fetchPredictions,
      this.props.debounce
    );
  }

  componentDidMount() {
    if (!window.google) {
      throw new Error(
        '[react-places-autocomplete]: Google Maps JavaScript API library must be loaded. See: https://github.com/kenny-hibino/react-places-autocomplete#load-google-library'
      );
    }

    if (!window.google.maps.places) {
      throw new Error(
        '[react-places-autocomplete]: Google Maps Places library must be loaded. Please add `libraries=places` to the src URL. See: https://github.com/kenny-hibino/react-places-autocomplete#load-google-library'
      );
    }

    this.autocompleteService = new window.google.maps.places.AutocompleteService();
    this.autocompleteOK = window.google.maps.places.PlacesServiceStatus.OK;
  }

  autocompleteCallback = (predictions, status) => {
    if (status !== this.autocompleteOK) {
      this.props.onError(status, this.clearSuggestions);
      return;
    }
    const { highlightFirstSuggestion } = this.props;
    this.setState({
      suggestions: predictions.map((p, idx) => ({
        id: p.id,
        description: p.description,
        placeId: p.place_id,
        active: highlightFirstSuggestion && idx === 0 ? true : false,
        index: idx,
        formattedSuggestion: formattedSuggestion(p.structured_formatting),
        matchedSubstrings: p.matched_substrings,
        terms: p.terms,
        types: p.types,
      })),
    });
  };

  fetchPredictions = () => {
    const { value } = this.props;
    if (value.length) {
      this.autocompleteService.getPlacePredictions(
        {
          ...this.props.searchOptions,
          input: value,
        },
        this.autocompleteCallback
      );
    }
  };

  clearSuggestions = () => {
    this.setState({ suggestions: [] });
  };

  clearActive = () => {
    this.setState({
      suggestions: this.state.suggestions.map(suggestion => ({
        ...suggestion,
        active: false,
      })),
    });
  };

  handleSelect = (address, placeId) => {
    this.clearSuggestions();
    this.props.onChange(address);
    this.props.onSelect && this.props.onSelect(address, placeId);
  };

  getActiveSuggestion = () => {
    return this.state.suggestions.find(suggestion => suggestion.active);
  };

  selectActiveAtIndex = index => {
    const activeName = this.state.suggestions.find(
      suggestion => suggestion.index === index
    ).description;
    this.setActiveAtIndex(index);
    this.props.onChange(activeName);
  };

  selectUserInputValue = () => {
    this.clearActive();
    this.props.onChange(this.state.userInputValue);
  };

  handleEnterKey = () => {
    const activeSuggestion = this.getActiveSuggestion();
    if (activeSuggestion === undefined) {
      this.handleSelect(this.props.value, null);
    } else {
      this.handleSelect(activeSuggestion.description, activeSuggestion.placeId);
    }
  };

  handleDownKey = () => {
    if (this.state.suggestions.length === 0) {
      return;
    }

    const activeSuggestion = this.getActiveSuggestion();
    if (activeSuggestion === undefined) {
      this.selectActiveAtIndex(0);
    } else if (activeSuggestion.index === this.state.suggestions.length - 1) {
      this.selectUserInputValue();
    } else {
      this.selectActiveAtIndex(activeSuggestion.index + 1);
    }
  };

  handleUpKey = () => {
    if (this.state.suggestions.length === 0) {
      return;
    }

    const activeSuggestion = this.getActiveSuggestion();
    if (activeSuggestion === undefined) {
      this.selectActiveAtIndex(this.state.suggestions.length - 1);
    } else if (activeSuggestion.index === 0) {
      this.selectUserInputValue();
    } else {
      this.selectActiveAtIndex(activeSuggestion.index - 1);
    }
  };

  handleInputKeyDown = event => {
    /* eslint-disable indent */
    switch (event.key) {
      case 'Enter':
        event.preventDefault();
        this.handleEnterKey();
        break;
      case 'ArrowDown':
        event.preventDefault(); // prevent the cursor from moving
        this.handleDownKey();
        break;
      case 'ArrowUp':
        event.preventDefault(); // prevent the cursor from moving
        this.handleUpKey();
        break;
      case 'Escape':
        this.clearSuggestions();
        break;
    }
    /* eslint-enable indent */
  };

  setActiveAtIndex = index => {
    this.setState({
      suggestions: this.state.suggestions.map((suggestion, idx) => {
        if (idx === index) {
          return { ...suggestion, active: true };
        } else {
          return { ...suggestion, active: false };
        }
      }),
    });
  };

  handleInputChange = event => {
    const { value } = event.target;
    this.props.onChange(value);
    this.setState({ userInputValue: value });
    if (!value) {
      this.clearSuggestions();
      return;
    }
    if (this.props.shouldFetchSuggestions) {
      this.debouncedFetchPredictions();
    }
  };

  handleInputOnBlur = () => {
    if (!this.mousedownOnSuggestion) {
      this.clearSuggestions();
    }
  };

  getActiveSuggestionId = () => {
    const activeSuggestion = this.getActiveSuggestion();
    return activeSuggestion
      ? `PlacesAutocomplete__suggestion-${activeSuggestion.placeId}`
      : null;
  };

  getIsExpanded = () => {
    return this.state.suggestions.length > 0;
  };

  getInputProps = (options = {}) => {
    if (options.hasOwnProperty('value')) {
      throw new Error(
        '[react-places-autocomplete]: getInputProps does not accept `value`. Use `value` prop instead'
      );
    }

    if (options.hasOwnProperty('onChange')) {
      throw new Error(
        '[react-places-autocomplete]: getInputProps does not accept `onChange`. Use `onChange` prop instead'
      );
    }

    const defaultInputProps = {
      type: 'text',
      autoComplete: 'off',
      role: 'combobox',
      'aria-autocomplete': 'list',
      'aria-expanded': this.getIsExpanded(),
      'aria-activedescendant': this.getActiveSuggestionId(),
    };

    return {
      ...defaultInputProps,
      ...options,
      onKeyDown: compose(this.handleInputKeyDown, options.onKeyDown),
      onBlur: compose(this.handleInputOnBlur, options.onBlur),
      value: this.props.value,
      onChange: event => {
        this.handleInputChange(event);
      },
    };
  };

  getSuggestionItemProps = (suggestion, options = {}) => {
    const whitelistedOptions = pick(options, 'className', 'style');
    return {
      ...whitelistedOptions,
      key: suggestion.placeId,
      id: this.getActiveSuggestionId(),
      role: 'option',
      onMouseEnter: this.handleSuggestionMouseEnter.bind(
        this,
        suggestion.index
      ),
      onMouseLeave: this.handleSuggestionMouseLeave,
      onMouseDown: this.handleSuggestionMouseDown,
      onMouseUp: this.handleSuggestionMouseUp,
      onTouchStart: this.handleSuggestionTouchStart,
      onTouchEnd: this.handleSuggestionMouseUp,
      onClick: this.handleSuggestionClick.bind(this, suggestion),
    };
  };

  handleSuggestionMouseEnter = index => {
    this.setActiveAtIndex(index);
  };

  handleSuggestionMouseLeave = () => {
    this.mousedownOnSuggestion = false;
    this.clearActive();
  };

  handleSuggestionMouseDown = event => {
    event.preventDefault();
    this.mousedownOnSuggestion = true;
  };

  handleSuggestionTouchStart = () => {
    this.mousedownOnSuggestion = true;
  };

  handleSuggestionMouseUp = () => {
    this.mousedownOnSuggestion = false;
  };

  handleSuggestionClick = (suggestion, event) => {
    if (event && event.preventDefault) {
      event.preventDefault();
    }
    const { description, placeId } = suggestion;
    this.handleSelect(description, placeId);
    setTimeout(() => {
      this.mousedownOnSuggestion = false;
    });
  };

  render() {
    return this.props.children({
      getInputProps: this.getInputProps,
      getSuggestionItemProps: this.getSuggestionItemProps,
      suggestions: this.state.suggestions,
    });
  }
}

PlacesAutocomplete.propTypes = {
  onChange: PropTypes.func.isRequired,
  value: PropTypes.string.isRequired,
  children: PropTypes.func.isRequired,
  onError: PropTypes.func,
  onSelect: PropTypes.func,
  searchOptions: PropTypes.shape({
    bounds: PropTypes.object,
    componentRestrictions: PropTypes.object,
    location: PropTypes.object,
    offset: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
    radius: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
    types: PropTypes.array,
  }),
  debounce: PropTypes.number,
  highlightFirstSuggestion: PropTypes.bool,
  shouldFetchSuggestions: PropTypes.bool,
};

PlacesAutocomplete.defaultProps = {
  /* eslint-disable no-unused-vars, no-console */
  onError: (status, _clearSuggestions) =>
    console.error(
      '[react-places-autocomplete]: error happened when fetching data from Google Maps API.\nPlease check the docs here (https://developers.google.com/maps/documentation/javascript/places#place_details_responses)\nStatus: ',
      status
    ),
  /* eslint-enable no-unused-vars, no-console */
  searchOptions: {},
  debounce: 200,
  highlightFirstSuggestion: false,
  shouldFetchSuggestions: true,
};

export default PlacesAutocomplete;
<commit_msg>Use suggesion.id for key<commit_after>/*
* Copyright (c) 2016-present, Ken Hibino.
* Licensed under the MIT License (MIT).
* See https://kenny-hibino.github.io/react-places-autocomplete
*/

import React from 'react';
import PropTypes from 'prop-types';
import debounce from 'lodash.debounce';
import { compose, pick } from './helpers';

// transform snake_case to camelCase
const formattedSuggestion = structured_formatting => ({
  mainText: structured_formatting.main_text,
  secondaryText: structured_formatting.secondary_text,
});

class PlacesAutocomplete extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      suggestions: [],
      userInputValue: props.value,
    };

    this.debouncedFetchPredictions = debounce(
      this.fetchPredictions,
      this.props.debounce
    );
  }

  componentDidMount() {
    if (!window.google) {
      throw new Error(
        '[react-places-autocomplete]: Google Maps JavaScript API library must be loaded. See: https://github.com/kenny-hibino/react-places-autocomplete#load-google-library'
      );
    }

    if (!window.google.maps.places) {
      throw new Error(
        '[react-places-autocomplete]: Google Maps Places library must be loaded. Please add `libraries=places` to the src URL. See: https://github.com/kenny-hibino/react-places-autocomplete#load-google-library'
      );
    }

    this.autocompleteService = new window.google.maps.places.AutocompleteService();
    this.autocompleteOK = window.google.maps.places.PlacesServiceStatus.OK;
  }

  autocompleteCallback = (predictions, status) => {
    if (status !== this.autocompleteOK) {
      this.props.onError(status, this.clearSuggestions);
      return;
    }
    const { highlightFirstSuggestion } = this.props;
    this.setState({
      suggestions: predictions.map((p, idx) => ({
        id: p.id,
        description: p.description,
        placeId: p.place_id,
        active: highlightFirstSuggestion && idx === 0 ? true : false,
        index: idx,
        formattedSuggestion: formattedSuggestion(p.structured_formatting),
        matchedSubstrings: p.matched_substrings,
        terms: p.terms,
        types: p.types,
      })),
    });
  };

  fetchPredictions = () => {
    const { value } = this.props;
    if (value.length) {
      this.autocompleteService.getPlacePredictions(
        {
          ...this.props.searchOptions,
          input: value,
        },
        this.autocompleteCallback
      );
    }
  };

  clearSuggestions = () => {
    this.setState({ suggestions: [] });
  };

  clearActive = () => {
    this.setState({
      suggestions: this.state.suggestions.map(suggestion => ({
        ...suggestion,
        active: false,
      })),
    });
  };

  handleSelect = (address, placeId) => {
    this.clearSuggestions();
    this.props.onChange(address);
    this.props.onSelect && this.props.onSelect(address, placeId);
  };

  getActiveSuggestion = () => {
    return this.state.suggestions.find(suggestion => suggestion.active);
  };

  selectActiveAtIndex = index => {
    const activeName = this.state.suggestions.find(
      suggestion => suggestion.index === index
    ).description;
    this.setActiveAtIndex(index);
    this.props.onChange(activeName);
  };

  selectUserInputValue = () => {
    this.clearActive();
    this.props.onChange(this.state.userInputValue);
  };

  handleEnterKey = () => {
    const activeSuggestion = this.getActiveSuggestion();
    if (activeSuggestion === undefined) {
      this.handleSelect(this.props.value, null);
    } else {
      this.handleSelect(activeSuggestion.description, activeSuggestion.placeId);
    }
  };

  handleDownKey = () => {
    if (this.state.suggestions.length === 0) {
      return;
    }

    const activeSuggestion = this.getActiveSuggestion();
    if (activeSuggestion === undefined) {
      this.selectActiveAtIndex(0);
    } else if (activeSuggestion.index === this.state.suggestions.length - 1) {
      this.selectUserInputValue();
    } else {
      this.selectActiveAtIndex(activeSuggestion.index + 1);
    }
  };

  handleUpKey = () => {
    if (this.state.suggestions.length === 0) {
      return;
    }

    const activeSuggestion = this.getActiveSuggestion();
    if (activeSuggestion === undefined) {
      this.selectActiveAtIndex(this.state.suggestions.length - 1);
    } else if (activeSuggestion.index === 0) {
      this.selectUserInputValue();
    } else {
      this.selectActiveAtIndex(activeSuggestion.index - 1);
    }
  };

  handleInputKeyDown = event => {
    /* eslint-disable indent */
    switch (event.key) {
      case 'Enter':
        event.preventDefault();
        this.handleEnterKey();
        break;
      case 'ArrowDown':
        event.preventDefault(); // prevent the cursor from moving
        this.handleDownKey();
        break;
      case 'ArrowUp':
        event.preventDefault(); // prevent the cursor from moving
        this.handleUpKey();
        break;
      case 'Escape':
        this.clearSuggestions();
        break;
    }
    /* eslint-enable indent */
  };

  setActiveAtIndex = index => {
    this.setState({
      suggestions: this.state.suggestions.map((suggestion, idx) => {
        if (idx === index) {
          return { ...suggestion, active: true };
        } else {
          return { ...suggestion, active: false };
        }
      }),
    });
  };

  handleInputChange = event => {
    const { value } = event.target;
    this.props.onChange(value);
    this.setState({ userInputValue: value });
    if (!value) {
      this.clearSuggestions();
      return;
    }
    if (this.props.shouldFetchSuggestions) {
      this.debouncedFetchPredictions();
    }
  };

  handleInputOnBlur = () => {
    if (!this.mousedownOnSuggestion) {
      this.clearSuggestions();
    }
  };

  getActiveSuggestionId = () => {
    const activeSuggestion = this.getActiveSuggestion();
    return activeSuggestion
      ? `PlacesAutocomplete__suggestion-${activeSuggestion.placeId}`
      : null;
  };

  getIsExpanded = () => {
    return this.state.suggestions.length > 0;
  };

  getInputProps = (options = {}) => {
    if (options.hasOwnProperty('value')) {
      throw new Error(
        '[react-places-autocomplete]: getInputProps does not accept `value`. Use `value` prop instead'
      );
    }

    if (options.hasOwnProperty('onChange')) {
      throw new Error(
        '[react-places-autocomplete]: getInputProps does not accept `onChange`. Use `onChange` prop instead'
      );
    }

    const defaultInputProps = {
      type: 'text',
      autoComplete: 'off',
      role: 'combobox',
      'aria-autocomplete': 'list',
      'aria-expanded': this.getIsExpanded(),
      'aria-activedescendant': this.getActiveSuggestionId(),
    };

    return {
      ...defaultInputProps,
      ...options,
      onKeyDown: compose(this.handleInputKeyDown, options.onKeyDown),
      onBlur: compose(this.handleInputOnBlur, options.onBlur),
      value: this.props.value,
      onChange: event => {
        this.handleInputChange(event);
      },
    };
  };

  getSuggestionItemProps = (suggestion, options = {}) => {
    const whitelistedOptions = pick(options, 'className', 'style');
    return {
      ...whitelistedOptions,
      key: suggestion.id,
      id: this.getActiveSuggestionId(),
      role: 'option',
      onMouseEnter: this.handleSuggestionMouseEnter.bind(
        this,
        suggestion.index
      ),
      onMouseLeave: this.handleSuggestionMouseLeave,
      onMouseDown: this.handleSuggestionMouseDown,
      onMouseUp: this.handleSuggestionMouseUp,
      onTouchStart: this.handleSuggestionTouchStart,
      onTouchEnd: this.handleSuggestionMouseUp,
      onClick: this.handleSuggestionClick.bind(this, suggestion),
    };
  };

  handleSuggestionMouseEnter = index => {
    this.setActiveAtIndex(index);
  };

  handleSuggestionMouseLeave = () => {
    this.mousedownOnSuggestion = false;
    this.clearActive();
  };

  handleSuggestionMouseDown = event => {
    event.preventDefault();
    this.mousedownOnSuggestion = true;
  };

  handleSuggestionTouchStart = () => {
    this.mousedownOnSuggestion = true;
  };

  handleSuggestionMouseUp = () => {
    this.mousedownOnSuggestion = false;
  };

  handleSuggestionClick = (suggestion, event) => {
    if (event && event.preventDefault) {
      event.preventDefault();
    }
    const { description, placeId } = suggestion;
    this.handleSelect(description, placeId);
    setTimeout(() => {
      this.mousedownOnSuggestion = false;
    });
  };

  render() {
    return this.props.children({
      getInputProps: this.getInputProps,
      getSuggestionItemProps: this.getSuggestionItemProps,
      suggestions: this.state.suggestions,
    });
  }
}

PlacesAutocomplete.propTypes = {
  onChange: PropTypes.func.isRequired,
  value: PropTypes.string.isRequired,
  children: PropTypes.func.isRequired,
  onError: PropTypes.func,
  onSelect: PropTypes.func,
  searchOptions: PropTypes.shape({
    bounds: PropTypes.object,
    componentRestrictions: PropTypes.object,
    location: PropTypes.object,
    offset: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
    radius: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
    types: PropTypes.array,
  }),
  debounce: PropTypes.number,
  highlightFirstSuggestion: PropTypes.bool,
  shouldFetchSuggestions: PropTypes.bool,
};

PlacesAutocomplete.defaultProps = {
  /* eslint-disable no-unused-vars, no-console */
  onError: (status, _clearSuggestions) =>
    console.error(
      '[react-places-autocomplete]: error happened when fetching data from Google Maps API.\nPlease check the docs here (https://developers.google.com/maps/documentation/javascript/places#place_details_responses)\nStatus: ',
      status
    ),
  /* eslint-enable no-unused-vars, no-console */
  searchOptions: {},
  debounce: 200,
  highlightFirstSuggestion: false,
  shouldFetchSuggestions: true,
};

export default PlacesAutocomplete;
<|endoftext|>


<commit_before>
L.provide('LW.plugin.experiment.experiment_monitor', ['#LW.init'], function () {

  if (typeof(LW.plugin.experiment) == "undefined") LW.plugin.experiment = {};

  LW.plugin.experiment.experiment_monitor = function(exp_name) {
    var current_event = null;
    var graphs = {};

    function ctxt() {};

    OHUB.bind('data_source.status_' + exp_name + '.changed', function(update) {
      var events = update.events;
    });

    OHUB.bind('data_source.log_' + exp_name + '.changed', function(ev) {
      var msgs = ev.data_source.rows(); //.events;
      var l = msgs.length;
      if (l < 1 || current_event == msgs[l - 1]) return;

      var html = ""
      _.each(msgs.slice(0).reverse(), function(e) {
        var ts = e[1].toFixed(1);
        var severity = e[2];
        var message = e[4];
        // Hack to hide stop exp button
        if (message.match(/^Experiment .+ finished after .+$/)) $("#btn-stop-experiment").hide();

        html = html + '
'
          + ts
          + '	' + severity
          + '	' + message
          + '
'
          ;
      });
      $('table.experiment-log').html(html)
    });

    var embed = function(embed_container, options) {
      opts = jQuery.extend(true, {}, options); // deep copy
      var type = opts.type;

      // Create a div to embed the graph in
      var eid =  'e' + Math.round((Math.random() * 10E12));
      var caption = options.caption || 'Caption Missing';
      var cap_h = '
'
                //+ '_'
                //+ '

'
                + ''
                + 'Figure:'
                + '' + caption + ''
                + '</div'
                ;
      embed_container
        .append('

')
        .append(cap_h)
        ;
      opts.base_el = '#w' + eid;
      L.require('#OML.' + type, 'graph/js/' + type + '.js', function() {
        //graphs[eid] = new OML[type](opts);
        new OML[type](opts);
      });

      // Make Caption draggable
      var del = $('#d' + eid);
      del.data('content', {mime_type: 'data/graph', opts: opts });
      del.data('embedder', function(embed_container) {
        embed(embed_container, options);
      });
      del.draggable({
        appendTo: "body",
        helper: "clone",
        stack: 'body',
        zIndex: 9999
      });
    };

    var process_graph_announcements = function(gds) {
      _.each(gds.rows(), function(e) {
        var id = e[1];
        if (graphs[id]) return;

        var opts = JSON.parse(e[2]);

        // Create the datasources
        _.each(opts.data_sources, function(dsh) {
          var ds = OML.data_sources.register(dsh);
          // var ds = OML.data_sources.register(dsh.stream, null, dsh.schema, []);
          // if (dsh.update_interval) {
            // ds.is_dynamic(dsh.update_interval)
          // }
        });
        embed($('div.experiment-graphs'), opts);
      })
    };
    var gds = OML.data_sources.lookup('graph_' + exp_name);
    process_graph_announcements(gds);
    OHUB.bind(gds.event_name, function(ev) {
      process_graph_announcements(ev.data_source);
    });

    var sections = $('.widget_body h3 a.toggle');
    sections.click(function(ev) {
      var a = $(this)
      a.toggleClass('toggle-closed');
      var p = a.parent().next();
      p.slideToggle(400);
      return false;
    });

    // STOP Experiment button
    $(".btn-stop-experiment").click(function(event) {
      var opts = {
        action: 'stop_experiment',
        col: 'execute'
      };
      LW.execute_controller.refresh_content(opts, 'POST');
      return false;
    })

    // Hacking Dump button
    $("#btn-dump").click(function(event) {
      $(this).attr('disabled', 'disabled');
      $.post("/dump", { domain: $(this).attr("exp_id")}, function(data) {
        $(".alert-dump").html(data);
        $(".alert-dump").addClass("alert-success");
        $(".alert-dump").removeClass("alert-error");
      }).fail(function(data) {
        $(".alert-dump").html(data.responseText);
        $(".alert-dump").addClass("alert-error");
        $(".alert-dump").removeClass("alert-success");
      }).always(function(data) {
        $(".alert-dump").show();
      });
      setTimeout(function() {
        $(".alert-dump").hide();
        $("#btn-dump").removeAttr('disabled');
      }, 60000);
      return false;
    })

    return ctxt;
  };

})
<commit_msg>Flash when exp finished<commit_after>
L.provide('LW.plugin.experiment.experiment_monitor', ['#LW.init'], function () {

  if (typeof(LW.plugin.experiment) == "undefined") LW.plugin.experiment = {};

  LW.plugin.experiment.experiment_monitor = function(exp_name) {
    var current_event = null;
    var graphs = {};

    function ctxt() {};

    OHUB.bind('data_source.status_' + exp_name + '.changed', function(update) {
      var events = update.events;
    });

    OHUB.bind('data_source.log_' + exp_name + '.changed', function(ev) {
      var msgs = ev.data_source.rows(); //.events;
      var l = msgs.length;
      if (l < 1 || current_event == msgs[l - 1]) return;

      var html = ""
      _.each(msgs.slice(0).reverse(), function(e) {
        var ts = e[1].toFixed(1);
        var severity = e[2];
        var message = e[4];
        // Hack to hide stop exp button
        if (message.match(/^Experiment .+ finished after .+$/)) {
          $("#btn-stop-experiment").hide();
          $(".alert-dump").html(message).addClass("alert-success").removeClass("alert-error").show();
        }

        html = html + '
'
          + ts
          + '	' + severity
          + '	' + message
          + '
'
          ;
      });
      $('table.experiment-log').html(html)
    });

    var embed = function(embed_container, options) {
      opts = jQuery.extend(true, {}, options); // deep copy
      var type = opts.type;

      // Create a div to embed the graph in
      var eid =  'e' + Math.round((Math.random() * 10E12));
      var caption = options.caption || 'Caption Missing';
      var cap_h = '
'
                //+ '_'
                //+ '

'
                + ''
                + 'Figure:'
                + '' + caption + ''
                + '</div'
                ;
      embed_container
        .append('

')
        .append(cap_h)
        ;
      opts.base_el = '#w' + eid;
      L.require('#OML.' + type, 'graph/js/' + type + '.js', function() {
        //graphs[eid] = new OML[type](opts);
        new OML[type](opts);
      });

      // Make Caption draggable
      var del = $('#d' + eid);
      del.data('content', {mime_type: 'data/graph', opts: opts });
      del.data('embedder', function(embed_container) {
        embed(embed_container, options);
      });
      del.draggable({
        appendTo: "body",
        helper: "clone",
        stack: 'body',
        zIndex: 9999
      });
    };

    var process_graph_announcements = function(gds) {
      _.each(gds.rows(), function(e) {
        var id = e[1];
        if (graphs[id]) return;

        var opts = JSON.parse(e[2]);

        // Create the datasources
        _.each(opts.data_sources, function(dsh) {
          var ds = OML.data_sources.register(dsh);
          // var ds = OML.data_sources.register(dsh.stream, null, dsh.schema, []);
          // if (dsh.update_interval) {
            // ds.is_dynamic(dsh.update_interval)
          // }
        });
        embed($('div.experiment-graphs'), opts);
      })
    };
    var gds = OML.data_sources.lookup('graph_' + exp_name);
    process_graph_announcements(gds);
    OHUB.bind(gds.event_name, function(ev) {
      process_graph_announcements(ev.data_source);
    });

    var sections = $('.widget_body h3 a.toggle');
    sections.click(function(ev) {
      var a = $(this)
      a.toggleClass('toggle-closed');
      var p = a.parent().next();
      p.slideToggle(400);
      return false;
    });

    // STOP Experiment button
    $(".btn-stop-experiment").click(function(event) {
      $(this).attr('disabled', 'disabled');
      $(this).html('Stopping...');
      var opts = {
        action: 'stop_experiment',
        col: 'execute'
      };
      LW.execute_controller.refresh_content(opts, 'POST');
      return false;
    })

    // Hacking Dump button
    $("#btn-dump").click(function(event) {
      $(this).attr('disabled', 'disabled');
      $.post("/dump", { domain: $(this).attr("exp_id")}, function(data) {
        $(".alert-dump").html(data).addClass("alert-success").removeClass("alert-error");
      }).fail(function(data) {
        $(".alert-dump").html(data.responseText).addClass("alert-error").removeClass("alert-success");
      }).always(function(data) {
        $(".alert-dump").show();
      });
      setTimeout(function() {
        $(".alert-dump").hide();
        $("#btn-dump").removeAttr('disabled');
      }, 60000);
      return false;
    })

    return ctxt;
  };

})
<|endoftext|>


<commit_before>/**
* @license Apache-2.0
*
* Copyright (c) 2020 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

var randu = require( '@stdlib/random/base/randu' );
var round = require( '@stdlib/math/base/special/round' );
var Float64Array = require( '@stdlib/array/float64' );
var variance = require( './../lib' );

var x;
var i;

x = new Float64Array( 10 );
for ( i = 0; i < x.length; i++ ) {
	x[ i ] = round( (randu()*100.0) - 50.0 );
}
console.log( x );

var v = variance( x.length, 1, x, 1 );
console.log( v );
<commit_msg>Rename variable<commit_after>/**
* @license Apache-2.0
*
* Copyright (c) 2020 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

var randu = require( '@stdlib/random/base/randu' );
var round = require( '@stdlib/math/base/special/round' );
var Float64Array = require( '@stdlib/array/float64' );
var variancepn = require( './../lib' );

var x;
var i;

x = new Float64Array( 10 );
for ( i = 0; i < x.length; i++ ) {
	x[ i ] = round( (randu()*100.0) - 50.0 );
}
console.log( x );

var v = variancepn( x.length, 1, x, 1 );
console.log( v );
<|endoftext|>


<commit_before>prettyPrint();

// sidebar navigation
$(function() {
  var loc = window.location.href; // returns the full URL
  if(/overview/.test(loc)) {
    $('.overview-nav').addClass('active');
  }
  else if(/code_index/.test(loc)) {
    $('.code-index-nav').addClass('active');
  }
  else if(/smells_index/.test(loc)) {
    $('.smells-index-nav').addClass('active');
  }
});

var turbulenceData = turbulenceData || [];
var COLOR = {
  'A' : '#00B50E',
  'B': '#53D700',
  'C': '#FDF400',
  'D': '#FF6C00',
  'F': '#C40009'
};
$("#churn-vs-complexity-graph-container").highcharts({
  chart: {
    type: "scatter",
    zoomType: "xy"
  },
  title: {
    text: "Churn vs Complexity"
  },
  xAxis: {
    title: {
      enabled: true,
      text: "Churn"
    },
    floor: 0,
    startOnTick: true,
    endOnTick: true
  },
  yAxis: {
    title: {
      text: "Complexity"
    },
    floor: 0,
    startOnTick: true,
    endOnTick: true
  },
  plotOptions: {
    series: {
      turboThreshold: 1500
    },
    scatter: {
      marker: {
        radius: 5,
        states: {
          hover: {
            enabled: true,
            lineColor: "rgb(100,100,100)"
          }
        }
      },
      tooltip: {
        headerFormat: "{point.key}
",
        pointFormat: "Committed {point.x} times, with Flog score of {point.y}"
      }
    }
  },
  series: [{
    showInLegend: false,
    color: "steelblue",
    data: getMappedTurbulenceData()
  }]
});

function getMappedTurbulenceData(){
  var dataWithColorInformation = turbulenceData.map(function(data){
    data.color = COLOR[data.rating];
    return data;
  });
  return dataWithColorInformation;
};

$(function() {
  $("#gpa-chart").highcharts(
    {
      chart: {
        type: 'pie',
        events: {
            load: addTitle,
            redraw: addTitle,
        },
      },
      title: {
        text: "",
        useHTML: true
      },
      plotOptions: {
        pie: {
          shadow: false
        }
      },
      tooltip: {
        formatter: function() {
          return ''+ this.point.name +': '+ this.y +' %';
        }
      },
      series: [{
        name: 'Browsers',
        data: getGpaData(),
        size: '90%',
        innerSize: '65%',
        showInLegend:true,
        dataLabels: {
          enabled: false
        }
      }]
    });
});

function addTitle() {
    if (this.title) {
        this.title.destroy();
    }
    var r = this.renderer,
        x = this.series[0].center[0] + this.plotLeft,
        y = this.series[0].center[1] + this.plotTop;
    this.title = r.label(''+score.toFixed(2)+'/100', 0, 0, "", 0, 0, true)
        .css({
        color: 'black'
    }).hide().add();
    var bbox = this.title.getBBox();
    this.title.attr({
        x: x - (bbox.width / 2),
        y: y
    }).show();
    this.title.useHTML = true;
};

function getGpaData(){
  var ratingACount = getRatingWiseCount("A");
  var ratingBCount = getRatingWiseCount("B");
  var ratingCCount = getRatingWiseCount("C");
  var ratingDCount = getRatingWiseCount("D");
  var ratingFCount = getRatingWiseCount("F");
  var total = ratingACount + ratingBCount + ratingCCount + ratingDCount + ratingFCount;
  return [
    {name: 'A', y: parseFloat(calculatePercentage(ratingACount, total).toFixed(2)), color: COLOR['A']},
    {name: 'B', y: parseFloat(calculatePercentage(ratingBCount, total).toFixed(2)), color: COLOR['B']},
    {name: 'C', y: parseFloat(calculatePercentage(ratingCCount, total).toFixed(2)), color: COLOR['C']},
    {name: 'D', y: parseFloat(calculatePercentage(ratingDCount, total).toFixed(2)), color: COLOR['D']},
    {name: 'F', y: parseFloat(calculatePercentage(ratingFCount, total).toFixed(2)), color: COLOR['F']},
  ];
};

function calculatePercentage(gradeCount, total){
  return (gradeCount/total)*100;
};

function getRatingWiseCount(rating){
  var count = 0;
  turbulenceData.forEach(function(data, index){
    if(data.rating === rating){
      count++;
    }
  });
  return count;
};

function emphasizeLineFromFragment() {
  emphasizeLine(window.location.hash)
}

$(".js-file-code").on("click", ".js-smell-location", emphasizeLineFromHref);

function emphasizeLineFromHref(event) {
  if (hrefTargetIsOnCurrentPage(this) && !event.ctrlKey) {
    $(".js-file-code li").removeClass("highlight");
    var lineId = "#" + this.href.split("#")[1];
    emphasizeLine(lineId);
    return false;
  }
}

function hrefTargetIsOnCurrentPage(aTag) {
  return (window.location.pathname === aTag.pathname);
}

function emphasizeLine(lineReference) {
  scrollToTarget(lineReference);
  highlightLine(lineReference);
}

function scrollToTarget(lineReference) {
  window.location.hash = lineReference;
  $.scrollTo(lineReference, {
    duration: 300,
    easing: "linear",
    offset: {top: -87}
  });
}

function highlightLine(lineReference) {
  $(lineReference).addClass("highlight");
}

$("#toggle-code").on("click", showCode);
$("#toggle-smells").on("click", showSmells);

function showCode() {
  $('#toggle-code').parent('li').addClass('active');
  $('#toggle-smells').parent('li').removeClass('active');
  $(".smells").hide();
}

function showSmells() {
  $('#toggle-code').parent('li').removeClass('active');
  $('#toggle-smells').parent('li').addClass('active');
  $(".smells").show();
}

$("#codeTable")
  .tablesorter({          // Sort the table
    sortList: [[0,1]]
  });

$("#js-index-table")
  .tablesorter({          // Sort the table
    sortList: [[0,0]]
  });

$(".js-timeago").timeago();

$(function(){
  $('.table-header').click(function(){
    $('.table-header').not(this).each(function(){
      $(this).removeClass('active');
      $(this).find('.sort-type').removeClass('table-header-asc');
      $(this).find('.sort-type').removeClass('table-header-desc');
    });
    if($(this).hasClass('active')){
      $(this).find('.sort-type').toggleClass('table-header-asc table-header-desc');
    }
    else{
      $(this).addClass('active');
      $(this).find('.sort-type').addClass('table-header-asc');
    }
  });
});

function assignIdsToCodeLines(){
  $($('.linenums')[1]).children().each(function(index){
    $(this).attr('id', "L" + index)
  });
};

$(document).ready(function(){
  assignIdsToCodeLines();
  emphasizeLineFromFragment();
  initTableFilters();
});

var initTableFilters = function() {
  $("#codeTable").filterTable({ignoreColumns: [2], placeholder: 'Filter by Name'});
  $("#js-index-table").filterTable({ignoreColumns: [2, 3, 4, 5], placeholder: 'Filter by Smell or Location', inputSelector: 'form-control'});
}
<commit_msg>Only scroll Y axis when visiting page with anchor tag<commit_after>prettyPrint();

// sidebar navigation
$(function() {
  var loc = window.location.href; // returns the full URL
  if(/overview/.test(loc)) {
    $('.overview-nav').addClass('active');
  }
  else if(/code_index/.test(loc)) {
    $('.code-index-nav').addClass('active');
  }
  else if(/smells_index/.test(loc)) {
    $('.smells-index-nav').addClass('active');
  }
});

var turbulenceData = turbulenceData || [];
var COLOR = {
  'A' : '#00B50E',
  'B': '#53D700',
  'C': '#FDF400',
  'D': '#FF6C00',
  'F': '#C40009'
};
$("#churn-vs-complexity-graph-container").highcharts({
  chart: {
    type: "scatter",
    zoomType: "xy"
  },
  title: {
    text: "Churn vs Complexity"
  },
  xAxis: {
    title: {
      enabled: true,
      text: "Churn"
    },
    floor: 0,
    startOnTick: true,
    endOnTick: true
  },
  yAxis: {
    title: {
      text: "Complexity"
    },
    floor: 0,
    startOnTick: true,
    endOnTick: true
  },
  plotOptions: {
    series: {
      turboThreshold: 1500
    },
    scatter: {
      marker: {
        radius: 5,
        states: {
          hover: {
            enabled: true,
            lineColor: "rgb(100,100,100)"
          }
        }
      },
      tooltip: {
        headerFormat: "{point.key}
",
        pointFormat: "Committed {point.x} times, with Flog score of {point.y}"
      }
    }
  },
  series: [{
    showInLegend: false,
    color: "steelblue",
    data: getMappedTurbulenceData()
  }]
});

function getMappedTurbulenceData(){
  var dataWithColorInformation = turbulenceData.map(function(data){
    data.color = COLOR[data.rating];
    return data;
  });
  return dataWithColorInformation;
};

$(function() {
  $("#gpa-chart").highcharts(
    {
      chart: {
        type: 'pie',
        events: {
            load: addTitle,
            redraw: addTitle,
        },
      },
      title: {
        text: "",
        useHTML: true
      },
      plotOptions: {
        pie: {
          shadow: false
        }
      },
      tooltip: {
        formatter: function() {
          return ''+ this.point.name +': '+ this.y +' %';
        }
      },
      series: [{
        name: 'Browsers',
        data: getGpaData(),
        size: '90%',
        innerSize: '65%',
        showInLegend:true,
        dataLabels: {
          enabled: false
        }
      }]
    });
});

function addTitle() {
    if (this.title) {
        this.title.destroy();
    }
    var r = this.renderer,
        x = this.series[0].center[0] + this.plotLeft,
        y = this.series[0].center[1] + this.plotTop;
    this.title = r.label(''+score.toFixed(2)+'/100', 0, 0, "", 0, 0, true)
        .css({
        color: 'black'
    }).hide().add();
    var bbox = this.title.getBBox();
    this.title.attr({
        x: x - (bbox.width / 2),
        y: y
    }).show();
    this.title.useHTML = true;
};

function getGpaData(){
  var ratingACount = getRatingWiseCount("A");
  var ratingBCount = getRatingWiseCount("B");
  var ratingCCount = getRatingWiseCount("C");
  var ratingDCount = getRatingWiseCount("D");
  var ratingFCount = getRatingWiseCount("F");
  var total = ratingACount + ratingBCount + ratingCCount + ratingDCount + ratingFCount;
  return [
    {name: 'A', y: parseFloat(calculatePercentage(ratingACount, total).toFixed(2)), color: COLOR['A']},
    {name: 'B', y: parseFloat(calculatePercentage(ratingBCount, total).toFixed(2)), color: COLOR['B']},
    {name: 'C', y: parseFloat(calculatePercentage(ratingCCount, total).toFixed(2)), color: COLOR['C']},
    {name: 'D', y: parseFloat(calculatePercentage(ratingDCount, total).toFixed(2)), color: COLOR['D']},
    {name: 'F', y: parseFloat(calculatePercentage(ratingFCount, total).toFixed(2)), color: COLOR['F']},
  ];
};

function calculatePercentage(gradeCount, total){
  return (gradeCount/total)*100;
};

function getRatingWiseCount(rating){
  var count = 0;
  turbulenceData.forEach(function(data, index){
    if(data.rating === rating){
      count++;
    }
  });
  return count;
};

function emphasizeLineFromFragment() {
  emphasizeLine(window.location.hash)
}

$(".js-file-code").on("click", ".js-smell-location", emphasizeLineFromHref);

function emphasizeLineFromHref(event) {
  if (hrefTargetIsOnCurrentPage(this) && !event.ctrlKey) {
    $(".js-file-code li").removeClass("highlight");
    var lineId = "#" + this.href.split("#")[1];
    emphasizeLine(lineId);
    return false;
  }
}

function hrefTargetIsOnCurrentPage(aTag) {
  return (window.location.pathname === aTag.pathname);
}

function emphasizeLine(lineReference) {
  scrollToTarget(lineReference);
  highlightLine(lineReference);
}

function scrollToTarget(lineReference) {
  window.location.hash = lineReference;
  $.scrollTo(lineReference, {
    duration: 300,
    easing: "linear",
    offset: {top: -87},
    axis: 'y'
  });
}

function highlightLine(lineReference) {
  $(lineReference).addClass("highlight");
}

$("#toggle-code").on("click", showCode);
$("#toggle-smells").on("click", showSmells);

function showCode() {
  $('#toggle-code').parent('li').addClass('active');
  $('#toggle-smells').parent('li').removeClass('active');
  $(".smells").hide();
}

function showSmells() {
  $('#toggle-code').parent('li').removeClass('active');
  $('#toggle-smells').parent('li').addClass('active');
  $(".smells").show();
}

$("#codeTable")
  .tablesorter({          // Sort the table
    sortList: [[0,1]]
  });

$("#js-index-table")
  .tablesorter({          // Sort the table
    sortList: [[0,0]]
  });

$(".js-timeago").timeago();

$(function(){
  $('.table-header').click(function(){
    $('.table-header').not(this).each(function(){
      $(this).removeClass('active');
      $(this).find('.sort-type').removeClass('table-header-asc');
      $(this).find('.sort-type').removeClass('table-header-desc');
    });
    if($(this).hasClass('active')){
      $(this).find('.sort-type').toggleClass('table-header-asc table-header-desc');
    }
    else{
      $(this).addClass('active');
      $(this).find('.sort-type').addClass('table-header-asc');
    }
  });
});

function assignIdsToCodeLines(){
  $($('.linenums')[1]).children().each(function(index){
    $(this).attr('id', "L" + index)
  });
};

$(document).ready(function(){
  assignIdsToCodeLines();
  emphasizeLineFromFragment();
  initTableFilters();
});

var initTableFilters = function() {
  $("#codeTable").filterTable({ignoreColumns: [2], placeholder: 'Filter by Name'});
  $("#js-index-table").filterTable({ignoreColumns: [2, 3, 4, 5], placeholder: 'Filter by Smell or Location', inputSelector: 'form-control'});
}
<|endoftext|>


<commit_before>(function (root, factory) {
  // AMD.
  if(typeof define === 'function' && define.amd) {
    define([], factory);
  }

  // Browser Global.
  if(typeof root.navigator === "object") {
    if(typeof root.Terraformer === "undefined"){
      root.Terraformer = {};
    }
    if(typeof root.Terraformer.Store === "undefined"){
      root.Terraformer.Store = {};
    }
    root.Terraformer.Store.LocalStorage = factory().LocalStorage;
  }
}(this, function() {
  var exports = { };

  var Terraformer;

  // Local Reference To Browser Global
  if(typeof this.navigator === "object") {
    Terraformer = this.Terraformer;
  }

  // Setup Node Dependencies
  if(typeof module === 'object' && typeof module.exports === 'object') {
    Terraformer = require('terraformer');
  }

  // Setup AMD Dependencies
  if(arguments[0] && typeof define === 'function' && define.amd) {
    Terraformer = arguments[0];
  }

  // These methods get called in context of the geostore
  function LocalStorage(){
    var opts = arguments[0] || {};
    this._key = opts.key || "_terraformer";
  }

  // store the data at id returns true if stored successfully
  LocalStorage.prototype.add = function(geojson, dfd){
    if(geojson.type === "FeatureCollection"){
      for (var i = 0; i < geojson.features.length; i++) {
        this.set(geojson.features[i]);
      }
    } else {
      this.set(geojson);
    }
    dfd.resolve(geojson);
    return dfd;
  };

  LocalStorage.prototype.key = function(id){
    return this._key +"_"+id;
  };

  // remove the data from the index and data with id returns true if removed successfully.
  LocalStorage.prototype.remove = function(id, dfd){
    localStorage.removeItem(this.key(id));
    dfd.resolve(id);
    return dfd;
  };

  // return the data stored at id
  LocalStorage.prototype.get = function(id, dfd){
    dfd.resolve(JSON.parse(localStorage.getItem(this.key(id))));
    return dfd;
  };

  LocalStorage.prototype.set = function(feature){
    localStorage.setItem(this.key(feature.id), JSON.stringify(feature));
  };

  LocalStorage.prototype.update = function(geojson, dfd){
    this.set(geojson);
    dfd.resolve(geojson);
    return dfd;
  };

  LocalStorage.prototype.toJSON = function(){
    var exports = {};
    for(var feature in localStorage){
      if(feature.match(this._key)){
        exports[feature] = localStorage[feature];
      }
    }
    return exports;
  };

  LocalStorage.prototype.serialize = function(callback){
    var objs = [];

    // make a new deferred
    var dfd = new Terraformer.Deferred();

    // map callback to dfd if we have one
    if(callback){
      dfd.then(function(result){
        callback(null, result);
      }, function(error){
        callback(error, null);
      });
    }

    for (var key in localStorage){
      if(key.match(this._key)){
        objs.push(localStorage.getItem(key));
      }
    }

    dfd.resolve(JSON.stringify(objs));

    return dfd;
  };

  LocalStorage.prototype.deserialize = function(serial){
    var data = JSON.parse(serial);
    for (var i = data.length - 1; i >= 0; i--) {
      this.set(data[i]);
    }
    return this;
  };

  exports.LocalStorage = LocalStorage;

  return exports;
}));<commit_msg>removed deferred from localstorage store<commit_after>(function (root, factory) {
  // AMD.
  if(typeof define === 'function' && define.amd) {
    define([], factory);
  }

  // Browser Global.
  if(typeof root.navigator === "object") {
    if(typeof root.Terraformer === "undefined"){
      root.Terraformer = {};
    }
    if(typeof root.Terraformer.Store === "undefined"){
      root.Terraformer.Store = {};
    }
    root.Terraformer.Store.LocalStorage = factory().LocalStorage;
  }
}(this, function() {
  var exports = { };

  var Terraformer, callback;

  // Local Reference To Browser Global
  if(typeof this.navigator === "object") {
    Terraformer = this.Terraformer;
  }

  // Setup Node Dependencies
  if(typeof module === 'object' && typeof module.exports === 'object') {
    Terraformer = require('terraformer');
  }

  // Setup AMD Dependencies
  if(arguments[0] && typeof define === 'function' && define.amd) {
    Terraformer = arguments[0];
  }

  // These methods get called in context of the geostore
  function LocalStorage(){
    var opts = arguments[0] || {};
    this._key = opts.key || "_terraformer";
  }

  // store the data at id returns true if stored successfully
  LocalStorage.prototype.add = function(geojson, callback){
    if(geojson.type === "FeatureCollection"){
      for (var i = 0; i < geojson.features.length; i++) {
        this.set(geojson.features[i]);
      }
    } else {
      this.set(geojson);
    }
    if ( callback ) callback( null, geojson );
  };

  LocalStorage.prototype.key = function(id){
    return this._key +"_"+id;
  };

  // remove the data from the index and data with id returns true if removed successfully.
  LocalStorage.prototype.remove = function( id, callback ){
    localStorage.removeItem( this.key( id ) );
    if ( callback ) callback( null, id );
  };

  // return the data stored at id
  LocalStorage.prototype.get = function(id, callback){
    if ( callback ) callback( null, JSON.parse(localStorage.getItem(this.key(id))));
  };

  LocalStorage.prototype.set = function(feature){
    if ( callback ) localStorage.setItem(this.key(feature.id), JSON.stringify(feature));
  };

  LocalStorage.prototype.update = function(geojson, callback){
    this.set(geojson);
    if ( callback ) callback( null, geojson );
  };

  LocalStorage.prototype.toJSON = function(){
    var exports = {};
    for(var feature in localStorage){
      if(feature.match(this._key)){
        exports[feature] = localStorage[feature];
      }
    }
    return exports;
  };

  LocalStorage.prototype.serialize = function(callback){
    var objs = [];

    for (var key in localStorage){
      if(key.match(this._key)){
        objs.push(localStorage.getItem(key));
      }
    }

    if ( callback ) callback(null, JSON.stringify(objs));
  };

  LocalStorage.prototype.deserialize = function(serial){
    var data = JSON.parse(serial);
    for (var i = data.length - 1; i >= 0; i--) {
      this.set(data[i]);
    }
    return this;
  };

  exports.LocalStorage = LocalStorage;

  return exports;
}));
<|endoftext|>


<commit_before>/**
 * @file ListItem component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import Checkbox from '../Checkbox';
import Radio from '../Radio';
import CircularLoading from '../CircularLoading';
import TipProvider from '../TipProvider';
import TouchRipple from '../TouchRipple';
import Theme from '../Theme';

import Util from '../_vendors/Util';
import Position from '../_statics/Position';
import SelectMode from '../_statics/SelectMode';

class ListItem extends Component {

    static SelectMode = SelectMode;
    static Theme = Theme;

    constructor(props, ...restArgs) {
        super(props, ...restArgs);
    }

    multiSelectChangeHandler = checked => {

        const {onSelect, onDeselect} = this.props;

        if (checked) {
            onSelect && onSelect();
        } else {
            onDeselect && onDeselect();
        }

    };

    singleSelectChangeHandler = () => {
        if (!this.props.checked) {
            const {onSelect} = this.props;
            onSelect && onSelect();
        }
    };

    clickHandler = e => {

        const {disabled, isLoading, readOnly, autoSelect} = this.props;

        if (disabled || isLoading || readOnly) {
            return;
        }

        const {onClick} = this.props;
        onClick && onClick(e);

        if (!autoSelect) {
            return;
        }

        switch (this.props.selectMode) {
            case SelectMode.MULTI_SELECT:
                this.multiSelectChangeHandler(!this.props.checked);
                return;
            case SelectMode.SINGLE_SELECT:
                this.singleSelectChangeHandler();
                return;
        }

    };

    radioCheckHandler = () => {
        this.singleSelectChangeHandler();
    };

    checkboxCheckHandler = () => {
        this.multiSelectChangeHandler(true);
    };

    checkboxUncheckHandler = () => {
        this.multiSelectChangeHandler(false);
    };

    render() {

        const {

                index, className, style, theme, data, text, desc, iconCls, rightIconCls, tip, tipPosition,
                disabled, isLoading, disableTouchRipple, rippleDisplayCenter, renderer, itemRenderer, readOnly,

                checked, selectTheme, selectMode, indeterminateCallback, radioUncheckedIconCls, radioCheckedIconCls,
                checkboxUncheckedIconCls, checkboxCheckedIconCls, checkboxIndeterminateIconCls,
                stopSelectClickEventPropagation,

                onMouseEnter, onMouseLeave

            } = this.props,

            listItemClassName = classNames('list-item', {
                [`theme-${theme}`]: theme,
                activated: checked,
                [className]: className
            }),

            loadingIconPosition = (rightIconCls && !iconCls) ? 'right' : 'left';

        return (
            <TipProvider text={tip}
                         position={tipPosition}>

                    {
                        selectMode === SelectMode.SINGLE_SELECT && (radioUncheckedIconCls || radioCheckedIconCls) ?
                            <Radio className="list-item-select"
                                   theme={selectTheme}
                                   checked={checked}
                                   disabled={disabled || isLoading}
                                   uncheckedIconCls={radioUncheckedIconCls}
                                   checkedIconCls={radioCheckedIconCls}
                                   disableTouchRipple={true}
                                   onCheck={this.radioCheckHandler}
                                   onClick={e => stopSelectClickEventPropagation && e.stopPropagation()}/>
                            :
                            null
                    }

                    {
                        selectMode === SelectMode.MULTI_SELECT ?
                            <Checkbox className="list-item-select"
                                      theme={selectTheme}
                                      checked={checked}
                                      indeterminate={indeterminateCallback && indeterminateCallback(data)}
                                      disabled={disabled || isLoading}
                                      uncheckedIconCls={checkboxUncheckedIconCls}
                                      checkedIconCls={checkboxCheckedIconCls}
                                      indeterminateIconCls={checkboxIndeterminateIconCls}
                                      disableTouchRipple={true}
                                      onCheck={this.checkboxCheckHandler}
                                      onUncheck={this.checkboxUncheckHandler}
                                      onClick={e => stopSelectClickEventPropagation && e.stopPropagation()}/>
                            :
                            null
                    }

                    {
                        isLoading && loadingIconPosition === 'left' ?

                                <CircularLoading className="button-loading-icon"
                                                 size="small"/>

                            :
                            (
                                iconCls ?
                                    <i className={`button-icon button-icon-left ${iconCls}`}
                                       aria-hidden="true">
                                    :
                                    null
                            )
                    }

                    {
                        itemRenderer && typeof itemRenderer === 'function' ?
                            itemRenderer(data, index)
                            :
                            (
                                renderer && typeof renderer === 'function' ?
                                    renderer(data, index)
                                    :
                                    (
                                        desc ?

                                                    {text}

                                                    {desc}

                                            :
                                            text
                                    )
                            )
                    }

                    {
                        isLoading && loadingIconPosition === 'right' ?
                            <CircularLoading className="button-icon button-icon-right button-loading-icon"
                                             size="small"/>
                            :
                            (
                                rightIconCls ?
                                    <i className={`button-icon button-icon-right ${rightIconCls}`}
                                       aria-hidden="true">
                                    :
                                    null
                            )
                    }

                    {
                        disableTouchRipple || readOnly ?
                            null
                            :
                            <TouchRipple ref="touchRipple"
                                         className={disabled || isLoading ? 'hidden' : ''}
                                         displayCenter={rippleDisplayCenter}/>
                    }

            </TipProvider>
        );

    }
}

ListItem.propTypes = {

    index: PropTypes.number,

    className: PropTypes.string,
    style: PropTypes.object,
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    selectTheme: PropTypes.oneOf(Util.enumerateValue(Theme)),
    selectMode: PropTypes.oneOf(Util.enumerateValue(SelectMode)),

    data: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.object]),
    value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
    text: PropTypes.any,
    desc: PropTypes.string,

    disabled: PropTypes.bool,
    isLoading: PropTypes.bool,
    disableTouchRipple: PropTypes.bool,
    rippleDisplayCenter: PropTypes.bool,
    checked: PropTypes.bool,
    readOnly: PropTypes.bool,

    iconCls: PropTypes.string,
    rightIconCls: PropTypes.string,

    tip: PropTypes.string,
    tipPosition: PropTypes.oneOf(Util.enumerateValue(Position)),

    radioUncheckedIconCls: PropTypes.string,
    radioCheckedIconCls: PropTypes.string,
    checkboxUncheckedIconCls: PropTypes.string,
    checkboxCheckedIconCls: PropTypes.string,
    checkboxIndeterminateIconCls: PropTypes.string,

    itemRenderer: PropTypes.func,
    renderer: PropTypes.func,
    indeterminateCallback: PropTypes.func,

    autoSelect: PropTypes.bool,
    stopSelectClickEventPropagation: PropTypes.bool,

    onClick: PropTypes.func,
    onSelect: PropTypes.func,
    onDeselect: PropTypes.func,
    onMouseEnter: PropTypes.func,
    onMouseLeave: PropTypes.func

};

ListItem.defaultProps = {

    index: 0,

    theme: Theme.DEFAULT,

    selectTheme: Theme.DEFAULT,
    selectMode: SelectMode.SINGLE_SELECT,

    disabled: false,
    isLoading: false,
    disableTouchRipple: false,
    rippleDisplayCenter: false,
    checked: false,
    readOnly: false,

    tipPosition: Position.BOTTOM,

    checkboxUncheckedIconCls: 'far fa-square',
    checkboxCheckedIconCls: 'fas fa-check-square',
    checkboxIndeterminateIconCls: 'fas fa-minus-square',

    autoSelect: true,
    stopSelectClickEventPropagation: false

};

export default ListItem;<commit_msg>update ListItem<commit_after>/**
 * @file ListItem component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import Checkbox from '../Checkbox';
import Radio from '../Radio';
import CircularLoading from '../CircularLoading';
import TipProvider from '../TipProvider';
import TouchRipple from '../TouchRipple';
import Theme from '../Theme';

import Util from '../_vendors/Util';
import Position from '../_statics/Position';
import SelectMode from '../_statics/SelectMode';

class ListItem extends Component {

    static SelectMode = SelectMode;
    static Theme = Theme;

    constructor(props, ...restArgs) {
        super(props, ...restArgs);
    }

    multiSelectChangeHandler = checked => {

        const {onSelect, onDeselect} = this.props;

        if (checked) {
            onSelect && onSelect();
        } else {
            onDeselect && onDeselect();
        }

    };

    singleSelectChangeHandler = () => {
        if (!this.props.checked) {
            const {onSelect} = this.props;
            onSelect && onSelect();
        }
    };

    clickHandler = e => {

        const {disabled, isLoading, readOnly, autoSelect} = this.props;

        if (disabled || isLoading || readOnly) {
            return;
        }

        const {onClick} = this.props;
        onClick && onClick(e);

        if (!autoSelect) {
            return;
        }

        switch (this.props.selectMode) {
            case SelectMode.MULTI_SELECT:
                this.multiSelectChangeHandler(!this.props.checked);
                return;
            case SelectMode.SINGLE_SELECT:
                this.singleSelectChangeHandler();
                return;
        }

    };

    radioCheckHandler = () => {
        this.singleSelectChangeHandler();
    };

    checkboxCheckHandler = () => {
        this.multiSelectChangeHandler(true);
    };

    checkboxUncheckHandler = () => {
        this.multiSelectChangeHandler(false);
    };

    render() {

        const {

                index, className, style, theme, data, text, desc, title, iconCls, rightIconCls, tip, tipPosition,
                disabled, isLoading, disableTouchRipple, rippleDisplayCenter, renderer, itemRenderer, readOnly,

                checked, selectTheme, selectMode, indeterminateCallback, radioUncheckedIconCls, radioCheckedIconCls,
                checkboxUncheckedIconCls, checkboxCheckedIconCls, checkboxIndeterminateIconCls,
                stopSelectClickEventPropagation,

                onMouseEnter, onMouseLeave

            } = this.props,

            listItemClassName = classNames('list-item', {
                [`theme-${theme}`]: theme,
                activated: checked,
                [className]: className
            }),

            loadingIconPosition = (rightIconCls && !iconCls) ? 'right' : 'left';

        return (
            <TipProvider text={tip}
                         position={tipPosition}>

                    {
                        selectMode === SelectMode.SINGLE_SELECT && (radioUncheckedIconCls || radioCheckedIconCls) ?
                            <Radio className="list-item-select"
                                   theme={selectTheme}
                                   checked={checked}
                                   disabled={disabled || isLoading}
                                   uncheckedIconCls={radioUncheckedIconCls}
                                   checkedIconCls={radioCheckedIconCls}
                                   disableTouchRipple={true}
                                   onCheck={this.radioCheckHandler}
                                   onClick={e => stopSelectClickEventPropagation && e.stopPropagation()}/>
                            :
                            null
                    }

                    {
                        selectMode === SelectMode.MULTI_SELECT ?
                            <Checkbox className="list-item-select"
                                      theme={selectTheme}
                                      checked={checked}
                                      indeterminate={indeterminateCallback && indeterminateCallback(data)}
                                      disabled={disabled || isLoading}
                                      uncheckedIconCls={checkboxUncheckedIconCls}
                                      checkedIconCls={checkboxCheckedIconCls}
                                      indeterminateIconCls={checkboxIndeterminateIconCls}
                                      disableTouchRipple={true}
                                      onCheck={this.checkboxCheckHandler}
                                      onUncheck={this.checkboxUncheckHandler}
                                      onClick={e => stopSelectClickEventPropagation && e.stopPropagation()}/>
                            :
                            null
                    }

                    {
                        isLoading && loadingIconPosition === 'left' ?

                                <CircularLoading className="button-loading-icon"
                                                 size="small"/>

                            :
                            (
                                iconCls ?
                                    <i className={`button-icon button-icon-left ${iconCls}`}
                                       aria-hidden="true">
                                    :
                                    null
                            )
                    }

                    {
                        itemRenderer && typeof itemRenderer === 'function' ?
                            itemRenderer(data, index)
                            :
                            (
                                renderer && typeof renderer === 'function' ?
                                    renderer(data, index)
                                    :
                                    (
                                        desc ?

                                                    {text}

                                                    {desc}

                                            :
                                            text
                                    )
                            )
                    }

                    {
                        isLoading && loadingIconPosition === 'right' ?
                            <CircularLoading className="button-icon button-icon-right button-loading-icon"
                                             size="small"/>
                            :
                            (
                                rightIconCls ?
                                    <i className={`button-icon button-icon-right ${rightIconCls}`}
                                       aria-hidden="true">
                                    :
                                    null
                            )
                    }

                    {
                        disableTouchRipple || readOnly ?
                            null
                            :
                            <TouchRipple ref="touchRipple"
                                         className={disabled || isLoading ? 'hidden' : ''}
                                         displayCenter={rippleDisplayCenter}/>
                    }

            </TipProvider>
        );

    }
}

ListItem.propTypes = {

    index: PropTypes.number,

    className: PropTypes.string,
    style: PropTypes.object,
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    selectTheme: PropTypes.oneOf(Util.enumerateValue(Theme)),
    selectMode: PropTypes.oneOf(Util.enumerateValue(SelectMode)),

    data: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.object]),
    value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
    text: PropTypes.any,
    desc: PropTypes.string,
    title: PropTypes.string,

    disabled: PropTypes.bool,
    isLoading: PropTypes.bool,
    disableTouchRipple: PropTypes.bool,
    rippleDisplayCenter: PropTypes.bool,
    checked: PropTypes.bool,
    readOnly: PropTypes.bool,

    iconCls: PropTypes.string,
    rightIconCls: PropTypes.string,

    tip: PropTypes.string,
    tipPosition: PropTypes.oneOf(Util.enumerateValue(Position)),

    radioUncheckedIconCls: PropTypes.string,
    radioCheckedIconCls: PropTypes.string,
    checkboxUncheckedIconCls: PropTypes.string,
    checkboxCheckedIconCls: PropTypes.string,
    checkboxIndeterminateIconCls: PropTypes.string,

    itemRenderer: PropTypes.func,
    renderer: PropTypes.func,
    indeterminateCallback: PropTypes.func,

    autoSelect: PropTypes.bool,
    stopSelectClickEventPropagation: PropTypes.bool,

    onClick: PropTypes.func,
    onSelect: PropTypes.func,
    onDeselect: PropTypes.func,
    onMouseEnter: PropTypes.func,
    onMouseLeave: PropTypes.func

};

ListItem.defaultProps = {

    index: 0,

    theme: Theme.DEFAULT,

    selectTheme: Theme.DEFAULT,
    selectMode: SelectMode.SINGLE_SELECT,

    disabled: false,
    isLoading: false,
    disableTouchRipple: false,
    rippleDisplayCenter: false,
    checked: false,
    readOnly: false,

    tipPosition: Position.BOTTOM,

    checkboxUncheckedIconCls: 'far fa-square',
    checkboxCheckedIconCls: 'fas fa-check-square',
    checkboxIndeterminateIconCls: 'fas fa-minus-square',

    autoSelect: true,
    stopSelectClickEventPropagation: false

};

export default ListItem;<|endoftext|>


<commit_before>/**
 * @file ListItem component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import Checkbox from '../Checkbox';
import Radio from '../Radio';
import CircularLoading from '../CircularLoading';
import TipProvider from '../TipProvider';
import TouchRipple from '../TouchRipple';
import Theme from '../Theme';

import Util from '../_vendors/Util';
import Position from '../_statics/Position';
import SelectMode from '../_statics/SelectMode';

class ListItem extends Component {

    static SelectMode = SelectMode;
    static Theme = Theme;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.state = {
            checked: props.checked
        };

        this.checkboxChangeHandler = ::this.checkboxChangeHandler;
        this.radioChangeHandler = ::this.radioChangeHandler;
        this.touchTapHandler = ::this.touchTapHandler;

    }

    checkboxChangeHandler(checked) {
        this.setState({
            checked
        }, () => {

            const {onSelect, onDeselect} = this.props;

            if (checked) {
                onSelect && onSelect();
            } else {
                onDeselect && onDeselect();
            }

        });
    }

    radioChangeHandler() {

        const {checked} = this.state;

        if (!checked) {
            this.setState({
                checked: true
            }, () => {
                const {onSelect} = this.props;
                onSelect && onSelect();
            });
        }

    }

    touchTapHandler(e) {

        e.preventDefault();

        const {disabled, isLoading, readOnly} = this.props;

        if (disabled || isLoading || readOnly) {
            return;
        }

        const {onTouchTap} = this.props;
        onTouchTap && onTouchTap(e);

        switch (this.props.selectMode) {
            case SelectMode.MULTI_SELECT:
                this.checkboxChangeHandler(!this.state.checked);
                return;
            case SelectMode.SINGLE_SELECT:
                this.radioChangeHandler();
                return;
        }

    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.checked !== this.state.checked) {
            this.setState({
                checked: nextProps.checked
            });
        }
    }

    render() {

        const {

                index, className, style, theme, data, text, desc, iconCls, rightIconCls, tip, tipPosition,
                disabled, isLoading, disableTouchRipple, rippleDisplayCenter, renderer, itemRenderer, readOnly,

                selectTheme, selectMode, radioUncheckedIconCls, radioCheckedIconCls,
                checkboxUncheckedIconCls, checkboxCheckedIconCls, checkboxIndeterminateIconCls,

                onMouseEnter, onMouseLeave

            } = this.props,
            {checked} = this.state,

            listItemClassName = classNames('list-item', {
                [`theme-${theme}`]: theme,
                activated: checked,
                [className]: className
            }),

            loadingIconPosition = (rightIconCls && !iconCls) ? 'right' : 'left';

        return (
            <TipProvider className='block'
                         text={tip}
                         position={tipPosition}>

                    {
                        selectMode === SelectMode.SINGLE_SELECT && (radioUncheckedIconCls || radioCheckedIconCls) ?
                            <Radio className="list-item-select"
                                   theme={selectTheme}
                                   checked={checked}
                                   disabled={disabled || isLoading}
                                   uncheckedIconCls={radioUncheckedIconCls}
                                   checkedIconCls={radioCheckedIconCls}
                                   disableTouchRipple={true}/>
                            :
                            null
                    }

                    {
                        selectMode === SelectMode.MULTI_SELECT ?
                            <Checkbox className="list-item-select"
                                      theme={selectTheme}
                                      checked={checked}
                                      disabled={disabled || isLoading}
                                      uncheckedIconCls={checkboxUncheckedIconCls}
                                      checkedIconCls={checkboxCheckedIconCls}
                                      indeterminateIconCls={checkboxIndeterminateIconCls}
                                      disableTouchRipple={true}/>
                            :
                            null
                    }

                    {
                        isLoading && loadingIconPosition === 'left' ?

                                <CircularLoading className="button-loading-icon"
                                                 size="small"/>

                            :
                            (
                                iconCls ?
                                    <i className={`button-icon button-icon-left ${iconCls}`}
                                       aria-hidden="true">
                                    :
                                    null
                            )
                    }

                    {
                        itemRenderer && typeof itemRenderer === 'function' ?
                            itemRenderer(data, index)
                            :
                            (
                                renderer && typeof renderer === 'function' ?
                                    renderer(data, index)
                                    :
                                    (
                                        desc ?

                                                    {text}

                                                    {desc}

                                            :
                                            text
                                    )
                            )
                    }

                    {
                        isLoading && loadingIconPosition === 'right' ?
                            <CircularLoading className="button-icon button-icon-right button-loading-icon"
                                             size="small"/>
                            :
                            (
                                rightIconCls ?
                                    <i className={`button-icon button-icon-right ${rightIconCls}`}
                                       aria-hidden="true">
                                    :
                                    null
                            )
                    }

                    {
                        disableTouchRipple || readOnly ?
                            null
                            :
                            <TouchRipple ref="touchRipple"
                                         className={disabled || isLoading ? 'hidden' : ''}
                                         displayCenter={rippleDisplayCenter}/>
                    }

            </TipProvider>
        );

    }
};

ListItem.propTypes = {

    index: PropTypes.number,

    className: PropTypes.string,
    style: PropTypes.object,
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    selectTheme: PropTypes.oneOf(Util.enumerateValue(Theme)),
    selectMode: PropTypes.oneOf(Util.enumerateValue(SelectMode)),

    data: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.object]),
    value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
    text: PropTypes.any,
    desc: PropTypes.string,

    disabled: PropTypes.bool,
    isLoading: PropTypes.bool,
    disableTouchRipple: PropTypes.bool,
    rippleDisplayCenter: PropTypes.bool,
    checked: PropTypes.bool,
    readOnly: PropTypes.bool,

    iconCls: PropTypes.string,
    rightIconCls: PropTypes.string,

    tip: PropTypes.string,
    tipPosition: PropTypes.oneOf(Util.enumerateValue(Position)),

    radioUncheckedIconCls: PropTypes.string,
    radioCheckedIconCls: PropTypes.string,
    checkboxUncheckedIconCls: PropTypes.string,
    checkboxCheckedIconCls: PropTypes.string,
    checkboxIndeterminateIconCls: PropTypes.string,

    itemRenderer: PropTypes.func,
    renderer: PropTypes.func,

    onTouchTap: PropTypes.func,
    onSelect: PropTypes.func,
    onDeselect: PropTypes.func,
    onMouseEnter: PropTypes.func,
    onMouseLeave: PropTypes.func

};

ListItem.defaultProps = {

    index: 0,

    className: null,
    style: null,
    theme: Theme.DEFAULT,

    selectTheme: Theme.DEFAULT,
    selectMode: SelectMode.SINGLE_SELECT,

    data: null,
    value: null,
    text: null,
    desc: null,

    disabled: false,
    isLoading: false,
    disableTouchRipple: false,
    rippleDisplayCenter: false,
    checked: false,
    readOnly: false,

    iconCls: null,
    rightIconCls: null,

    tip: null,
    tipPosition: Position.BOTTOM,

    radioUncheckedIconCls: null,
    radioCheckedIconCls: null,
    checkboxUncheckedIconCls: 'far fa-square',
    checkboxCheckedIconCls: 'fas fa-check-square',
    checkboxIndeterminateIconCls: 'fas fa-minus-square'

};

export default ListItem;<commit_msg>update ListItem<commit_after>/**
 * @file ListItem component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import Checkbox from '../Checkbox';
import Radio from '../Radio';
import CircularLoading from '../CircularLoading';
import TipProvider from '../TipProvider';
import TouchRipple from '../TouchRipple';
import Theme from '../Theme';

import PureRender from '../_vendors/PureRender';
import Util from '../_vendors/Util';
import Position from '../_statics/Position';
import SelectMode from '../_statics/SelectMode';

@PureRender
class ListItem extends Component {

    static SelectMode = SelectMode;
    static Theme = Theme;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.state = {
            checked: props.checked
        };

        this.checkboxChangeHandler = ::this.checkboxChangeHandler;
        this.radioChangeHandler = ::this.radioChangeHandler;
        this.touchTapHandler = ::this.touchTapHandler;

    }

    checkboxChangeHandler(checked) {
        this.setState({
            checked
        }, () => {

            const {onSelect, onDeselect} = this.props;

            if (checked) {
                onSelect && onSelect();
            } else {
                onDeselect && onDeselect();
            }

        });
    }

    radioChangeHandler() {

        const {checked} = this.state;

        if (!checked) {
            this.setState({
                checked: true
            }, () => {
                const {onSelect} = this.props;
                onSelect && onSelect();
            });
        }

    }

    touchTapHandler(e) {

        e.preventDefault();

        const {disabled, isLoading, readOnly} = this.props;

        if (disabled || isLoading || readOnly) {
            return;
        }

        const {onTouchTap} = this.props;
        onTouchTap && onTouchTap(e);

        switch (this.props.selectMode) {
            case SelectMode.MULTI_SELECT:
                this.checkboxChangeHandler(!this.state.checked);
                return;
            case SelectMode.SINGLE_SELECT:
                this.radioChangeHandler();
                return;
        }

    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.checked !== this.state.checked) {
            this.setState({
                checked: nextProps.checked
            });
        }
    }

    render() {

        const {

                index, className, style, theme, data, text, desc, iconCls, rightIconCls, tip, tipPosition,
                disabled, isLoading, disableTouchRipple, rippleDisplayCenter, renderer, itemRenderer, readOnly,

                selectTheme, selectMode, radioUncheckedIconCls, radioCheckedIconCls,
                checkboxUncheckedIconCls, checkboxCheckedIconCls, checkboxIndeterminateIconCls,

                onMouseEnter, onMouseLeave

            } = this.props,
            {checked} = this.state,

            listItemClassName = classNames('list-item', {
                [`theme-${theme}`]: theme,
                activated: checked,
                [className]: className
            }),

            loadingIconPosition = (rightIconCls && !iconCls) ? 'right' : 'left';

        return (
            <TipProvider className='block'
                         text={tip}
                         position={tipPosition}>

                    {
                        selectMode === SelectMode.SINGLE_SELECT && (radioUncheckedIconCls || radioCheckedIconCls) ?
                            <Radio className="list-item-select"
                                   theme={selectTheme}
                                   checked={checked}
                                   disabled={disabled || isLoading}
                                   uncheckedIconCls={radioUncheckedIconCls}
                                   checkedIconCls={radioCheckedIconCls}
                                   disableTouchRipple={true}/>
                            :
                            null
                    }

                    {
                        selectMode === SelectMode.MULTI_SELECT ?
                            <Checkbox className="list-item-select"
                                      theme={selectTheme}
                                      checked={checked}
                                      disabled={disabled || isLoading}
                                      uncheckedIconCls={checkboxUncheckedIconCls}
                                      checkedIconCls={checkboxCheckedIconCls}
                                      indeterminateIconCls={checkboxIndeterminateIconCls}
                                      disableTouchRipple={true}/>
                            :
                            null
                    }

                    {
                        isLoading && loadingIconPosition === 'left' ?

                                <CircularLoading className="button-loading-icon"
                                                 size="small"/>

                            :
                            (
                                iconCls ?
                                    <i className={`button-icon button-icon-left ${iconCls}`}
                                       aria-hidden="true">
                                    :
                                    null
                            )
                    }

                    {
                        itemRenderer && typeof itemRenderer === 'function' ?
                            itemRenderer(data, index)
                            :
                            (
                                renderer && typeof renderer === 'function' ?
                                    renderer(data, index)
                                    :
                                    (
                                        desc ?

                                                    {text}

                                                    {desc}

                                            :
                                            text
                                    )
                            )
                    }

                    {
                        isLoading && loadingIconPosition === 'right' ?
                            <CircularLoading className="button-icon button-icon-right button-loading-icon"
                                             size="small"/>
                            :
                            (
                                rightIconCls ?
                                    <i className={`button-icon button-icon-right ${rightIconCls}`}
                                       aria-hidden="true">
                                    :
                                    null
                            )
                    }

                    {
                        disableTouchRipple || readOnly ?
                            null
                            :
                            <TouchRipple ref="touchRipple"
                                         className={disabled || isLoading ? 'hidden' : ''}
                                         displayCenter={rippleDisplayCenter}/>
                    }

            </TipProvider>
        );

    }
};

process.env.NODE_ENV !== 'production' && (ListItem.propTypes = {

    index: PropTypes.number,

    className: PropTypes.string,
    style: PropTypes.object,
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    selectTheme: PropTypes.oneOf(Util.enumerateValue(Theme)),
    selectMode: PropTypes.oneOf(Util.enumerateValue(SelectMode)),

    data: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.object]),
    value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
    text: PropTypes.any,
    desc: PropTypes.string,

    disabled: PropTypes.bool,
    isLoading: PropTypes.bool,
    disableTouchRipple: PropTypes.bool,
    rippleDisplayCenter: PropTypes.bool,
    checked: PropTypes.bool,
    readOnly: PropTypes.bool,

    iconCls: PropTypes.string,
    rightIconCls: PropTypes.string,

    tip: PropTypes.string,
    tipPosition: PropTypes.oneOf(Util.enumerateValue(Position)),

    radioUncheckedIconCls: PropTypes.string,
    radioCheckedIconCls: PropTypes.string,
    checkboxUncheckedIconCls: PropTypes.string,
    checkboxCheckedIconCls: PropTypes.string,
    checkboxIndeterminateIconCls: PropTypes.string,

    itemRenderer: PropTypes.func,
    renderer: PropTypes.func,

    onTouchTap: PropTypes.func,
    onSelect: PropTypes.func,
    onDeselect: PropTypes.func,
    onMouseEnter: PropTypes.func,
    onMouseLeave: PropTypes.func

});

ListItem.defaultProps = {

    index: 0,

    theme: Theme.DEFAULT,

    selectTheme: Theme.DEFAULT,
    selectMode: SelectMode.SINGLE_SELECT,

    disabled: false,
    isLoading: false,
    disableTouchRipple: false,
    rippleDisplayCenter: false,
    checked: false,
    readOnly: false,

    tipPosition: Position.BOTTOM,

    checkboxUncheckedIconCls: 'far fa-square',
    checkboxCheckedIconCls: 'fas fa-check-square',
    checkboxIndeterminateIconCls: 'fas fa-minus-square'

};

export default ListItem;<|endoftext|>