import React from "react" import ajax from "misago/services/ajax" import snackbar from "misago/services/snackbar" import misago from "misago" import cleanResults from "./clean-results" import Dropdown from "./dropdown" export default class extends React.Component { constructor() { super() this.state = { isLoading: false, isOpen: false, query: "", results: [], } this.intervalId = null } componentDidMount() { document.addEventListener("mousedown", this.onDocumentMouseDown) document.addEventListener("keydown", this.onEscape) } componentWillUnmount() { document.removeEventListener("mousedown", this.onDocumentMouseDown) document.removeEventListener("keydown", this.onEscape) } onToggle = (ev) => { this.setState((prevState, props) => { if (!prevState.isOpen) { window.setTimeout(() => { this.container.querySelector("input").focus() }, 100) } return { isOpen: !prevState.isOpen } }) } onDocumentMouseDown = (ev) => { let closeResults = true let node = ev.target while (node !== null && node !== document) { if (node === this.container) { closeResults = false return } node = node.parentNode } if (closeResults) { this.setState({ isOpen: false }) } } onEscape = (ev) => { if (ev.key === "Escape") { this.setState({ isOpen: false }) } } onChange = (ev) => { const query = ev.target.value this.setState({ query }) this.loadResults(query.trim()) } loadResults(query) { if (!query.length) return const delay = 300 + Math.random() * 300 if (this.intervalId) { window.clearTimeout(this.intervalId) } this.setState({ isLoading: true }) this.intervalId = window.setTimeout(() => { ajax.get(misago.get("SEARCH_API"), { q: query }).then( (data) => { this.setState({ intervalId: null, isLoading: false, results: cleanResults(data), }) }, (rejection) => { snackbar.apiError(rejection) this.setState({ intervalId: null, isLoading: false, results: [], }) } ) }, delay) } render() { let className = "navbar-search dropdown" if (this.state.isOpen) className += " open" return ( <div className={className} ref={(container) => (this.container = container)} > <a aria-haspopup="true" aria-expanded="false" className="navbar-icon" data-toggle="dropdown" href={misago.get("SEARCH_URL")} onClick={this.onToggle} > <i className="material-icon">search</i> </a> <Dropdown isLoading={this.state.isLoading} onChange={this.onChange} results={this.state.results} query={this.state.query} /> </div> ) } }