diff --git a/internal_packages/composer/lib/contenteditable-component.cjsx b/internal_packages/composer/lib/contenteditable-component.cjsx index fe1f52d03..5db6103d3 100644 --- a/internal_packages/composer/lib/contenteditable-component.cjsx +++ b/internal_packages/composer/lib/contenteditable-component.cjsx @@ -2,7 +2,7 @@ _ = require 'underscore' React = require 'react' classNames = require 'classnames' sanitizeHtml = require 'sanitize-html' -{Utils, QuotedHTMLParser, DraftStore} = require 'nylas-exports' +{DOMUtils, Utils, QuotedHTMLParser, DraftStore} = require 'nylas-exports' FloatingToolbar = require './floating-toolbar' linkUUID = 0 @@ -627,6 +627,13 @@ class ContenteditableComponent extends React.Component selection = document.getSelection() range = selection.getRangeAt(0) + + # On Windows, right-clicking a word does not select it at the OS-level. + # We need to implement this behavior locally for the rest of the logic here. + if range.collapsed + DOMUtils.selectWordContainingRange(range) + range = selection.getRangeAt(0) + text = range.toString() remote = require('remote') diff --git a/src/dom-utils.coffee b/src/dom-utils.coffee index b5da06b8a..55bd8b720 100644 --- a/src/dom-utils.coffee +++ b/src/dom-utils.coffee @@ -1,4 +1,5 @@ _ = require 'underscore' +_s = require 'underscore.string' DOMUtils = @@ -85,6 +86,29 @@ DOMUtils = nodes.unshift(node) while node = node.parentNode return nodes + # This method finds the bounding points of the word that the range + # is currently within and selects that word. + selectWordContainingRange: (range) -> + selection = document.getSelection() + node = selection.focusNode + text = node.textContent + wordStart = _s.reverse(text.substring(0, selection.focusOffset)).search(/\s/) + if wordStart is -1 + wordStart = 0 + else + wordStart = selection.focusOffset - wordStart + wordEnd = text.substring(selection.focusOffset).search(/\s/) + if wordEnd is -1 + wordEnd = text.length + else + wordEnd += selection.focusOffset + + selection.removeAllRanges() + range = new Range() + range.setStart(node, wordStart) + range.setEnd(node, wordEnd) + selection.addRange(range) + commonAncestor: (nodes=[]) -> nodes = Array::slice.call(nodes)