From 5af65bd49b66809709660c5360020114a24625f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=87a=C4=9Fatay=20=C3=87ivici?= Date: Mon, 4 Dec 2017 13:13:15 +0300 Subject: [PATCH] Fixed #210 --- src/components/autocomplete/AutoComplete.js | 59 +++++-------------- .../autocomplete/AutoCompletePanel.js | 58 ++++++++++++++++++ 2 files changed, 73 insertions(+), 44 deletions(-) create mode 100644 src/components/autocomplete/AutoCompletePanel.js diff --git a/src/components/autocomplete/AutoComplete.js b/src/components/autocomplete/AutoComplete.js index f8488ab1e4..d3437469b0 100644 --- a/src/components/autocomplete/AutoComplete.js +++ b/src/components/autocomplete/AutoComplete.js @@ -5,6 +5,7 @@ import { InputText } from '../inputtext/InputText'; import { Button } from '../button/Button'; import DomHandler from '../utils/DomHandler'; import ObjectUtils from '../utils/ObjectUtils'; +import {AutoCompletePanel} from './AutoCompletePanel'; import classNames from 'classnames'; export class AutoComplete extends Component { @@ -101,6 +102,7 @@ export class AutoComplete extends Component { this.onMultiContainerClick = this.onMultiContainerClick.bind(this); this.onMultiInputFocus = this.onMultiInputFocus.bind(this); this.onMultiInputBlur = this.onMultiInputBlur.bind(this); + this.selectItem = this.selectItem.bind(this); } shouldComponentUpdate() { @@ -205,10 +207,10 @@ export class AutoComplete extends Component { if(this.focus) { this.alignPanel(); - if(!this.panel.offsetParent) { - this.panel.style.zIndex = DomHandler.getZindex(); - this.panel.style.display = "block"; - DomHandler.fadeIn(this.panel, 200); + if (this.panel && this.panel.element && !this.panel.element.offsetParent) { + this.panel.element.style.zIndex = DomHandler.getZindex(); + this.panel.element.style.display = "block"; + DomHandler.fadeIn(this.panel.element, 200); this.bindDocumentClickListener(); } } @@ -218,13 +220,13 @@ export class AutoComplete extends Component { let target = this.props.multiple ? this.multiContainer : this.inputEl; if(this.props.appendTo) - DomHandler.absolutePosition(this.panel, target); + DomHandler.absolutePosition(this.panel.element, target); else - DomHandler.relativePosition(this.panel, target); + DomHandler.relativePosition(this.panel.element, target); } hidePanel() { - this.panel.style.display = 'none'; + this.panel.element.style.display = 'none'; this.unbindDocumentClickListener(); } @@ -263,7 +265,7 @@ export class AutoComplete extends Component { onInputKeyDown(event) { if(this.isPanelVisible()) { - let highlightItem = DomHandler.findSingle(this.panel, 'li.ui-state-highlight'); + let highlightItem = DomHandler.findSingle(this.panel.element, 'li.ui-state-highlight'); switch(event.which) { //down @@ -273,11 +275,11 @@ export class AutoComplete extends Component { if(nextElement) { DomHandler.addClass(nextElement, 'ui-state-highlight'); DomHandler.removeClass(highlightItem, 'ui-state-highlight'); - DomHandler.scrollInView(this.panel, nextElement); + DomHandler.scrollInView(this.panel.element, nextElement); } } else { - DomHandler.addClass(this.panel.firstChild.firstChild, 'ui-state-highlight'); + DomHandler.addClass(this.panel.element.firstChild.firstChild, 'ui-state-highlight'); } event.preventDefault(); @@ -417,15 +419,6 @@ export class AutoComplete extends Component { return index; } - componentDidMount() { - if(this.props.appendTo) { - if(this.props.appendTo === 'body') - document.body.appendChild(this.panel); - else - DomHandler.appendChild(this.panel, this.props.appendTo); - } - } - componentDidUpdate() { if(this.searching) { if (this.props.suggestions && this.props.suggestions.length) @@ -525,28 +518,6 @@ export class AutoComplete extends Component { ); } - renderPanel() { - let items; - - if(this.props.suggestions) { - items = this.props.suggestions.map((suggestion, index) => { - let itemContent = this.props.itemTemplate ? this.props.itemTemplate(suggestion) : this.props.field ? ObjectUtils.resolveFieldData(suggestion, this.props.field): suggestion; - - return ( -
  • this.selectItem(e, suggestion)}>{itemContent}
  • - ); - }); - } - - return ( -
    this.panel = el} className="ui-autocomplete-panel ui-widget-content ui-corner-all ui-shadow" style={{maxHeight: this.props.scrollHeight}}> - -
    - ); - } - bindDocumentClickListener() { if(!this.documentClickListener) { this.documentClickListener = (event) => { @@ -574,12 +545,11 @@ export class AutoComplete extends Component { } isPanelVisible() { - return this.panel.offsetParent != null; + return this.panel.element.offsetParent != null; } render() { let input, dropdown; - let panel = this.renderPanel(); let className = classNames('ui-autocomplete ui-widget', this.props.className, { 'ui-autocomplete-dd': this.props.dropdown, 'ui-autocomplete-multiple': this.props.multiple @@ -600,7 +570,8 @@ export class AutoComplete extends Component { {input} {loader} {dropdown} - {panel} + this.panel = el} suggestions={this.props.suggestions} field={this.props.field} + appendTo={this.props.appendTo} itemTemplate={this.props.itemTemplate} onItemClick={this.selectItem}/> ); } diff --git a/src/components/autocomplete/AutoCompletePanel.js b/src/components/autocomplete/AutoCompletePanel.js new file mode 100644 index 0000000000..8f65af3c65 --- /dev/null +++ b/src/components/autocomplete/AutoCompletePanel.js @@ -0,0 +1,58 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import ReactDOM from 'react-dom'; +import ObjectUtils from '../utils/ObjectUtils'; + +export class AutoCompletePanel extends Component { + + static defaultProps = { + suggestions: null, + field: null, + appendTo: null, + itemTemplate: null, + onItemClick: null, + scrollHeight: '200px' + } + + static propTypes = { + suggestions: PropTypes.array, + field: PropTypes.string, + appendTo: PropTypes.any, + itemTemplate: PropTypes.func, + onItemClick: PropTypes.func, + scrollHeight: PropTypes.string + }; + + renderElement() { + let items; + + if (this.props.suggestions) { + items = this.props.suggestions.map((suggestion, index) => { + let itemContent = this.props.itemTemplate ? this.props.itemTemplate(suggestion) : this.props.field ? ObjectUtils.resolveFieldData(suggestion, this.props.field) : suggestion; + + return ( +
  • this.props.onItemClick(e, suggestion)}>{itemContent}
  • + ); + }); + } + + return ( +
    this.element = el} className="ui-autocomplete-panel ui-widget-content ui-corner-all ui-shadow" style={{ maxHeight: this.props.scrollHeight }}> +
      + {items} +
    +
    + ); + } + + render() { + let element = this.renderElement(); + + if (this.props.appendTo) { + return ReactDOM.createPortal(element, this.props.appendTo); + } + else { + return element; + } + } +} \ No newline at end of file