mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 595236 - Match Tabs From Other Windows in Panorama Search [r=dietrich, a=blocking]
--HG-- rename : browser/base/content/test/tabview/browser_tabview_search.js => browser/base/content/test/tabview/browser_tabview_multiwindow_search.js extra : rebase_source : ff634626a815445d66fb94d4e1e263a79173affc
This commit is contained in:
parent
282c374265
commit
e08e388ec4
@ -101,6 +101,11 @@ let TabView = {
|
||||
Services.obs.addObserver(observer, "quit-application-requested", false);
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
getContentWindow: function TabView_getContentWindow() {
|
||||
return this._window;
|
||||
},
|
||||
|
||||
// ----------
|
||||
isVisible: function() {
|
||||
|
@ -109,6 +109,43 @@ function scorePatternMatch(pattern, matched, offset) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// ##########
|
||||
// Class: TabUtils
|
||||
//
|
||||
// A collection of helper functions for dealing with both
|
||||
// <TabItem>s and <xul:tab>s without having to worry which
|
||||
// one is which.
|
||||
var TabUtils = {
|
||||
// ---------
|
||||
// Function: _nameOfTab
|
||||
// Given a <TabItem> or a <xul:tab> returns the tab's name.
|
||||
nameOf: function TabUtils_nameOfTab(tab) {
|
||||
// We can have two types of tabs: A <TabItem> or a <xul:tab>
|
||||
// because we have to deal with both tabs represented inside
|
||||
// of active Panoramas as well as for windows in which
|
||||
// Panorama has yet to be activated. We uses object sniffing to
|
||||
// determine the type of tab and then returns its name.
|
||||
return tab.label != undefined ? tab.label : tab.nameEl.innerHTML;
|
||||
},
|
||||
|
||||
// ---------
|
||||
// Function: favURLOf
|
||||
// Given a <TabItem> or a <xul:tab> returns the URL of tab's favicon.
|
||||
faviconURLOf: function TabUtils_faviconURLOf(tab) {
|
||||
return tab.image != undefined ? tab.image : tab.favEl.src;
|
||||
},
|
||||
|
||||
// ---------
|
||||
// Function: focus
|
||||
// Given a <TabItem> or a <xul:tab>, focuses it and it's window.
|
||||
focus: function TabUtils_focus(tab) {
|
||||
// Convert a <TabItem> to a <xul:tab>
|
||||
if (tab.tab != undefined) tab = tab.tab;
|
||||
tab.ownerDocument.defaultView.gBrowser.selectedTab = tab;
|
||||
tab.ownerDocument.defaultView.focus();
|
||||
}
|
||||
};
|
||||
|
||||
// ##########
|
||||
// Class: TabMatcher
|
||||
//
|
||||
@ -119,66 +156,141 @@ function TabMatcher(term) {
|
||||
this.term = term;
|
||||
}
|
||||
|
||||
TabMatcher.prototype = {
|
||||
TabMatcher.prototype = {
|
||||
// ---------
|
||||
// Function: _filterAndSortMatches
|
||||
// Given an array of <TabItem>s and <xul:tab>s returns a new array
|
||||
// of tabs whose name matched the search term, sorted by lexical
|
||||
// closeness.
|
||||
_filterAndSortForMatches: function TabMatcher__filterAndSortForMatches(tabs) {
|
||||
var self = this;
|
||||
tabs = tabs.filter(function(tab){
|
||||
var name = TabUtils.nameOf(tab);
|
||||
return name.match(self.term, "i");
|
||||
});
|
||||
|
||||
tabs.sort(function sorter(x, y){
|
||||
var yScore = scorePatternMatch(self.term, TabUtils.nameOf(y));
|
||||
var xScore = scorePatternMatch(self.term, TabUtils.nameOf(x));
|
||||
return yScore - xScore;
|
||||
});
|
||||
|
||||
return tabs;
|
||||
},
|
||||
|
||||
// ---------
|
||||
// Function: _filterForUnmatches
|
||||
// Given an array of <TabItem>s returns an unsorted array of tabs whose name
|
||||
// does not match the the search term.
|
||||
_filterForUnmatches: function TabMatcher__filterForUnmatches(tabs) {
|
||||
var self = this;
|
||||
return tabs.filter(function(tab) {
|
||||
var name = tab.nameEl.innerHTML;
|
||||
return !name.match(self.term, "i");
|
||||
});
|
||||
},
|
||||
|
||||
// ---------
|
||||
// Function: _getTabsForOtherWindows
|
||||
// Returns an array of <TabItem>s and <xul:tabs>s representing that
|
||||
// tabs from all windows but the currently focused window. <TabItem>s
|
||||
// will be returned for windows in which Panorama has been activated at
|
||||
// least once, while <xul:tab>s will be return for windows in which
|
||||
// Panorama has never been activated.
|
||||
_getTabsForOtherWindows: function TabMatcher__getTabsForOtherWindows(){
|
||||
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
||||
.getService(Components.interfaces.nsIWindowMediator);
|
||||
var enumerator = wm.getEnumerator("navigator:browser");
|
||||
var currentWindow = wm.getMostRecentWindow("navigator:browser");
|
||||
|
||||
var allTabs = [];
|
||||
while (enumerator.hasMoreElements()) {
|
||||
var win = enumerator.getNext();
|
||||
// This function gets tabs from other windows: not the one you currently
|
||||
// have focused.
|
||||
if (win != currentWindow) {
|
||||
// If TabView is around iterate over all tabs, else get the currently
|
||||
// shown tabs...
|
||||
|
||||
tvWindow = win.TabView.getContentWindow();
|
||||
if (tvWindow)
|
||||
allTabs = allTabs.concat( tvWindow.TabItems.getItems() );
|
||||
else
|
||||
// win.gBrowser.tabs isn't a proper array, so we can't use concat
|
||||
for (var i=0; i<win.gBrowser.tabs.length; i++) allTabs.push( win.gBrowser.tabs[i] );
|
||||
}
|
||||
}
|
||||
return allTabs;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: matchedTabsFromOtherWindows
|
||||
// Returns an array of <TabItem>s and <xul:tab>s that match the search term
|
||||
// from all windows but the currently focused window. <TabItem>s will be
|
||||
// returned for windows in which Panorama has been activated at least once,
|
||||
// while <xul:tab>s will be return for windows in which Panorama has never
|
||||
// been activated.
|
||||
// (new TabMatcher("app")).matchedTabsFromOtherWindows();
|
||||
matchedTabsFromOtherWindows: function TabMatcher_matchedTabsFromOtherWindows(){
|
||||
if (this.term.length < 2)
|
||||
return [];
|
||||
|
||||
var tabs = this._getTabsForOtherWindows();
|
||||
tabs = this._filterAndSortForMatches(tabs);
|
||||
return tabs;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: matched
|
||||
// Returns an array of <TabItem>s which match the current search term.
|
||||
// If the term is less than 2 characters in length, it returns
|
||||
// nothing.
|
||||
matched: function matched() {
|
||||
var self = this;
|
||||
matched: function TabMatcher_matched() {
|
||||
if (this.term.length < 2)
|
||||
return [];
|
||||
|
||||
|
||||
var tabs = TabItems.getItems();
|
||||
tabs = tabs.filter(function(tab){
|
||||
var name = tab.nameEl.innerHTML;
|
||||
return name.match(self.term, "i");
|
||||
});
|
||||
|
||||
tabs.sort(function sorter(x, y){
|
||||
var yScore = scorePatternMatch(self.term, y.nameEl.innerHTML);
|
||||
var xScore = scorePatternMatch(self.term, x.nameEl.innerHTML);
|
||||
return yScore - xScore;
|
||||
});
|
||||
|
||||
tabs = this._filterAndSortForMatches(tabs);
|
||||
return tabs;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: unmatched
|
||||
// Returns all of <TabItem>s that .matched() doesn't return.
|
||||
unmatched: function unmatched() {
|
||||
var self = this;
|
||||
unmatched: function TabMatcher_unmatched() {
|
||||
var tabs = TabItems.getItems();
|
||||
|
||||
if ( this.term.length < 2 )
|
||||
return tabs;
|
||||
|
||||
return tabs.filter(function(tab) {
|
||||
var name = tab.nameEl.innerHTML;
|
||||
return !name.match(self.term, "i");
|
||||
});
|
||||
|
||||
return this._filterForUnmatches(tabs);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: doSearch
|
||||
// Performs the search. Lets you provide two functions, one that is called
|
||||
// on all matched tabs, and one that is called on all unmatched tabs.
|
||||
// Both functions take two parameters: A <TabItem> and its integer index
|
||||
// Performs the search. Lets you provide three functions.
|
||||
// The first is on all matched tabs in the window, the second on all unmatched
|
||||
// tabs in the window, and the third on all matched tabs in other windows.
|
||||
// The first two functions take two parameters: A <TabItem> and its integer index
|
||||
// indicating the absolute rank of the <TabItem> in terms of match to
|
||||
// the search term.
|
||||
doSearch: function(matchFunc, unmatchFunc) {
|
||||
// the search term. The last function also takes two paramaters, but can be
|
||||
// passed both <TabItem>s and <xul:tab>s and the index is offset by the
|
||||
// number of matched tabs inside the window.
|
||||
doSearch: function TabMatcher_doSearch(matchFunc, unmatchFunc, otherFunc) {
|
||||
var matches = this.matched();
|
||||
var unmatched = this.unmatched();
|
||||
var otherMatches = this.matchedTabsFromOtherWindows();
|
||||
|
||||
matches.forEach(function(tab, i) {
|
||||
matchFunc(tab, i);
|
||||
});
|
||||
|
||||
otherMatches.forEach(function(tab,i){
|
||||
otherFunc(tab, i+matches.length);
|
||||
});
|
||||
|
||||
unmatched.forEach(function(tab, i) {
|
||||
unmatchFunc(tab, i);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@ -247,9 +359,14 @@ SearchEventHandlerClass.prototype = {
|
||||
if (event.which == event.DOM_VK_BACK_SPACE && term.length <= 1)
|
||||
hideSearch(event);
|
||||
|
||||
var matches = (new TabMatcher(term)).matched();
|
||||
if (event.which == event.DOM_VK_RETURN && matches.length > 0) {
|
||||
matches[0].zoomIn();
|
||||
var matcher = new TabMatcher(term);
|
||||
var matches = matcher.matched();
|
||||
var others = matcher.matchedTabsFromOtherWindows();
|
||||
if (event.which == event.DOM_VK_RETURN && (matches.length > 0 || others.length > 0)) {
|
||||
if (matches.length > 0)
|
||||
matches[0].zoomIn();
|
||||
else
|
||||
TabUtils.focus(others[0]);
|
||||
hideSearch(event);
|
||||
}
|
||||
},
|
||||
@ -281,24 +398,23 @@ SearchEventHandlerClass.prototype = {
|
||||
|
||||
var TabHandlers = {
|
||||
onMatch: function(tab, index){
|
||||
tab.setZ(1010);
|
||||
index != 0 ? tab.addClass("notMainMatch") : tab.removeClass("notMainMatch");
|
||||
|
||||
// Remove any existing handlers before adding the new ones.
|
||||
// If we don't do this, then we may add more handlers than
|
||||
// we remove.
|
||||
iQ(tab.canvasEl)
|
||||
tab.addClass("onTop");
|
||||
index != 0 ? tab.addClass("notMainMatch") : tab.removeClass("notMainMatch");
|
||||
|
||||
// Remove any existing handlers before adding the new ones.
|
||||
// If we don't do this, then we may add more handlers than
|
||||
// we remove.
|
||||
iQ(tab.canvasEl)
|
||||
.unbind("mousedown", TabHandlers._hideHandler)
|
||||
.unbind("mouseup", TabHandlers._showHandler);
|
||||
|
||||
iQ(tab.canvasEl)
|
||||
|
||||
iQ(tab.canvasEl)
|
||||
.mousedown(TabHandlers._hideHandler)
|
||||
.mouseup(TabHandlers._showHandler);
|
||||
},
|
||||
|
||||
onUnmatch: function(tab, index){
|
||||
// TODO: Set back as value per tab. bug 593902
|
||||
tab.setZ(500);
|
||||
iQ(tab.container).removeClass("onTop");
|
||||
tab.removeClass("notMainMatch");
|
||||
|
||||
iQ(tab.canvasEl)
|
||||
@ -306,6 +422,30 @@ var TabHandlers = {
|
||||
.unbind("mouseup", TabHandlers._showHandler);
|
||||
},
|
||||
|
||||
onOther: function(tab, index){
|
||||
// Unlike the other on* functions, in this function tab can
|
||||
// either be a <TabItem> or a <xul:tab>. In other functions
|
||||
// it is always a <TabItem>. Also note that index is offset
|
||||
// by the number of matches within the window.
|
||||
var item = iQ("<div/>")
|
||||
.addClass("inlineMatch")
|
||||
.click(function(){
|
||||
TabUtils.focus(tab);
|
||||
});
|
||||
|
||||
iQ("<img/>")
|
||||
.attr("src", TabUtils.faviconURLOf(tab) )
|
||||
.appendTo(item);
|
||||
|
||||
iQ("<span/>")
|
||||
.text( TabUtils.nameOf(tab) )
|
||||
.appendTo(item);
|
||||
|
||||
index != 0 ? item.addClass("notMainMatch") : item.removeClass("notMainMatch");
|
||||
item.appendTo("#results");
|
||||
iQ("#otherresults").show();
|
||||
},
|
||||
|
||||
_hideHandler: function(event){
|
||||
iQ("#search").fadeOut();
|
||||
TabHandlers._mouseDownLocation = {x:event.clientX, y:event.clientY};
|
||||
@ -358,7 +498,14 @@ function hideSearch(event){
|
||||
|
||||
function performSearch() {
|
||||
var matcher = new TabMatcher(iQ("#searchbox").val());
|
||||
matcher.doSearch(TabHandlers.onMatch, TabHandlers.onUnmatch);
|
||||
|
||||
// Remove any previous other-window search results and
|
||||
// hide the display area.
|
||||
iQ("#results").empty();
|
||||
iQ("#otherresults").hide();
|
||||
iQ("#otherresults>.label").text(tabviewString("search.otherWindowTabs"));
|
||||
|
||||
matcher.doSearch(TabHandlers.onMatch, TabHandlers.onUnmatch, TabHandlers.onOther);
|
||||
}
|
||||
|
||||
function ensureSearchShown(event){
|
||||
|
@ -226,3 +226,22 @@ body {
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
#otherresults{
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.onTop{
|
||||
z-index: 1010 !important;
|
||||
}
|
||||
|
||||
.inlineMatch{
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.inlineMatch>span{
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
@ -20,6 +20,10 @@
|
||||
|
||||
<div id="search">
|
||||
<input id="searchbox" type="text"/>
|
||||
<div id="otherresults">
|
||||
<span class="label"></span>
|
||||
<span id="results"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript;version=1.8" src="tabview.js"></script>
|
||||
|
@ -55,6 +55,7 @@ _BROWSER_FILES = \
|
||||
browser_tabview_exit_button.js \
|
||||
browser_tabview_group.js \
|
||||
browser_tabview_launch.js \
|
||||
browser_tabview_multiwindow_search.js \
|
||||
browser_tabview_search.js \
|
||||
browser_tabview_snapping.js \
|
||||
browser_tabview_undo_group.js \
|
||||
|
@ -0,0 +1,184 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is tabview search test.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Raymond Lee <raymond@appcoast.com>
|
||||
* Ehsan Akhgari <ehsan@mozilla.com>
|
||||
* Sean Dunn <seanedunn@yahoo.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
let newWindows = [];
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
let windowOne = openDialog(location, "", "chrome,all,dialog=no", "data:text/html,");
|
||||
let windowTwo;
|
||||
|
||||
windowOne.addEventListener("load", function() {
|
||||
windowOne.gBrowser.selectedBrowser.addEventListener("load", function() {
|
||||
windowOne.gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
windowTwo = openDialog(location, "", "chrome,all,dialog=no", "http://mochi.test:8888/");
|
||||
windowTwo.addEventListener("load", function() {
|
||||
windowTwo.gBrowser.selectedBrowser.addEventListener("load", function() {
|
||||
windowTwo.gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
newWindows = [ windowOne, windowTwo ];
|
||||
|
||||
// show the tab view
|
||||
window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||
ok(!TabView.isVisible(), "Tab View is hidden");
|
||||
TabView.toggle();
|
||||
}, true);
|
||||
}, false);
|
||||
}, true);
|
||||
}, false);
|
||||
}
|
||||
|
||||
function onTabViewWindowLoaded() {
|
||||
window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||
ok(TabView.isVisible(), "Tab View is visible");
|
||||
|
||||
let contentWindow = document.getElementById("tab-view").contentWindow;
|
||||
let search = contentWindow.document.getElementById("search");
|
||||
let searchButton = contentWindow.document.getElementById("searchbutton");
|
||||
|
||||
ok(searchButton, "Search button exists");
|
||||
|
||||
let onSearchEnabled = function() {
|
||||
ok(search.style.display != "none", "Search is enabled");
|
||||
contentWindow.removeEventListener(
|
||||
"tabviewsearchenabled", onSearchEnabled, false);
|
||||
searchTest(contentWindow);
|
||||
}
|
||||
contentWindow.addEventListener("tabviewsearchenabled", onSearchEnabled, false);
|
||||
// enter search mode
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" }, searchButton, contentWindow);
|
||||
}
|
||||
|
||||
// conveniently combine local and other window tab results from a query
|
||||
function getMatchResults(contentWindow, query) {
|
||||
let matcher = new contentWindow.TabMatcher(query);
|
||||
let localMatchResults = matcher.matched();
|
||||
let otherMatchResults = matcher.matchedTabsFromOtherWindows();
|
||||
return localMatchResults.concat(otherMatchResults);
|
||||
}
|
||||
|
||||
function searchTest(contentWindow) {
|
||||
let searchBox = contentWindow.document.getElementById("searchbox");
|
||||
let matcher = null;
|
||||
let matchResults = [];
|
||||
|
||||
// get the titles of tabs.
|
||||
let tabNames = [];
|
||||
|
||||
let tabItems = contentWindow.TabItems.getItems();
|
||||
is(tabItems.length, 1, "Have only one tab in the current window's tab items");
|
||||
tabItems.forEach(function(tab) {
|
||||
tabNames.push(tab.nameEl.innerHTML);
|
||||
});
|
||||
|
||||
newWindows.forEach(function(win) {
|
||||
for(var i=0; i<win.gBrowser.tabs.length; ++i) {
|
||||
tabNames.push(win.gBrowser.tabs[i].label);
|
||||
}
|
||||
});
|
||||
|
||||
ok(tabNames[0] && tabNames[0].length > 2,
|
||||
"The title of tab item is longer than 2 chars")
|
||||
|
||||
// empty string
|
||||
searchBox.setAttribute("value", "");
|
||||
matchResults = getMatchResults(contentWindow, searchBox.getAttribute("value"));
|
||||
ok(matchResults.length == 0, "Match nothing if it's an empty string");
|
||||
|
||||
// one char
|
||||
searchBox.setAttribute("value", tabNames[0].charAt(0));
|
||||
matchResults = getMatchResults(contentWindow, searchBox.getAttribute("value"));
|
||||
ok(matchResults.length == 0,
|
||||
"Match nothing if the length of search term is less than 2");
|
||||
|
||||
// the full title
|
||||
searchBox.setAttribute("value", tabNames[2]);
|
||||
matchResults = getMatchResults(contentWindow, searchBox.getAttribute("value"));
|
||||
is(matchResults.length, 1,
|
||||
"Match something when the whole title exists");
|
||||
|
||||
// part of titled
|
||||
searchBox.setAttribute("value", tabNames[0].substr(1));
|
||||
contentWindow.performSearch();
|
||||
matchResults = getMatchResults(contentWindow, searchBox.getAttribute("value"));
|
||||
is(matchResults.length, 1,
|
||||
"Match something when a part of title exists");
|
||||
|
||||
cleanup(contentWindow);
|
||||
}
|
||||
|
||||
function cleanup(contentWindow) {
|
||||
contentWindow.hideSearch(null);
|
||||
|
||||
let onTabViewHidden = function() {
|
||||
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
ok(!TabView.isVisible(), "Tab View is hidden");
|
||||
let numToClose = newWindows.length;
|
||||
newWindows.forEach(function(win) {
|
||||
whenWindowObservesOnce(win, "domwindowclosed", function() {
|
||||
--numToClose;
|
||||
if(numToClose==0) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
win.close();
|
||||
});
|
||||
}
|
||||
window.addEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
EventUtils.synthesizeKey("VK_ENTER", {});
|
||||
}
|
||||
|
||||
function whenWindowObservesOnce(win, topic, func) {
|
||||
let windowWatcher = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
|
||||
.getService(Components.interfaces.nsIWindowWatcher);
|
||||
let origWin = win;
|
||||
let origTopic = topic;
|
||||
let origFunc = func;
|
||||
function windowObserver(aSubject, aTopic, aData) {
|
||||
let theWin = aSubject.QueryInterface(Ci.nsIDOMWindow);
|
||||
if (origWin && theWin != origWin)
|
||||
return;
|
||||
if(aTopic == origTopic) {
|
||||
windowWatcher.unregisterNotification(windowObserver);
|
||||
origFunc.apply(this, []);
|
||||
}
|
||||
}
|
||||
windowWatcher.registerNotification(windowObserver);
|
||||
}
|
@ -20,6 +20,7 @@
|
||||
*
|
||||
* Contributor(s):
|
||||
* Raymond Lee <raymond@appcoast.com>
|
||||
* Sean Dunn <seanedunn@yahoo.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -117,6 +118,11 @@ function searchTest(contentWindow) {
|
||||
searchBox.getAttribute("value")).matched().length == 2,
|
||||
"Match something when a part of title exists");
|
||||
|
||||
cleanup(contentWindow);
|
||||
}
|
||||
|
||||
function cleanup(contentWindow) {
|
||||
contentWindow.hideSearch(null);
|
||||
let onTabViewHidden = function() {
|
||||
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
ok(!TabView.isVisible(), "Tab View is hidden");
|
||||
|
@ -1,2 +1,3 @@
|
||||
tabview.groupItem.newTabButton=New tab
|
||||
tabview.groupItem.defaultName=Name this tab group…
|
||||
tabview.search.otherWindowTabs=Tabs from other windows
|
@ -449,3 +449,46 @@ input.defaultName {
|
||||
.notMainMatch{
|
||||
opacity: .70;
|
||||
}
|
||||
|
||||
#otherresults{
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
background-color: rgba(0,0,0,.3);
|
||||
-moz-box-shadow: 0px -1px 0px rgba(255,255,255,.1), inset 0px 2px 5px rgba(0,0,0,.3);
|
||||
}
|
||||
|
||||
#otherresults .label{
|
||||
color: #999;
|
||||
line-height:30px;
|
||||
margin-left:5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.inlineMatch{
|
||||
background-color: #EBEBEB;
|
||||
border-radius: 0.4em;
|
||||
-moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
|
||||
border: 1px solid rgba(255, 255, 255, 0.5);
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
height: 20px;
|
||||
margin-right: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.inlineMatch:hover{
|
||||
opacity: 1.0;
|
||||
}
|
||||
|
||||
.inlineMatch>img{
|
||||
margin-right: 5px;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
.inlineMatch>span{
|
||||
max-width:200px;
|
||||
height: 15px;
|
||||
}
|
||||
|
@ -455,3 +455,89 @@ input.defaultName {
|
||||
.notMainMatch{
|
||||
opacity: .70;
|
||||
}
|
||||
|
||||
#otherresults{
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
background-color: rgba(0,0,0,.3);
|
||||
-moz-box-shadow: 0px -1px 0px rgba(255,255,255,.1), inset 0px 2px 5px rgba(0,0,0,.3);
|
||||
}
|
||||
|
||||
#otherresults .label{
|
||||
color: #999;
|
||||
line-height:30px;
|
||||
margin-left:5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.inlineMatch{
|
||||
background-color: #EBEBEB;
|
||||
border-radius: 0.4em;
|
||||
-moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
|
||||
border: 1px solid rgba(255, 255, 255, 0.5);
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
height: 20px;
|
||||
margin-right: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.inlineMatch:hover{
|
||||
opacity: 1.0;
|
||||
}
|
||||
|
||||
.inlineMatch>img{
|
||||
margin-right: 5px;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
.inlineMatch>span{
|
||||
max-width:200px;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
#otherresults{
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
background-color: rgba(0,0,0,.3);
|
||||
-moz-box-shadow: 0px -1px 0px rgba(255,255,255,.1), inset 0px 2px 5px rgba(0,0,0,.3);
|
||||
}
|
||||
|
||||
#otherresults .label{
|
||||
color: #999;
|
||||
line-height:30px;
|
||||
margin-left:5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.inlineMatch{
|
||||
background-color: #EBEBEB;
|
||||
border-radius: 0.4em;
|
||||
-moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
|
||||
border: 1px solid rgba(255, 255, 255, 0.5);
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
height: 20px;
|
||||
margin-right: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.inlineMatch:hover{
|
||||
opacity: 1.0;
|
||||
}
|
||||
|
||||
.inlineMatch>img{
|
||||
margin-right: 5px;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
.inlineMatch>span{
|
||||
max-width:200px;
|
||||
height: 15px;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user