diff --git a/README.md b/README.md index e1c33336..2d2a5a9c 100644 --- a/README.md +++ b/README.md @@ -155,6 +155,12 @@ Default: `250` Sets the delay in milliseconds after typing before a request will be sent to find suggestions. Specify `0` if you wish to fetch suggestions after every keystroke. +#### highlightMatch +Type: `Boolean` +Default: `true` + +Highlights matched text. + #### onFocus Type: `Function` Default: `function() {}` diff --git a/src/Geosuggest.jsx b/src/Geosuggest.jsx index 3338c640..5a7b2288 100644 --- a/src/Geosuggest.jsx +++ b/src/Geosuggest.jsx @@ -241,7 +241,8 @@ class Geosuggest extends React.Component { suggests.push({ label: this.props.getSuggestLabel(suggest), placeId: suggest.place_id, - isFixture: false + isFixture: false, + matchedSubstrings: suggest.matched_substrings[0] }); } }); @@ -404,6 +405,8 @@ class Geosuggest extends React.Component { suggestionsList = {}, onSuggestSelect: () => {}, onSuggestNoResults: () => {}, diff --git a/src/prop-types.js b/src/prop-types.js index d0c1eac7..59ef248d 100644 --- a/src/prop-types.js +++ b/src/prop-types.js @@ -24,6 +24,7 @@ export default { types: React.PropTypes.array, queryDelay: React.PropTypes.number, googleMaps: React.PropTypes.object, + highlightMatch: React.PropTypes.bool, onSuggestSelect: React.PropTypes.func, onFocus: React.PropTypes.func, onBlur: React.PropTypes.func, diff --git a/src/suggest-item.jsx b/src/suggest-item.jsx index 4ddf9270..650dd02e 100644 --- a/src/suggest-item.jsx +++ b/src/suggest-item.jsx @@ -18,6 +18,36 @@ export default class SuggestItem extends React.Component { return shallowCompare(this, nextProps, nextState); } + /** + * Makes a text bold + * @param {String} el element + * @return {JSX} Bolder text + */ + makeBold(el) { + return + {el}; + } + + /** + * Replace matched text with the same bold + * @param {Object} userInput Value from input + * @param {Object} suggest Data from google + * @return {String} Formatted string with highlighted matched text + */ + formatMatchedText(userInput, suggest) { + if (!userInput || !suggest.matchedSubstrings) { + return suggest.label; + } + + let start = suggest.matchedSubstrings.offset, + end = suggest.matchedSubstrings.length, + split = suggest.label.split(''); + split.splice(start, end, + this.makeBold(suggest.label.substring(start, end))); + + return {split}; + } + /** * When the suggest item got clicked * @param {Event} event The click event @@ -46,7 +76,10 @@ export default class SuggestItem extends React.Component { onMouseDown={this.props.onMouseDown} onMouseOut={this.props.onMouseOut} onClick={this.onClick}> - {this.props.suggest.label} + { this.props.isHighlightMatch + ? this.formatMatchedText( + this.props.userInput, this.props.suggest) + : this.props.suggest.label } ; } } diff --git a/src/suggest-list.jsx b/src/suggest-list.jsx index 22607df5..751053f2 100644 --- a/src/suggest-list.jsx +++ b/src/suggest-list.jsx @@ -59,6 +59,8 @@ export default class SuggestList extends React.Component { return { }); }); }); + + describe('with highLightMatch', () => { // eslint-disable-line max-len + const props = { + suggestsClassName: 'suggests-class' + }; + + beforeEach(() => render(props)); + + it('should highlight matched text', () => { // eslint-disable-line max-len + const geoSuggestInput = TestUtils.findRenderedDOMComponentWithClass(component, 'geosuggest__input'); // eslint-disable-line max-len + geoSuggestInput.value = 'New'; + TestUtils.Simulate.change(geoSuggestInput); + TestUtils.Simulate.focus(geoSuggestInput); + let matchedText = TestUtils.scryRenderedDOMComponentsWithClass(component, 'matched-text'); // eslint-disable-line max-len + expect(matchedText).to.have.length.of.at.least(1); // eslint-disable-line max-len + }); + }); });