1 /* -*- mode: js; indent-tabs-mode: nil; js-indent-level: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 export var SelectionUtils = {
8 * Trim the selection text to a reasonable size and sanitize it to make it
9 * safe for search query input.
12 * The selection text to trim.
14 * The maximum string length, defaults to a reasonable size if undefined.
15 * @return The trimmed selection text.
17 trimSelection(aSelection, aMaxLen) {
18 // Selections of more than 150 characters aren't useful.
19 const maxLen = Math.min(aMaxLen || 150, aSelection.length);
21 if (aSelection.length > maxLen) {
22 // only use the first maxLen important chars. see bug 221361
23 let pattern = new RegExp("^(?:\\s*.){0," + maxLen + "}");
24 pattern.test(aSelection);
25 aSelection = RegExp.lastMatch;
28 aSelection = aSelection.trim().replace(/\s+/g, " ");
30 if (aSelection.length > maxLen) {
31 aSelection = aSelection.substr(0, maxLen);
38 * Retrieve the text selection details for the given window.
41 * The top window of the element containing the selection.
43 * The maximum string length for the selection text.
44 * @return The selection details containing the full and trimmed selection text
45 * and link details for link selections.
47 getSelectionDetails(aTopWindow, aCharLen) {
48 let focusedWindow = {};
49 let focusedElement = Services.focus.getFocusedElementForWindow(
54 focusedWindow = focusedWindow.value;
56 let selection = focusedWindow.getSelection();
57 let selectionStr = selection.toString();
63 let isDocumentLevelSelection = true;
64 // try getting a selected text in text input.
65 if (!selectionStr && focusedElement) {
66 // Don't get the selection for password fields. See bug 565717.
68 ChromeUtils.getClassName(focusedElement) === "HTMLTextAreaElement" ||
69 (ChromeUtils.getClassName(focusedElement) === "HTMLInputElement" &&
70 focusedElement.mozIsTextField(true))
72 selection = focusedElement.editor.selection;
73 selectionStr = selection.toString();
74 isDocumentLevelSelection = false;
78 let collapsed = selection.isCollapsed;
81 // Have some text, let's figure out if it looks like a URL that isn't
83 linkText = selectionStr.trim();
84 if (/^(?:https?|ftp):/i.test(linkText)) {
86 url = Services.io.newURI(linkText);
88 } else if (/^(?:[a-z\d-]+\.)+[a-z]+$/i.test(linkText)) {
89 // Check if this could be a valid url, just missing the protocol.
90 // Now let's see if this is an intentional link selection. Our guess is
91 // based on whether the selection begins/ends with whitespace or is
92 // preceded/followed by a non-word character.
94 // selection.toString() trims trailing whitespace, so we look for
95 // that explicitly in the first and last ranges.
96 let beginRange = selection.getRangeAt(0);
97 let delimitedAtStart = /^\s/.test(beginRange);
98 if (!delimitedAtStart) {
99 let container = beginRange.startContainer;
100 let offset = beginRange.startOffset;
101 if (container.nodeType == container.TEXT_NODE && offset > 0) {
102 delimitedAtStart = /\W/.test(container.textContent[offset - 1]);
104 delimitedAtStart = true;
108 let delimitedAtEnd = false;
109 if (delimitedAtStart) {
110 let endRange = selection.getRangeAt(selection.rangeCount - 1);
111 delimitedAtEnd = /\s$/.test(endRange);
112 if (!delimitedAtEnd) {
113 let container = endRange.endContainer;
114 let offset = endRange.endOffset;
116 container.nodeType == container.TEXT_NODE &&
117 offset < container.textContent.length
119 delimitedAtEnd = /\W/.test(container.textContent[offset]);
121 delimitedAtEnd = true;
126 if (delimitedAtStart && delimitedAtEnd) {
128 url = Services.uriFixup.getFixupURIInfo(linkText).preferredURI;
135 // Pass up to 16K through unmolested. If an add-on needs more, they will
136 // have to use a content script.
137 fullText = selectionStr.substr(0, 16384);
138 selectionStr = this.trimSelection(selectionStr, aCharLen);
141 if (url && !url.host) {
147 docSelectionIsCollapsed: collapsed,
148 isDocumentLevelSelection,
150 linkURL: url ? url.spec : null,
151 linkText: url ? linkText : "",