Autocomplete
// Dependencies
'use strict';
var React = __webpack_require__(124);
var builder = __webpack_require__(406).component.builder;
var types = __webpack_require__(406).component.types;
var find = __webpack_require__(755);
// Components
var Autocomplete = __webpack_require__(844).component;
/**
* Autocomplete for component
* @type {Object}
*/
var AutocompleteFor = {
/**
* Default props
* @return {Object} default props
*/
getDefaultProps: function getDefaultProps() {
return {
AutocompleteComp: Autocomplete,
pickList: [],
value: ''
};
},
/**
* Props validation
* @type {Object}
*/
propTypes: {
AutocompleteComp: types('func'),
allowUnmatchedValue: types('bool'),
codeResolver: types('func'),
isEdit: types('bool'),
onInputBlur: types('func'),
pickList: types('array'),
searcher: types('func'),
selectionHandler: types('func'),
value: types('string')
},
/**
* Get initial state
* @return {Object} initial state
*/
getInitialState: function getInitialState() {
var pickList = this.props.pickList;
return { pickList: pickList };
},
/**
* Component will mount, load the list
*/
componentWillMount: function componentWillMount() {
var _this = this;
var _props = this.props;
var isEdit = _props.isEdit;
var value = _props.value;
var codeResolver = _props.codeResolver;
if (!isEdit && value && codeResolver) {
// Resolve the code if in consult
codeResolver(value).then(function (resolvedCode) {
return _this.setState({ value: resolvedCode });
});
} else {
this._doLoad();
}
},
componentWillReceiveProps: function componentWillReceiveProps(_ref) {
var _this2 = this;
var codeResolver = _ref.codeResolver;
var value = _ref.value;
if (value !== this.props.value) {
codeResolver(value).then(function (resolvedCode) {
return _this2.setState({ value: resolvedCode });
});
}
},
/**
* List loader
* @param {string} text='' input text to search from
*/
_doLoad: function _doLoad() {
var _this3 = this;
var text = arguments.length <= 0 || arguments[0] === undefined ? '' : arguments[0];
var searcher = this.props.searcher;
if (searcher) {
searcher(text).then(function (pickList) {
return _this3.setState({ pickList: pickList });
});
}
},
/**
* Get value of the field
* @return {string} the code of the curren value
*/
getValue: function getValue() {
var autocomplete = this.refs.autocomplete;
return autocomplete ? autocomplete.getValue() : this.state.value;
},
/**
* Render the edit mode
* @return {HTML} rendered element
*/
_renderEdit: function _renderEdit() {
var _props2 = this.props;
var AutocompleteComp = _props2.AutocompleteComp;
var allowUnmatchedValue = _props2.allowUnmatchedValue;
var onInputBlur = _props2.onInputBlur;
var selectionHandler = _props2.selectionHandler;
var code = _props2.value;
var pickList = this.state.pickList;
return React.createElement(AutocompleteComp, {
allowUnmatchedValue: allowUnmatchedValue,
code: code,
inputChangeHandler: this._doLoad,
onInputBlur: onInputBlur,
pickList: pickList,
ref: 'autocomplete',
selectionHandler: selectionHandler
});
},
/**
* Render the consult mode
* @return {HTML} rendered element
*/
_renderConsult: function _renderConsult() {
var value = this.state.value;
var code = this.props.value;
return React.createElement(
'span',
null,
value ? value : code
);
},
/**
* Render the component
* @return {HTML} the rendered component
*/
render: function render() {
var isEdit = this.props.isEdit;
return false === isEdit ? this._renderConsult() : this._renderEdit();
}
};
module.exports = builder(AutocompleteFor);
var Autocomplete = {
/**
* Component will mount.
* Check if the Awesomplete library is in the Window object.
*/
componentWillMount: function componentWillMount() {
// Check if Awesomplete is set in Window
if (!window.Awesomplete) {
throw new Error('Please include Awesomplete to your application. See http://leaverou.github.io/awesomplete/ for more information');
}
},
/**
* Component did mount.
* Initiates the Awesomplete object.
*/
componentDidMount: function componentDidMount() {
var _this = this;
var input = this.refs.input.refs.inputText;
var _props = this.props;
var code = _props.code;
var codeResolver = _props.codeResolver;
var pickList = _props.pickList;
this._awesomeplete = new Awesomplete(React.findDOMNode(input), {
list: this._extractListFromData(pickList)
});
this._awesomeplete.input.addEventListener('awesomplete-select', function (event) {
return _this._selectionHandler(event.text);
});
this._resolveValueFromPicklistOrCodeResolver(code, pickList);
},
/**
* Default props.
* @return {Object} default props
*/
getDefaultProps: function getDefaultProps() {
return {
code: '',
pickList: [],
timeoutDuration: 200,
allowUnmatchedValue: true
};
},
/**
* Prop validation
* @type {Object}
*/
propTypes: {
allowUnmatchedValue: types('bool'), // restrict user input to values of the list, or allow freestyle
code: types('string'), // the field code value
inputChangeHandler: types('func'), // callback when input changed
onInputBlur: types('func'),
pickList: types('array'), // list of values, looking like [{code: '', value: ''}, {code: '', value: ''}, ...]
selectionHandler: types('func'), // selection callback
timeoutDuration: types('number') // the throttle duration of the input rate
},
/**
* Initial state.
* Retrieve the value from the provided code and pick list.
* @return {Object} initial state
*/
getInitialState: function getInitialState() {
var _props2 = this.props;
var code = _props2.code;
var pickList = _props2.pickList;
return {
value: 0 < pickList.length ? this._getValueFromCode(code) : code
};
},
/**
* Component will receive props.
* Update the pick list, and try to resolve the new value.
* @param {Object} nextProps new props
*/
componentWillReceiveProps: function componentWillReceiveProps(_ref) {
var pickList = _ref.pickList;
var code = _ref.code;
if (code !== this.props.code) {
this._resolveValueFromPicklistOrCodeResolver(code, pickList);
}
this._awesomeplete._list = this._extractListFromData(pickList);
},
_resolveValueFromPicklistOrCodeResolver: function _resolveValueFromPicklistOrCodeResolver(code, pickList) {
var _this2 = this;
var codeResolver = this.props.codeResolver;
var value = this._getValueFromCode(code, pickList);
if ('' !== value) {
this.setState({ value: value }); // eslint-disable-line
} else if (codeResolver) {
codeResolver(code).then(function (resolvedValue) {
if ('' !== resolvedValue) {
_this2.setState({ value: resolvedValue }, function () {
_this2.props.inputChangeHandler(resolvedValue);
}); // eslint-disable-line
}
});
}
},
/**
* Selection handler.
* If a selection handler is set in the props, send it the selected pick.
* Also, set a flag to tell the blur listener not to empty the value, because the selection, as it is a click outside the input, raises a blur event.
* @param {String} value selected value from the dropdown list
*/
_selectionHandler: function _selectionHandler(value) {
var selectionHandler = this.props.selectionHandler;
if (selectionHandler) {
var pickList = this.props.pickList;
var selectedPick = find(pickList, { value: value });
selectionHandler(selectedPick);
}
this._isSelecting = true; // Private flag to tell the blur listener not to replace the value
this.setState({ value: value });
},
/**
* Extract list of suggestions from pick list
* @param {Object} data the pick list
* @return {Array} the suggestion array
*/
_extractListFromData: function _extractListFromData(data) {
return data.map(function (datum) {
return datum.value;
});
},
/**
* Get code from value in the pick list
* @param {String} value the value
* @return {String} the code
*/
_getCodeFromValue: function _getCodeFromValue(value) {
var pickList = this.props.pickList;
var pick = find(pickList, { value: value });
return pick ? pick.code : pick;
},
/**
* Get value from code in the pick list
* @param {String} code the code
* @param {Object} pickList=this.props.pickList optional pick list to resolve the value from
* @return {String} value
*/
_getValueFromCode: function _getValueFromCode(code) {
var pickList = arguments.length <= 1 || arguments[1] === undefined ? this.props.pickList : arguments[1];
var pick = find(pickList, { code: code });
return pick ? pick.value : '';
},
/**
* Get the current code
* @return {String} the code
*/
getValue: function getValue() {
var value = this.state.value;
var allowUnmatchedValue = this.props.allowUnmatchedValue;
var computedValue = this._getCodeFromValue(value);
return computedValue ? computedValue : allowUnmatchedValue ? value : undefined;
},
/**
* On input blur.
* If allowUnmatchedValue is set in the props, validate the current value and erase it if not valid.
*/
_onInputBlur: function _onInputBlur() {
var value = this.state.value;
var _props3 = this.props;
var allowUnmatchedValue = _props3.allowUnmatchedValue;
var onInputBlur = _props3.onInputBlur;
var pickList = _props3.pickList;
var selectionHandler = _props3.selectionHandler;
var selectedPick = find(pickList, { value: value });
var code = this._getCodeFromValue(value);
if (selectedPick && !this._isSelecting && selectionHandler) {
selectionHandler(selectedPick);
}
if (!code && !allowUnmatchedValue && !this._isSelecting) {
this.setState({ value: '' });
}
if (onInputBlur) {
onInputBlur();
}
this._isSelecting = false;
},
/**
* On input change
* @param {Object} event change event
*/
_onInputChange: function _onInputChange(event) {
var _this3 = this;
var value = event.target.value;
var timeoutDuration = this.props.timeoutDuration;
this.setState({ value: value });
if (this._changeTimeout) {
clearTimeout(this._changeTimeout);
}
this._changeTimeout = setTimeout(function () {
var inputChangeHandler = _this3.props.inputChangeHandler;
if (inputChangeHandler) {
inputChangeHandler(value);
}
}, timeoutDuration);
},
/**
* Render
* @return {HTML} rendered element
*/
render: function render() {
var value = this.state.value;
var _onInputBlur = this._onInputBlur;
var _onInputChange = this._onInputChange;
return React.createElement(
'div',
{ 'data-focus': 'autocomplete' },
React.createElement(InputText, { onBlur: _onInputBlur, onChange: _onInputChange, ref: 'input', value: value })
);
}
};