UNPKG

ssc-refer

Version:
909 lines (782 loc) 29.2 kB
'use strict'; exports.__esModule = true; var _extends2 = require('babel-runtime/helpers/extends'); var _extends3 = _interopRequireDefault(_extends2); var _stringify = require('babel-runtime/core-js/json/stringify'); var _stringify2 = _interopRequireDefault(_stringify); var _classnames = require('classnames'); var _classnames2 = _interopRequireDefault(_classnames); var _lodash = require('lodash'); var _reactOnclickoutside = require('react-onclickoutside'); var _reactOnclickoutside2 = _interopRequireDefault(_reactOnclickoutside); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); var _ClearButton = require('./ClearButton.react'); var _ClearButton2 = _interopRequireDefault(_ClearButton); var _Loader = require('./Loader.react'); var _Loader2 = _interopRequireDefault(_Loader); var _Overlay = require('./Overlay.react'); var _Overlay2 = _interopRequireDefault(_Overlay); var _TokenizerInput = require('./TokenizerInput.react'); var _TokenizerInput2 = _interopRequireDefault(_TokenizerInput); var _TypeaheadInput = require('./TypeaheadInput.react'); var _TypeaheadInput2 = _interopRequireDefault(_TypeaheadInput); var _TypeaheadMenu = require('./TypeaheadMenu.react'); var _TypeaheadMenu2 = _interopRequireDefault(_TypeaheadMenu); var _ReferList = require('./ReferList.react'); var _ReferList2 = _interopRequireDefault(_ReferList); var _ReferTable = require('./ReferTable.react'); var _ReferTable2 = _interopRequireDefault(_ReferTable); var _ReferTreeTable = require('./ReferTreeTable.react'); var _ReferTreeTable2 = _interopRequireDefault(_ReferTreeTable); var _addCustomOption = require('./utils/addCustomOption'); var _addCustomOption2 = _interopRequireDefault(_addCustomOption); var _defaultFilterBy = require('./utils/defaultFilterBy'); var _defaultFilterBy2 = _interopRequireDefault(_defaultFilterBy); var _getHintText = require('./utils/getHintText'); var _getHintText2 = _interopRequireDefault(_getHintText); var _getInputText = require('./utils/getInputText'); var _getInputText2 = _interopRequireDefault(_getInputText); var _getOptionLabel = require('./utils/getOptionLabel'); var _getOptionLabel2 = _interopRequireDefault(_getOptionLabel); var _getTruncatedOptions = require('./utils/getTruncatedOptions'); var _getTruncatedOptions2 = _interopRequireDefault(_getTruncatedOptions); var _warn = require('./utils/warn'); var _warn2 = _interopRequireDefault(_warn); var _superagent = require('superagent'); var _superagent2 = _interopRequireDefault(_superagent); var _keyCode = require('./utils/keyCode'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } /** * Refer */ var Refers = _react2['default'].createClass({ displayName: 'Refers', propTypes: { /** * Allows the creation of new selections on the fly. Note that any new items * will be added to the list of selections, but not the list of original * options unless handled as such by `Typeahead`'s parent. */ allowNew: _propTypes2['default'].bool, /** * Autofocus the input when the component initially mounts. */ autoFocus: _propTypes2['default'].bool, /** * Whether to render the menu inline or attach to `document.body`. */ bodyContainer: _propTypes2['default'].bool, /** * Whether or not filtering should be case-sensitive. */ caseSensitive: _propTypes2['default'].bool, /** * Displays a button to clear the input when there are selections. */ clearButton: _propTypes2['default'].bool, /** * Specify any pre-selected options. Use only if you want the component to * be uncontrolled. */ defaultSelected: _propTypes2['default'].array, /** * Specify whether the menu should appear above the input. */ dropup: _propTypes2['default'].bool, /** * Either an array of fields in `option` to search, or a custom filtering * callback. */ filterBy: _propTypes2['default'].oneOfType([_propTypes2['default'].arrayOf(_propTypes2['default'].string.isRequired), _propTypes2['default'].func]), /** * Whether the filter should ignore accents and other diacritical marks. */ ignoreDiacritics: _propTypes2['default'].bool, /** * Indicate whether an asynchromous data fetch is happening. */ /** * Indicate whether an asynchromous data fetch is happening. */ isLoading: _propTypes2['default'].bool, /** * Specify the option key to use for display or a function returning the * display string. By default, the selector will use the `label` key. */ labelKey: _propTypes2['default'].oneOfType([_propTypes2['default'].string, _propTypes2['default'].func]), /** * Maximum number of results to display by default. Mostly done for * performance reasons so as not to render too many DOM nodes in the case of * large data sets. */ maxResults: _propTypes2['default'].number, /** * Number of input characters that must be entered before showing results. */ minLength: _propTypes2['default'].number, /** * Whether or not multiple selections are allowed. */ multiple: _propTypes2['default'].bool, /** * Callback fired when the input is blurred. Receives an event. */ onBlur: _propTypes2['default'].func, /** * Callback fired whenever items are added or removed. Receives an array of * the selected options. */ onChange: _propTypes2['default'].func, /** * Callback fired when the input is focused. Receives an event. */ onFocus: _propTypes2['default'].func, /** * Callback for handling changes to the user-input text. */ onInputChange: _propTypes2['default'].func, /** * Give user the ability to display additional results if the number of * results exceeds `maxResults`. */ paginate: _propTypes2['default'].bool, /** * Callback for custom menu rendering. */ renderMenu: _propTypes2['default'].func, /** * The selected option(s) displayed in the input. Use this prop if you want * to control the component via its parent. */ selected: _propTypes2['default'].array, /** * set refer data url ,for example `http://YOURHOST/queryRefJSON` */ referDataUrl: _propTypes2['default'].string.isRequired, /** * set refOptions ,for example `{"refCode":"dept","refType":"tree","rootName":"部门"}` */ referConditions: _propTypes2['default'].object.isRequired, /** * Is debug mode. */ requestHeader: _propTypes2['default'].object, /** * set refer type, for example: list, cascader, table, treetable, default type is list. */ referType: _propTypes2['default'].string.isRequired, /** * set custom columns for table display, for example `[{"field":"name", "label":"名称"},{"field":"code","label":"编码"},{"field":"addr","label":"地址"}]` */ tableColumns: _propTypes2['default'].array, /** * set refer whether to display the Disabled button */ showDisabledBtn: _propTypes2['default'].bool, /** * 显示停用按钮名称,默认值:'显示停用' */ showDisabledBtnText: _propTypes2['default'].string, /** * 隐藏停用按钮名称,默认值:'隐藏停用' */ showDisabledBtnText_Not: _propTypes2['default'].string, /** * set refer whether to display Disabled data */ showDisabled: _propTypes2['default'].bool, /** * Is debug mode. */ debugMode: _propTypes2['default'].bool, /** * search icon style */ searchIcon: _propTypes2['default'].string }, getDefaultProps: function getDefaultProps() { return { allowNew: false, autoFocus: false, bodyContainer: false, caseSensitive: false, clearButton: false, defaultSelected: [], dropup: false, filterBy: [], ignoreDiacritics: true, isLoading: false, labelKey: 'label', maxResults: 100, minLength: 0, multiple: false, onBlur: _lodash.noop, onChange: _lodash.noop, onFocus: _lodash.noop, onInputChange: _lodash.noop, paginate: true, selected: [], referDataUrl: 'http://172.20.4.220/ficloud/refbase_ctr/queryRefJSON', referConditions: {}, requestHeader: {}, referType: 'list', debugMode: false, showDisabledBtn: false, showDisabledBtnText: '显示停用', showDisabledBtnText_Not: '隐藏停用', showDisabled: false, searchIcon: 'glyphicon glyphicon-search refer-search-icon' }; }, childContextTypes: { activeIndex: _propTypes2['default'].number.isRequired, onActiveItemChange: _propTypes2['default'].func.isRequired, onInitialItemChange: _propTypes2['default'].func.isRequired, onMenuItemClick: _propTypes2['default'].func.isRequired }, getChildContext: function getChildContext() { return { activeIndex: this.state.activeIndex, onActiveItemChange: this._handleActiveItemChange, onInitialItemChange: this._handleInitialItemChange, onMenuItemClick: this._handleAddOption }; }, getInitialState: function getInitialState() { var _props = this.props, defaultSelected = _props.defaultSelected, maxResults = _props.maxResults, showDisabled = _props.showDisabled; var selected = this.props.selected.slice(); if (defaultSelected && defaultSelected.length) { selected = defaultSelected; } return { activeIndex: -1, activeItem: null, initialItem: null, selected: selected, showMenu: false, shownResults: maxResults, text: '', isAbove: true, responseData: [], styleStatus: { position: 'relative' }, showDisabled: showDisabled === undefined ? false : showDisabled }; }, componentWillMount: function componentWillMount() { var _props2 = this.props, allowNew = _props2.allowNew, labelKey = _props2.labelKey; (0, _warn2['default'])(!(typeof labelKey === 'function' && allowNew), '`labelKey` must be a string if creating new options is allowed.'); }, componentDidMount: function componentDidMount() { this.props.autoFocus && this.focus(); }, componentWillReceiveProps: function componentWillReceiveProps(nextProps) { var multiple = nextProps.multiple, selected = nextProps.selected; if (!(0, _lodash.isEqual)(selected, this.props.selected)) { // If new selections are passed in via props, treat the component as a // controlled input. this.setState({ selected: selected }); } if (multiple !== this.props.multiple) { this.setState({ text: '' }); } }, render: function render() { var _props3 = this.props, allowNew = _props3.allowNew, className = _props3.className, dropup = _props3.dropup, labelKey = _props3.labelKey, paginate = _props3.paginate, searchIcon = _props3.searchIcon; var _state = this.state, shownResults = _state.shownResults, text = _state.text; // First filter the results by the input string. var results = this._getFilteredResults(); // This must come before we truncate. var shouldPaginate = paginate && results.length > shownResults; // Truncate if necessary. if (shouldPaginate) { results = (0, _getTruncatedOptions2['default'])(results, shownResults); } // Add the custom option. if (allowNew) { results = (0, _addCustomOption2['default'])(results, text, labelKey); } return _react2['default'].createElement( 'div', { className: (0, _classnames2['default'])('bootstrap-typeahead', 'open', { 'dropup': dropup }, className), style: this.state.styleStatus }, this._renderInput(results), this._renderAux(), this._renderMenu(results, shouldPaginate) ); }, _getFilteredResults: function _getFilteredResults() { var _props4 = this.props, caseSensitive = _props4.caseSensitive, filterBy = _props4.filterBy, ignoreDiacritics = _props4.ignoreDiacritics, labelKey = _props4.labelKey, minLength = _props4.minLength, multiple = _props4.multiple; var _state2 = this.state, selected = _state2.selected, text = _state2.text; if (text.length < minLength) { return []; } var callback = Array.isArray(filterBy) ? function (option) { return (0, _defaultFilterBy2['default'])(option, text, labelKey, multiple && !!(0, _lodash.find)(selected, function (o) { return (0, _lodash.isEqual)(o, option); }), { caseSensitive: caseSensitive, ignoreDiacritics: ignoreDiacritics, fields: filterBy }); } : function (option) { return filterBy(option, text); }; return this.state.responseData.filter(callback); }, getFilteredSelected: function getFilteredSelected(responseData, selectedData) { var result = void 0; result = responseData.filter(function (item) { var flag = false; selectedData.map(function (obj) { if ((0, _stringify2['default'])(obj) === (0, _stringify2['default'])(item)) flag = true; }); return !flag; }); return result; }, _loadData: function _loadData() { var _props5 = this.props, referDataUrl = _props5.referDataUrl, referConditions = _props5.referConditions, requestHeader = _props5.requestHeader, debugMode = _props5.debugMode, selected = _props5.selected; var _this = this; referConditions['disableshow'] = _this.state.showDisabled; _superagent2['default'].post(referDataUrl).set(requestHeader).set('Content-Type', 'application/json').send((0, _stringify2['default'])(referConditions)).end(function (err, res) { if (err || !res.ok) { if (debugMode) console.log('network error!' + err); } else { var data = JSON.parse(res.text); if (data['success'] === undefined) { if (debugMode) console.log('response data format is error,for example: no success key'); return false; } if (!data['success']) { if (debugMode) console.log('response data success is false' + data['message']); } else { if ((0, _lodash.isArray)(data.data) && data.data.length >= 0) { _this.setState({ responseData: _this.getFilteredSelected(data.data, selected) }); } else { if (debugMode) console.log('Message:' + 'Data format error, maybe no data !'); } } } }); }, blur: function blur() { this.refs.input.blur(); this._hideDropdown(); }, /** * Public method to allow external clearing of the input. Clears both text * and selection(s). */ clear: function clear() { var _getInitialState = this.getInitialState(), activeIndex = _getInitialState.activeIndex, activeItem = _getInitialState.activeItem, showMenu = _getInitialState.showMenu; var selected = []; var text = ''; this.setState({ activeIndex: activeIndex, activeItem: activeItem, selected: selected, showMenu: showMenu, text: text }); this.props.onChange(selected); this.props.onInputChange(text); }, focus: function focus() { this.refs.input.focus(); }, getData: function getData() { return this.state.selected; }, getInputTextValue: function getInputTextValue() { var _props6 = this.props, bsSize = _props6.bsSize, disabled = _props6.disabled, labelKey = _props6.labelKey, minLength = _props6.minLength, multiple = _props6.multiple, name = _props6.name, placeholder = _props6.placeholder, renderToken = _props6.renderToken; var _state3 = this.state, activeIndex = _state3.activeIndex, activeItem = _state3.activeItem, initialItem = _state3.initialItem, selected = _state3.selected, text = _state3.text; return (0, _getInputText2['default'])({ activeItem: activeItem, labelKey: labelKey, multiple: multiple, selected: selected, text: text }); }, hideRefers: function hideRefers() { this.setState({ styleStatus: { display: 'none' } }); }, showRefers: function showRefers() { this.setState({ styleStatus: { position: 'relative' } }); }, _renderInput: function _renderInput(results) { var _this2 = this; var _props7 = this.props, bsSize = _props7.bsSize, disabled = _props7.disabled, labelKey = _props7.labelKey, minLength = _props7.minLength, multiple = _props7.multiple, name = _props7.name, placeholder = _props7.placeholder, renderToken = _props7.renderToken, searchIcon = _props7.searchIcon, showDisabledBtn = _props7.showDisabledBtn, showDisabledBtnText = _props7.showDisabledBtnText, showDisabledBtnText_Not = _props7.showDisabledBtnText_Not; var _state4 = this.state, activeIndex = _state4.activeIndex, activeItem = _state4.activeItem, initialItem = _state4.initialItem, selected = _state4.selected, text = _state4.text; var Input = multiple ? _TokenizerInput2['default'] : _TypeaheadInput2['default']; var inputProps = { bsSize: bsSize, disabled: disabled, name: name, placeholder: placeholder, renderToken: renderToken }; return _react2['default'].createElement( 'div', { className: 'input-group' }, _react2['default'].createElement(Input, (0, _extends3['default'])({}, inputProps, { activeIndex: activeIndex, activeItem: activeItem, hasAux: !!this._renderAux(), hintText: (0, _getHintText2['default'])({ activeItem: activeItem, initialItem: initialItem, labelKey: labelKey, minLength: minLength, selected: selected, text: text }), initialItem: initialItem, labelKey: labelKey, onAdd: this._handleAddOption, onBlur: this._handleBlur, onChange: this._handleTextChange, onFocus: this._handleFocus.bind(this, disabled), onKeyDown: function onKeyDown(e) { return _this2._handleKeydown(results, e); }, onRemove: this._handleRemoveOption, options: results, ref: 'input', selected: selected.slice(), value: (0, _getInputText2['default'])({ activeItem: activeItem, labelKey: labelKey, multiple: multiple, selected: selected, text: text }) })), _react2['default'].createElement( 'span', { className: "input-group-addon cursor-style", onClick: this._handleFocus.bind(this, disabled), style: disabled ? { 'cursor': 'no-drop' } : {} }, _react2['default'].createElement('span', { className: (0, _classnames2['default'])(searchIcon) }) ), showDisabledBtn === false ? null : _react2['default'].createElement( 'span', { className: 'input-group-addon cursor-style', style: disabled ? { 'cursor': 'no-drop' } : {}, title: this.state.showDisabled ? showDisabledBtnText_Not || '隐藏停用' : showDisabledBtnText || '显示停用', onClick: this._handleEnable.bind(this, disabled) }, _react2['default'].createElement('span', { className: this.state.showDisabled ? 'icon-show-disabled red' : 'icon-show-disabled' }) ) ); }, _renderMenu: function _renderMenu(results, shouldPaginate) { var _this3 = this; var _props8 = this.props, align = _props8.align, bodyContainer = _props8.bodyContainer, dropup = _props8.dropup, emptyLabel = _props8.emptyLabel, labelKey = _props8.labelKey, maxHeight = _props8.maxHeight, minLength = _props8.minLength, newSelectionPrefix = _props8.newSelectionPrefix, paginationText = _props8.paginationText, renderMenu = _props8.renderMenu, renderMenuItemChildren = _props8.renderMenuItemChildren, referType = _props8.referType, tableColumns = _props8.tableColumns; var _state5 = this.state, showMenu = _state5.showMenu, text = _state5.text; var menuProps = { align: align, dropup: dropup, emptyLabel: emptyLabel, labelKey: labelKey, maxHeight: maxHeight, newSelectionPrefix: newSelectionPrefix, paginationText: paginationText, onPaginate: this._handlePagination, paginate: shouldPaginate, text: text, tableColumns: tableColumns }; var list = renderMenu ? renderMenu(results, menuProps) : _react2['default'].createElement(_TypeaheadMenu2['default'], (0, _extends3['default'])({}, menuProps, { options: results, renderMenuItemChildren: renderMenuItemChildren })); var typeObj = _lodash.noop; switch (referType) { case 'list': typeObj = list; break; case 'cascader': var cascader = renderMenu ? renderMenu(results, menuProps) : _react2['default'].createElement(_ReferList2['default'], (0, _extends3['default'])({}, menuProps, { options: results, renderMenuItemChildren: renderMenuItemChildren })); typeObj = cascader; break; case 'table': var table = renderMenu ? renderMenu(results, menuProps) : _react2['default'].createElement(_ReferTable2['default'], (0, _extends3['default'])({}, menuProps, { options: results, onClickItem: this._handleAddOption })); typeObj = table; break; case 'treetable': var treetable = renderMenu ? renderMenu(results, menuProps) : _react2['default'].createElement(_ReferTreeTable2['default'], (0, _extends3['default'])({}, menuProps, { options: results, onClickItem: this._handleAddOption })); typeObj = treetable; break; default: typeObj = list; } return _react2['default'].createElement( _Overlay2['default'], { container: bodyContainer ? document.body : this, show: showMenu && text.length >= minLength, target: function target() { return _this3.refs.input; } }, typeObj ); }, _renderAux: function _renderAux() { var _props9 = this.props, bsSize = _props9.bsSize, clearButton = _props9.clearButton, disabled = _props9.disabled, isLoading = _props9.isLoading; if (isLoading) { return _react2['default'].createElement(_Loader2['default'], { bsSize: bsSize }); } if (clearButton && !disabled && this.state.selected.length) { return _react2['default'].createElement(_ClearButton2['default'], { bsSize: bsSize, className: 'bootstrap-typeahead-clear-button', onClick: this.clear }); } }, _handleActiveItemChange: function _handleActiveItemChange(activeItem) { this.setState({ activeItem: activeItem }); }, _handleBlur: function _handleBlur(e) { // Note: Don't hide the menu here, since that interferes with other actions // like making a selection by clicking on a menu item. if (this.props.onBlur) { this.props.onBlur(e); } }, _handleFocus: function _handleFocus(disabled, e) { if (disabled) { return; } this.props.onFocus(e); var multiple = this.props.multiple; if (!multiple) { // this.clear(); } this._loadData(); this.setState({ showMenu: true }); }, _handleEnable: function _handleEnable(disabled, e) { if (disabled) { return; } this._handleBlur(e); var showDisabled = this.state.showDisabled === undefined ? this.getInitialState() : this.state.showDisabled; this.setState({ showDisabled: !showDisabled, showMenu: false }); }, _handleInitialItemChange: function _handleInitialItemChange(initialItem) { var currentItem = this.state.initialItem; if (!currentItem) { this.setState({ initialItem: initialItem }); return; } var labelKey = this.props.labelKey; // Don't update the initial item if it hasn't changed. For custom items, // compare the `labelKey` values since a unique id is generated each time, // causing the comparison to always return false otherwise. if ((0, _lodash.isEqual)(initialItem, currentItem) || initialItem.customOption && initialItem[labelKey] === currentItem[labelKey]) { return; } this.setState({ initialItem: initialItem }); }, _handleTextChange: function _handleTextChange(text) { var _getInitialState2 = this.getInitialState(), activeIndex = _getInitialState2.activeIndex, activeItem = _getInitialState2.activeItem; this.setState({ activeIndex: activeIndex, activeItem: activeItem, showMenu: true, text: text }); this.props.onInputChange(text); }, _handleChange: function _handleChange(text, e) { this._handleTextChange(text); this.props.onChange(e); }, _handleKeydown: function _handleKeydown(options, e) { var _state6 = this.state, activeItem = _state6.activeItem, showMenu = _state6.showMenu; switch (e.keyCode) { case _keyCode.UP: case _keyCode.DOWN: // Don't cycle through the options if the menu is hidden. if (!showMenu) { return; } var activeIndex = this.state.activeIndex; // Prevents input cursor from going to the beginning when pressing up. e.preventDefault(); // Increment or decrement index based on user keystroke. activeIndex += e.keyCode === _keyCode.UP ? -1 : 1; // If we've reached the end, go back to the beginning or vice-versa. if (activeIndex === options.length) { activeIndex = -1; } else if (activeIndex === -2) { activeIndex = options.length - 1; } var newState = { activeIndex: activeIndex }; if (activeIndex === -1) { // Reset the active item if there is no active index. newState.activeItem = null; } this.setState(newState); break; case _keyCode.ESC: case _keyCode.TAB: // Prevent closing dialogs. e.keyCode === _keyCode.ESC && e.preventDefault(); this._hideDropdown(); break; case _keyCode.RETURN: // Prevent submitting forms. e.preventDefault(); if (showMenu) { activeItem && this._handleAddOption(activeItem); } break; } }, _handleAddOption: function _handleAddOption(selectedOption) { var _props10 = this.props, multiple = _props10.multiple, labelKey = _props10.labelKey, onChange = _props10.onChange, onInputChange = _props10.onInputChange; var selected = void 0; var text = void 0; if (multiple) { // If multiple selections are allowed, add the new selection to the // existing selections. selected = this.state.selected.concat(selectedOption); text = ''; } else { // If only a single selection is allowed, replace the existing selection // with the new one. selected = [selectedOption]; text = (0, _getOptionLabel2['default'])(selectedOption, labelKey); } this.setState({ initialItem: selectedOption, selected: selected, text: text }); this._hideDropdown(); onChange(selected); onInputChange(text); }, _handlePagination: function _handlePagination(e) { var shownResults = this.state.shownResults + this.props.maxResults; // Keep the input focused when paginating. this.focus(); this.setState({ shownResults: shownResults }); }, _handleRemoveOption: function _handleRemoveOption(removedOption) { var selected = this.state.selected.slice(); selected = selected.filter(function (option) { return !(0, _lodash.isEqual)(option, removedOption); }); // Make sure the input stays focused after the item is removed. this.focus(); this.setState({ selected: selected }); this._hideDropdown(); this.props.onChange(selected); }, /** * From `onClickOutside` HOC. */ handleClickOutside: function handleClickOutside(e) { this.state.showMenu && this._hideDropdown(); }, _hideDropdown: function _hideDropdown() { var _getInitialState3 = this.getInitialState(), activeIndex = _getInitialState3.activeIndex, activeItem = _getInitialState3.activeItem, showMenu = _getInitialState3.showMenu, shownResults = _getInitialState3.shownResults; this.setState({ activeIndex: activeIndex, activeItem: activeItem, showMenu: showMenu, shownResults: shownResults }); } }); exports['default'] = (0, _reactOnclickoutside2['default'])(Refers); module.exports = exports['default'];