Search code examples
javascriptreactjsdraftjs

How to focus among the search results on draft-js editor


I've implemented the find and replace feature like this tutorial and it works neat: https://reactrocket.com/post/draft-js-search-and-replace/

I want to know how it will be to have some focus() on the editor's search result every time user hits enter on the search box, looping among the results, similar to native google chrome's find feature.


Solution

  • I can suggest the following solution to the issue. Working demo - https://jsfiddle.net/levsha/o3xyvkw7/ For a start, we define activeHighlightIndex property in the component state. We will be store index of active highlighting here.

    constructor(props) {
      super(props);
    
      this.state = {
        search: '',
        replace: '',
        activeHighlightIndex: 0,
        editorState: EditorState.createWithContent(ContentState.createFromText(string)),
      }
    }
    

    Bind onKeyDown handler on search input. If it's enter button, we increase activeHighlightIndex.

    onKeyDown = (e) => {
      if (e.keyCode === 13) { // enter
        this.setState({
          activeHighlightIndex: this.state.activeHighlightIndex + 1
        });
      }
    }
    

    In componentDidUpdate method we apply appropriate styles for the active highlighting element and check if we should scroll the window for the element will be in the viewport.

    componentDidUpdate() {
      if (this.state.search.length) {
        const allHighlights = this.editor.refs.editor
          .getElementsByClassName('search-and-replace-highlight');
        const index = this.state.activeHighlightIndex % allHighlights.length;
        const newActiveHighlight = allHighlights[index];
        const currentActiveHighlight = this.editor.refs.editor
          .querySelector('.search-and-replace-highlight.active-highlight');
    
        if (newActiveHighlight && currentActiveHighlight !== newActiveHighlight) {
          currentActiveHighlight && currentActiveHighlight.classList
            .remove('active-highlight');
    
          newActiveHighlight.classList.add('active-highlight');
          scrollToElementIfNeeded(newActiveHighlight);
        }
      }
    }