1
0
mirror of https://github.com/roytam1/UXP.git synced 2026-05-27 13:28:54 +00:00
Files
UXP/mobile/android/chrome/content/FindHelper.js
T

198 lines
6.9 KiB
JavaScript

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
var FindHelper = {
_finder: null,
_targetTab: null,
_initialViewport: null,
_viewportChanged: false,
_result: null,
// Start of nsIObserver implementation.
observe: function(aMessage, aTopic, aData) {
switch(aTopic) {
case "FindInPage:Opened": {
this._findOpened();
break;
}
case "Tab:Selected": {
// Allow for page switching.
this._uninit();
break;
}
case "FindInPage:Closed":
this._uninit();
this._findClosed();
break;
}
},
/**
* When the FindInPageBar opens/ becomes visible, it's time to:
* 1. Add listeners for other message types sent from the FindInPageBar
* 2. initialize the Finder instance, if necessary.
*/
_findOpened: function() {
Messaging.addListener(data => this.doFind(data), "FindInPage:Find");
Messaging.addListener(data => this.findAgain(data, false), "FindInPage:Next");
Messaging.addListener(data => this.findAgain(data, true), "FindInPage:Prev");
// Initialize the finder component for the current page by performing a fake find.
this._init();
this._finder.requestMatchesCount("");
},
/**
* Fetch the Finder instance from the active tabs' browser and start tracking
* the active viewport.
*/
_init: function() {
// If there's no find in progress, start one.
if (this._finder) {
return;
}
this._targetTab = BrowserApp.selectedTab;
try {
this._finder = this._targetTab.browser.finder;
} catch (e) {
throw new Error("FindHelper: " + e + "\n" +
"JS stack: \n" + (e.stack || Components.stack.formattedStack));
}
this._finder.addResultListener(this);
this._initialViewport = JSON.stringify(this._targetTab.getViewport());
this._viewportChanged = false;
},
/**
* Detach from the Finder instance (so stop listening for messages) and stop
* tracking the active viewport.
*/
_uninit: function() {
// If there's no find in progress, there's nothing to clean up.
if (!this._finder) {
return;
}
this._finder.removeSelection();
this._finder.removeResultListener(this);
this._finder = null;
this._targetTab = null;
this._initialViewport = null;
this._viewportChanged = false;
},
/**
* When the FindInPageBar closes, it's time to stop listening for its messages.
*/
_findClosed: function() {
Messaging.removeListener("FindInPage:Find");
Messaging.removeListener("FindInPage:Next");
Messaging.removeListener("FindInPage:Prev");
},
/**
* Start an asynchronous find-in-page operation, using the current Finder
* instance and request to count the amount of matches.
* If no Finder instance is currently active, we'll lazily initialize it here.
*
* @param {String} searchString Word to search for in the current document
* @return {Object} Echo of the current find action
*/
doFind: function(searchString) {
if (!this._finder) {
this._init();
}
this._finder.fastFind(searchString, false);
return { searchString, findBackwards: false };
},
/**
* Restart the same find-in-page operation as before via `doFind()`. If we
* haven't called `doFind()`, we simply kick off a regular find.
*
* @param {String} searchString Word to search for in the current document
* @param {Boolean} findBackwards Direction to search in
* @return {Object} Echo of the current find action
*/
findAgain: function(searchString, findBackwards) {
// This always happens if the user taps next/previous after re-opening the
// search bar, and not only forces _init() but also an initial fastFind(STRING)
// before any findAgain(DIRECTION).
if (!this._finder) {
return this.doFind(searchString);
}
this._finder.findAgain(findBackwards, false, false);
return { searchString, findBackwards };
},
// Start of Finder.jsm listener implementation.
/**
* Pass along the count results to FindInPageBar for display. The result that
* is sent to the FindInPageBar is augmented with the current find-in-page count
* limit.
*
* @param {Object} result Result coming from the Finder instance that contains
* the following properties:
* - {Number} total The total amount of matches found
* - {Number} current The index of current found range
* in the document
*/
onMatchesCountResult: function(result) {
this._result = result;
Messaging.sendRequest(Object.assign({
type: "FindInPage:MatchesCountResult"
}, this._result));
},
/**
* When a find-in-page action finishes, this method is invoked. This is mainly
* used at the moment to detect if the current viewport has changed, which might
* be indicated by not finding a string in the current page.
*
* @param {Object} aData A dictionary, representing the find result, which
* contains the following properties:
* - {String} searchString Word that was searched for
* in the current document
* - {Number} result One of the following
* Ci.nsITypeAheadFind.* result
* indicators: FIND_FOUND,
* FIND_NOTFOUND, FIND_WRAPPED,
* FIND_PENDING
* - {Boolean} findBackwards Whether the search direction
* was backwards
* - {Boolean} findAgain Whether the previous search
* was repeated
* - {Boolean} drawOutline Whether we may (re-)draw the
* outline of a hyperlink
* - {Boolean} linksOnly Whether links-only mode was
* active
*/
onFindResult: function(aData) {
if (aData.result == Ci.nsITypeAheadFind.FIND_NOTFOUND) {
if (this._viewportChanged) {
if (this._targetTab != BrowserApp.selectedTab) {
// this should never happen
Cu.reportError("Warning: selected tab changed during find!");
// fall through and restore viewport on the initial tab anyway
}
this._targetTab.sendViewportUpdate();
}
} else {
// Disabled until bug 1014113 is fixed
// ZoomHelper.zoomToRect(aData.rect);
this._viewportChanged = true;
}
}
};