Jo Ko
Jo Ko

Reputation: 7575

ReactJS & Material-UI: How to highlight just content inside Material-UI's <Dialog> and not the whole page?

In my ReactJS project, I'm using <Dialog> (http://www.material-ui.com/#/components/dialog), and when I open up the <Dialog> and press command + a on Mac, it highlights the whole page rather than just the content in the <Dialog>.

How can I highlight just the content inside <Dialog> while the <Dialog> is open by pressing command + a on Mac?

Thank you in advance and will accept/upvote the answer.

Upvotes: 1

Views: 2306

Answers (1)

Jeff McCloud
Jeff McCloud

Reputation: 5927

Yes, this can be done. You'll need to listen for Command-A (or Ctrl-A on Windows) on window.document in componentDidMount() and perform the text selection programmatically. For cleanup, you un-listen in componentWillUnmount().

Working example here: http://www.webpackbin.com/41BuFVuBz

import React from 'react';
import { Dialog } from 'material-ui';

class HelloWorld extends React.Component {
  constructor(props) {
    super(props);
    // In ES6 classes, class methods like handleKeyDown aren't automatically bound to "this"
    this.handleKeyDown = this.handleKeyDown.bind(this);
  }

  handleKeyDown(e) {
    // If the A key is pressed while CTRL or COMMAND are also being pressed
    if (e.key === 'a' && (e.ctrlKey || e.metaKey)) {
      // Don't perform the default action, which would select everything on page
      e.preventDefault();

      const win = window;
      const doc = win.document;
      // this.dialogBody is the div's DOM element captured in the ref={}
      const element = this.dialogBody;

      if (doc.body.createTextRange) {      // check if this is Internet Explorer
        // Select all text in "element", the IE way
        var range = doc.body.createTextRange();
        range.moveToElementText(element);
        range.select();
      } else if (win.getSelection) {      // other browsers...
        // Select all text in "element", the standard way
        var selection = win.getSelection();
        var range = doc.createRange();
        range.selectNodeContents(element);
        selection.removeAllRanges();
        selection.addRange(range);
      }     
    }
  }

  componentDidMount() {
    // Element has been rendered, start capturing keyboard activity
    window.document.addEventListener('keydown', this.handleKeyDown);
  }

  componnetWillUnmount() {
    // Element is no longer been rendered, stop listening
    window.document.removeEventListener('keydown', this.handleKeyDown);
  }

  render() {
    return (
      <div>
        <p>
          Some text I don't want selected.
        </p>
        <p>
          More text I don't want selected.
        </p>
        <Dialog open>
          // Capture a reference to the div's DOM element inside ref={...} as this.dialogBody
          <div ref={(ref) => (this.dialogBody = ref)}>
            <h1>Hello World!</h1>
            <p>Nice day, isn't it?</p>
          </div>
        </Dialog>
      </div>
    );
  }
}

export default HelloWorld;

The code that actually performs the selection of text confined to a DOM element can be seen in slight variations in other answers on SO:

Select all DIV text with single mouse click

selecting all text within a div on a single left click with javascript

Select all or highlight all Text in an Element

...the only additional 'trick' is knowing where to put DOM manipulation code like this within the React component lifecycle (primarily componentDidMount, usually with the help of a ref, and sometimes cleanup is necessary in componentWillUnmount)

Upvotes: 2

Related Questions