UNPKG

react-selector

Version:

A React component that allows to filter and move item between two lists.

201 lines (191 loc) 6.52 kB
// Generated by CoffeeScript 1.9.1 (function() { var ARROW_DOWN, ARROW_UP, BACKSPACE, ENTER, ESCAPE, React, ReactSelector; React = require('react'); ARROW_UP = 38; ARROW_DOWN = 40; ENTER = 13; BACKSPACE = 8; ESCAPE = 27; ReactSelector = React.createClass({ getInitialState: function() { var query; query = ""; return { filtered_items_on_top: this.props.filtered_items_on_top || false, show_filtered_items: false, query: query, active_item_index: 0, filtered: this._calculateFiltered(this.props.universe, this.props.selected, query), selected: [].concat(this.props.selected).sort(this.props.compare) }; }, componentWillReceiveProps: function(nextProps) { var active_item_index, filtered, query, selected; query = ""; active_item_index = 0; selected = nextProps.selected; filtered = this._calculateFiltered(nextProps.universe, selected, query); return this.setState({ active_item_index: active_item_index, query: query, filtered: filtered, selected: selected.sort(this.props.compare) }); }, componentDidUpdate: function() { if (this.refs.active) { return this.refs.active.getDOMNode().scrollIntoView(false); } }, _calculateFiltered: function(universe, selected, query) { var filtered, item, j, len; filtered = []; for (j = 0, len = universe.length; j < len; j++) { item = universe[j]; if (!this.__arrayContainsObject(selected, item)) { if (item.name.toLowerCase().trim().indexOf(query.toLowerCase().trim()) !== -1) { filtered.push(item); } } } filtered.sort(this.props.compare); return filtered; }, __arrayContainsObject: function(array, object) { var j, len, o; for (j = 0, len = array.length; j < len; j++) { o = array[j]; if (object.id === o.id) { return true; } } return false; }, _getItems: function(list, filtering) { var i, is_active_item, item, item_class_name, item_component, items, j, len; if (filtering == null) { filtering = false; } items = []; for (i = j = 0, len = list.length; j < len; i = ++j) { item = list[i]; item_class_name = "item"; is_active_item = this.state.active_item_index === i; if (filtering && is_active_item) { item_class_name += " active"; } item_component = React.createElement(item.renderer, item.props); items.push(React.DOM.div({ ref: is_active_item ? "active" : void 0, key: item.id, onClick: this._onItemToggle.bind(null, item), className: item_class_name }, item_component)); } return items; }, _onItemToggle: function(item) { var input; item.onToggle(item.id); clearTimeout(this._timeout); input = this.refs.input.getDOMNode(); return input.focus(); }, _processActions: function(event) { var active_item, active_item_index, filtered, key, selected; key = event.keyCode; active_item_index = this.state.active_item_index; filtered = this.state.filtered; selected = this.state.selected; if (key === ARROW_DOWN) { this._showFilteredItems(); if (active_item_index < filtered.length - 1) { return this.setState({ active_item_index: active_item_index + 1 }); } } else if (key === ARROW_UP) { this._showFilteredItems(); if (active_item_index > 0) { return this.setState({ active_item_index: active_item_index - 1 }); } } else if (key === ENTER) { active_item = filtered[active_item_index]; if (active_item) { this._onItemToggle(active_item); } return event.preventDefault(); } else if (key === BACKSPACE && this.state.query === '' && selected.length > 0) { return this._onItemToggle(selected[selected.length - 1]); } else if (key === ESCAPE) { return this._hideFilteredItems(); } }, _processQuery: function(event) { var active_item_index, filtered, input, query; this._showFilteredItems(); input = event.target; query = input.value; if (query === this.state.query) { return; } filtered = this._calculateFiltered(this.props.universe, this.state.selected, query); active_item_index = this.state.active_item_index; if (active_item_index >= filtered.length && filtered.length > 0) { active_item_index = filtered.length - 1; } return this.setState({ query: query, filtered: filtered, active_item_index: active_item_index }); }, _showFilteredItems: function() { if (this.props.onFocus) { this.props.onFocus(); } return this.setState({ show_filtered_items: true }); }, _hideFilteredItems: function() { return this._timeout = setTimeout(((function(_this) { return function() { if (_this.props.onBlur) { _this.props.onBlur(); } return _this.setState({ show_filtered_items: false }); }; })(this)), 0); }, render: function() { var filtered_items, filtered_items_section, selected_items; filtered_items = this._getItems(this.state.filtered, true); selected_items = this._getItems(this.state.selected); filtered_items_section = React.DOM.div({ className: "universe" }, React.DOM.div({ className: "container" }, filtered_items)); return React.DOM.div({}, this.state.show_filtered_items && this.state.filtered_items_on_top ? filtered_items_section : void 0, React.DOM.div({ className: "selected" }, React.DOM.div({ className: "container" }, selected_items, React.DOM.input({ ref: "input", value: this.state.query, placeholder: this.props.placeholder, onKeyDown: this._processActions, onChange: this._processQuery, onFocus: this._showFilteredItems, onBlur: this._hideFilteredItems }))), this.state.show_filtered_items && !this.state.filtered_items_on_top ? filtered_items_section : void 0); } }); module.exports = ReactSelector; }).call(this);