UNPKG

14.8 kBJavaScriptView Raw
1'use strict';
2
3exports.__esModule = true;
4
5var _extends2 = require('babel-runtime/helpers/extends');
6
7var _extends3 = _interopRequireDefault(_extends2);
8
9var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
10
11var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
12
13var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
14
15var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
16
17var _inherits2 = require('babel-runtime/helpers/inherits');
18
19var _inherits3 = _interopRequireDefault(_inherits2);
20
21var _class, _temp;
22
23var _react = require('react');
24
25var _react2 = _interopRequireDefault(_react);
26
27var _reactDom = require('react-dom');
28
29var _reactDom2 = _interopRequireDefault(_reactDom);
30
31var _propTypes = require('prop-types');
32
33var _propTypes2 = _interopRequireDefault(_propTypes);
34
35var _classnames = require('classnames');
36
37var _classnames2 = _interopRequireDefault(_classnames);
38
39var _util = require('../util');
40
41var _input = require('../input');
42
43var _input2 = _interopRequireDefault(_input);
44
45var _base = require('./base');
46
47var _base2 = _interopRequireDefault(_base);
48
49function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
50
51var bindCtx = _util.func.bindCtx,
52 noop = _util.func.noop;
53
54/**
55 * Select.AutoComplete
56 */
57
58var AutoComplete = (_temp = _class = function (_Base) {
59 (0, _inherits3.default)(AutoComplete, _Base);
60
61 function AutoComplete(props) {
62 (0, _classCallCheck3.default)(this, AutoComplete);
63
64 var _this = (0, _possibleConstructorReturn3.default)(this, _Base.call(this, props));
65
66 _this.handleChange = function (value, proxy, item) {
67 var _this$props = _this.props,
68 disabled = _this$props.disabled,
69 readOnly = _this$props.readOnly,
70 filterLocal = _this$props.filterLocal;
71
72
73 if (disabled || readOnly) {
74 return false;
75 }
76
77 var actionType = typeof proxy === 'string' ? proxy : 'change';
78
79 _this.isInputing = actionType === 'change';
80
81 if (filterLocal) {
82 _this.setState({
83 dataSource: _this.dataStore.updateByKey(value)
84 });
85
86 _this.shouldControlPopup(_this.props, actionType);
87 _this.setFirstHightLightKeyForMenu();
88 }
89
90 // 非受控模式清空内部数据
91 if (!('value' in _this.props)) {
92 _this.setState({
93 value: value
94 });
95 }
96
97 _this.props.onChange(value, actionType, item);
98
99 if (actionType === 'itemClick' || actionType === 'enter') {
100 // 点击 item 的时候不会触发关闭,需要手动关闭,其它类型比如 keyDown 等都会有其它事件句柄处理
101 _this.setVisible(false, actionType);
102 }
103 };
104
105 _this.isAutoComplete = true;
106 _this.isInputing = false;
107
108 bindCtx(_this, ['handleTriggerKeyDown', 'handleMenuSelect', 'handleItemClick']);
109 return _this;
110 }
111
112 AutoComplete.prototype.componentWillMount = function componentWillMount() {
113 this.dataStore.setOptions({ key: this.state.value });
114
115 _Base.prototype.componentWillMount.call(this);
116 };
117
118 AutoComplete.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) {
119 if ('value' in nextProps) {
120 this.dataStore.setOptions({ key: nextProps.value });
121 this.setState({
122 value: nextProps.value
123 });
124 }
125
126 if ('visible' in nextProps) {
127 this.setState({
128 visible: nextProps.visible
129 });
130 }
131
132 this.dataStore.setOptions({
133 filter: nextProps.filter,
134 filterLocal: nextProps.filterLocal
135 });
136
137 if (nextProps.children !== this.props.children || nextProps.dataSource !== this.props.dataSource) {
138 var dataSource = this.setDataSource(nextProps);
139 this.setState({
140 dataSource: dataSource
141 });
142 }
143
144 // remote dataSource and focused
145 // 因为autoComplete没有下拉数据不展示,搜索并且有数据了需要自动展示下拉
146 if (!nextProps.filterLocal && this.isInputing) {
147 this.shouldControlPopup(nextProps, 'update');
148 }
149
150 if (!nextProps.filterLocal && !nextProps.popupContent) {
151 this.setFirstHightLightKeyForMenu();
152 }
153 };
154
155 AutoComplete.prototype.componentWillUpdate = function componentWillUpdate() {
156 if (this.hasClear()) {
157 var inputNode = _reactDom2.default.findDOMNode(this.inputRef);
158 if (inputNode) {
159 this.clearNode = inputNode.querySelector('.' + this.props.prefix + 'input-control');
160 }
161 }
162 };
163
164 AutoComplete.prototype.shouldControlPopup = function shouldControlPopup() {
165 var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.props;
166 var type = arguments[1];
167
168 var hasPopup = props.popupContent || this.dataStore.getMenuDS().length;
169 if (hasPopup) {
170 this.setVisible(true, type);
171 } else {
172 this.setVisible(false, type);
173 }
174 };
175
176 AutoComplete.prototype.handleMenuSelect = function handleMenuSelect(keys) {
177 var key = keys[0];
178 if (this.state.value === keys[0]) {
179 return this.setVisible(false, 'itemClick');
180 }
181
182 var mapDS = this.dataStore.getMapDS();
183
184 if (key in mapDS) {
185 var item = mapDS[key];
186 this.handleSelectEvent(key, item, 'itemClick');
187 }
188 };
189
190 AutoComplete.prototype.handleItemClick = function handleItemClick() {
191 this.setVisible(false, 'itemClick');
192 };
193
194 AutoComplete.prototype.handleSelectEvent = function handleSelectEvent(key, item, triggerType) {
195 var value = item && item[this.props.fillProps] || key;
196
197 if (triggerType === 'itemClick' || triggerType === 'enter') {
198 // 点击 item 的时候不会触发关闭,需要手动关闭,其它类型比如 keyDown 等都会有其它事件句柄处理
199 this.setVisible(false, triggerType);
200 }
201
202 this.handleChange(value, triggerType, item);
203 };
204
205 AutoComplete.prototype.handleVisibleChange = function handleVisibleChange(visible, type) {
206 if (!('visible' in this.props) && visible && !this.props.popupContent && !this.dataStore.getMenuDS().length) {
207 return;
208 }
209
210 this.setVisible(visible, type);
211 };
212
213 AutoComplete.prototype.beforeClose = function beforeClose() {
214 this.isInputing = false;
215 };
216
217 /**
218 * Handle trigger keydown event
219 * @param {Event} e
220 */
221
222
223 AutoComplete.prototype.handleTriggerKeyDown = function handleTriggerKeyDown(e) {
224 var _props = this.props,
225 popupContent = _props.popupContent,
226 onToggleHighlightItem = _props.onToggleHighlightItem,
227 onKeyDown = _props.onKeyDown;
228
229 if (popupContent) {
230 e.stopPropagation(); //stopPropagation can make use onChange triggerd while typing space('') in Input
231 return onKeyDown(e);
232 }
233
234 switch (e.keyCode) {
235 case _util.KEYCODE.UP:
236 e.preventDefault();
237 onToggleHighlightItem(this.toggleHighlightItem(-1, e), 'up');
238 break;
239 case _util.KEYCODE.DOWN:
240 e.preventDefault();
241 onToggleHighlightItem(this.toggleHighlightItem(1, e), 'down');
242 break;
243 case _util.KEYCODE.ENTER:
244 e.preventDefault();
245 this.chooseHighlightItem(e);
246 break;
247 case _util.KEYCODE.SPACE:
248 // stopPropagation can make use onChange triggerd while typing space('') in Input
249 e.stopPropagation();
250 break;
251 case _util.KEYCODE.ESC:
252 e.preventDefault();
253 this.state.visible && this.setVisible(false, 'esc');
254 break;
255 default:
256 break;
257 }
258
259 onKeyDown(e);
260 };
261
262 // 回车 选择高亮的 item
263
264
265 AutoComplete.prototype.chooseHighlightItem = function chooseHighlightItem() {
266 if (!this.state.visible) {
267 return false;
268 }
269
270 var highlightKey = this.state.highlightKey;
271
272 var highlightItem = this.dataStore.getEnableDS().find(function (item) {
273 return highlightKey === '' + item.value;
274 });
275
276 if (highlightItem) {
277 this.handleSelectEvent(highlightKey, highlightItem, 'enter');
278 }
279 };
280
281 AutoComplete.prototype.hasClear = function hasClear() {
282 var _props2 = this.props,
283 hasClear = _props2.hasClear,
284 readOnly = _props2.readOnly,
285 disabled = _props2.disabled;
286 var value = this.state.value;
287
288
289 return value && hasClear && !readOnly && !disabled;
290 };
291
292 /**
293 * 选择器
294 * @override
295 * @param {object} props
296 */
297
298
299 AutoComplete.prototype.renderSelect = function renderSelect() {
300 var _classNames;
301
302 var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.props;
303 var placeholder = props.placeholder,
304 size = props.size,
305 prefix = props.prefix,
306 className = props.className,
307 style = props.style,
308 label = props.label,
309 readOnly = props.readOnly,
310 disabled = props.disabled,
311 highlightHolder = props.highlightHolder,
312 locale = props.locale,
313 hasClear = props.hasClear,
314 state = props.state,
315 rtl = props.rtl;
316
317 var others = _util.obj.pickOthers(AutoComplete.propTypes, props);
318 var othersData = _util.obj.pickAttrsWith(others, 'data-');
319
320 var value = this.state.value;
321 var visible = this.state.visible;
322
323 // // 下拉箭头
324 // const arrowNode = this.renderArrowNode(props, () => {
325 // this.focusInput();
326 // this.setVisible(!this.state.visible);
327 // });
328
329 // trigger className
330 var triggerClazz = (0, _classnames2.default)([prefix + 'select', prefix + 'select-auto-complete', prefix + 'size-' + size, className], (_classNames = {}, _classNames[prefix + 'active'] = visible, _classNames[prefix + 'disabled'] = disabled, _classNames));
331
332 // highlightKey into placeholder
333 // compatible with selectPlaceHolder. TODO: removed in 2.0 version
334 var _placeholder = placeholder || locale.autoCompletePlaceholder || locale.autoCompletePlaceHolder;
335 if (highlightHolder && visible) {
336 _placeholder = this.state.highlightKey || _placeholder;
337 }
338
339 // Input props
340 var _inputProps = (0, _extends3.default)({}, _util.obj.pickOthers(othersData, others), {
341 state: state,
342 ref: this.saveInputRef,
343 hasClear: hasClear,
344 value: value,
345 size: size,
346 disabled: disabled,
347 readOnly: readOnly,
348 placeholder: _placeholder,
349 label: label,
350 // extra: arrowNode,
351 onChange: this.handleChange,
352 onKeyDown: this.handleTriggerKeyDown
353 });
354
355 return _react2.default.createElement(
356 'span',
357 (0, _extends3.default)({}, othersData, {
358 className: triggerClazz,
359 style: style,
360 dir: rtl ? 'rtl' : undefined,
361 ref: this.saveSelectRef,
362 onClick: this.focusInput
363 }),
364 _react2.default.createElement(_input2.default, (0, _extends3.default)({
365 role: 'combobox',
366 'aria-autocomplete': 'list',
367 'aria-disabled': disabled,
368 'aria-expanded': this.state.visible
369 }, _inputProps)),
370 _react2.default.createElement(
371 'span',
372 { className: prefix + 'sr-only', 'aria-live': 'polite' },
373 this.state.srReader
374 )
375 );
376 };
377
378 AutoComplete.prototype.render = function render() {
379 var _this2 = this;
380
381 if (this.hasClear()) {
382 // clear 按钮点击后,会在 dom 结构中被删除掉,需要将其额外设置为安全节点,防止触发弹层的显示或隐藏
383 var safeNode = this.props.popupProps.safeNode || [];
384 var safeNodes = Array.isArray(safeNode) ? safeNode : [safeNode];
385 safeNodes.push(function () {
386 return _this2.clearNode;
387 });
388 this.props.popupProps.safeNode = safeNodes;
389 }
390
391 return _Base.prototype.render.call(this, (0, _extends3.default)({}, this.props, { canCloseByTrigger: false }));
392 };
393
394 return AutoComplete;
395}(_base2.default), _class.propTypes = (0, _extends3.default)({}, _base2.default.propTypes, {
396 /**
397 * 当前值,用于受控模式
398 */
399 value: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.number]),
400 /**
401 * 初始化的默认值
402 */
403 defaultValue: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.number]),
404 /**
405 * Select发生改变时触发的回调
406 * @param {*} value 选中的值
407 * @param {String} actionType 触发的方式, 'itemClick', 'enter', 'change'
408 * @param {*} item 选中的值的对象数据
409 */
410 onChange: _propTypes2.default.func,
411 /**
412 * 传入的数据源,可以动态渲染子项
413 */
414 dataSource: _propTypes2.default.arrayOf(_propTypes2.default.oneOfType([_propTypes2.default.shape({
415 value: _propTypes2.default.string,
416 label: _propTypes2.default.any,
417 disabled: _propTypes2.default.bool,
418 children: _propTypes2.default.array
419 }), _propTypes2.default.string])),
420 /**
421 * 填充到选择框里的值的 key,默认是 value
422 */
423 fillProps: _propTypes2.default.string,
424 /**
425 * 渲染 MenuItem 内容的方法
426 * @param {Object} item 渲染节点的 item
427 * @return {ReactNode} item node
428 */
429 itemRender: _propTypes2.default.func,
430 // input keydown
431 onKeyDown: _propTypes2.default.func,
432 // 是否将当前高亮的选项作为 placeholder
433 highlightHolder: _propTypes2.default.bool,
434 style: _propTypes2.default.object
435}), _class.defaultProps = (0, _extends3.default)({}, _base2.default.defaultProps, {
436 onKeyDown: noop,
437 fillProps: 'value'
438}), _temp);
439exports.default = AutoComplete;
440module.exports = exports['default'];
\No newline at end of file