mirror of
https://github.com/roytam1/UXP.git
synced 2026-05-27 13:28:54 +00:00
198 lines
6.9 KiB
JavaScript
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;
|
|
}
|
|
}
|
|
};
|