mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
merge the last green changeset on m-c to fx-team
This commit is contained in:
commit
c5833c2f56
@ -1297,9 +1297,6 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
// Returns true if the groupItem, given "count", should stack (instead of
|
||||
// grid).
|
||||
shouldStack: function GroupItem_shouldStack(count) {
|
||||
if (count <= 1)
|
||||
return false;
|
||||
|
||||
let bb = this.getContentBounds();
|
||||
let options = {
|
||||
return: 'widthAndColumns',
|
||||
|
@ -53,80 +53,23 @@
|
||||
// Title: search.js
|
||||
// Implementation for the search functionality of Firefox Panorama.
|
||||
|
||||
// ----------
|
||||
// Function: scorePatternMatch
|
||||
// Given a pattern string, returns a score between 0 and 1 of how well
|
||||
// that pattern matches the original string. It mimics the heuristics
|
||||
// of the Mac application launcher Quicksilver.
|
||||
function scorePatternMatch(pattern, matched, offset) {
|
||||
offset = offset || 0;
|
||||
pattern = pattern.toLowerCase();
|
||||
matched = matched.toLowerCase();
|
||||
|
||||
if (pattern.length == 0) return 0.9;
|
||||
if (pattern.length > matched.length) return 0.0;
|
||||
|
||||
for (var i = pattern.length; i > 0; i--) {
|
||||
var sub_pattern = pattern.substring(0,i);
|
||||
var index = matched.indexOf(sub_pattern);
|
||||
|
||||
if (index < 0) continue;
|
||||
if (index + pattern.length > matched.length + offset) continue;
|
||||
|
||||
var next_string = matched.substring(index+sub_pattern.length);
|
||||
var next_pattern = null;
|
||||
|
||||
if (i >= pattern.length)
|
||||
next_pattern = '';
|
||||
else
|
||||
next_pattern = pattern.substring(i);
|
||||
|
||||
var remaining_score =
|
||||
scorePatternMatch(next_pattern, next_string, offset + index);
|
||||
|
||||
if (remaining_score > 0) {
|
||||
var score = matched.length-next_string.length;
|
||||
|
||||
if (index != 0) {
|
||||
var j = 0;
|
||||
|
||||
var c = matched.charCodeAt(index-1);
|
||||
if (c == 32 || c == 9) {
|
||||
for (var j = (index - 2); j >= 0; j--) {
|
||||
c = matched.charCodeAt(j);
|
||||
score -= ((c == 32 || c == 9) ? 1 : 0.15);
|
||||
}
|
||||
} else {
|
||||
score -= index;
|
||||
}
|
||||
}
|
||||
|
||||
score += remaining_score * next_string.length;
|
||||
score /= matched.length;
|
||||
return score;
|
||||
}
|
||||
}
|
||||
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 = {
|
||||
//
|
||||
// A collection of helper functions for dealing with both <TabItem>s and
|
||||
// <xul:tab>s without having to worry which one is which.
|
||||
let TabUtils = {
|
||||
// ----------
|
||||
// Function: toString
|
||||
// Prints [TabUtils] for debug use
|
||||
// Prints [TabUtils] for debug use.
|
||||
toString: function TabUtils_toString() {
|
||||
return "[TabUtils]";
|
||||
},
|
||||
|
||||
// ---------
|
||||
// Function: _nameOfTab
|
||||
// Function: nameOfTab
|
||||
// Given a <TabItem> or a <xul:tab> returns the tab's name.
|
||||
nameOf: function TabUtils_nameOfTab(tab) {
|
||||
nameOf: function TabUtils_nameOf(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
|
||||
@ -134,88 +77,88 @@ var TabUtils = {
|
||||
// determine the type of tab and then returns its name.
|
||||
return tab.label != undefined ? tab.label : tab.$tabTitle[0].textContent;
|
||||
},
|
||||
|
||||
|
||||
// ---------
|
||||
// Function: URLOf
|
||||
// Given a <TabItem> or a <xul:tab> returns the URL of tab
|
||||
// Given a <TabItem> or a <xul:tab> returns the URL of tab.
|
||||
URLOf: function TabUtils_URLOf(tab) {
|
||||
// Convert a <TabItem> to <xul:tab>
|
||||
if(tab.tab != undefined)
|
||||
if ("tab" in tab)
|
||||
tab = tab.tab;
|
||||
return tab.linkedBrowser.currentURI.spec;
|
||||
},
|
||||
|
||||
// ---------
|
||||
// Function: favURLOf
|
||||
// Function: faviconURLOf
|
||||
// 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.$favImage[0].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;
|
||||
if ("tab" in tab)
|
||||
tab = tab.tab;
|
||||
tab.ownerDocument.defaultView.gBrowser.selectedTab = tab;
|
||||
tab.ownerDocument.defaultView.focus();
|
||||
tab.ownerDocument.defaultView.focus();
|
||||
}
|
||||
};
|
||||
|
||||
// ##########
|
||||
// Class: TabMatcher
|
||||
//
|
||||
// A singleton class that allows you to iterate over
|
||||
// matching and not-matching tabs, given a case-insensitive
|
||||
// search term.
|
||||
function TabMatcher(term) {
|
||||
this.term = term;
|
||||
//
|
||||
// A class that allows you to iterate over matching and not-matching tabs,
|
||||
// given a case-insensitive search term.
|
||||
function TabMatcher(term) {
|
||||
this.term = term;
|
||||
}
|
||||
|
||||
TabMatcher.prototype = {
|
||||
// ----------
|
||||
// Function: toString
|
||||
// Prints [TabMatcher (term)] for debug use
|
||||
// Prints [TabMatcher (term)] for debug use.
|
||||
toString: function TabMatcher_toString() {
|
||||
return "[TabMatcher (" + this.term + ")]";
|
||||
},
|
||||
|
||||
// ---------
|
||||
// Function: _filterAndSortMatches
|
||||
// Function: _filterAndSortForMatches
|
||||
// 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.
|
||||
// closeness.
|
||||
_filterAndSortForMatches: function TabMatcher__filterAndSortForMatches(tabs) {
|
||||
var self = this;
|
||||
tabs = tabs.filter(function(tab){
|
||||
let self = this;
|
||||
tabs = tabs.filter(function TabMatcher__filterAndSortForMatches_filter(tab) {
|
||||
let name = TabUtils.nameOf(tab);
|
||||
let url = TabUtils.URLOf(tab);
|
||||
return name.match(self.term, "i") || url.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;
|
||||
tabs.sort(function TabMatcher__filterAndSortForMatches_sort(x, y) {
|
||||
let yScore = self._scorePatternMatch(self.term, TabUtils.nameOf(y));
|
||||
let xScore = self._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) {
|
||||
let self = this;
|
||||
return tabs.filter(function TabMatcher__filterForUnmatches_filter(tab) {
|
||||
let name = tab.$tabTitle[0].textContent;
|
||||
let url = TabUtils.URLOf(tab);
|
||||
return !name.match(self.term, "i") && !url.match(self.term, "i");
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
// ---------
|
||||
// Function: _getTabsForOtherWindows
|
||||
// Returns an array of <TabItem>s and <xul:tabs>s representing tabs
|
||||
@ -224,18 +167,18 @@ TabMatcher.prototype = {
|
||||
// <xul:tab>s will be returned for windows in which Panorama has never
|
||||
// been activated.
|
||||
_getTabsForOtherWindows: function TabMatcher__getTabsForOtherWindows() {
|
||||
var enumerator = Services.wm.getEnumerator("navigator:browser");
|
||||
var allTabs = [];
|
||||
let enumerator = Services.wm.getEnumerator("navigator:browser");
|
||||
let allTabs = [];
|
||||
|
||||
while (enumerator.hasMoreElements()) {
|
||||
var win = enumerator.getNext();
|
||||
let win = enumerator.getNext();
|
||||
// This function gets tabs from other windows, not from the current window
|
||||
if (win != gWindow)
|
||||
allTabs.push.apply(allTabs, win.gBrowser.tabs);
|
||||
}
|
||||
return allTabs;
|
||||
},
|
||||
|
||||
|
||||
// ----------
|
||||
// Function: matchedTabsFromOtherWindows
|
||||
// Returns an array of <TabItem>s and <xul:tab>s that match the search term
|
||||
@ -244,37 +187,34 @@ TabMatcher.prototype = {
|
||||
// <xul:tab>s will be returned for windows in which Panorama has never
|
||||
// been activated.
|
||||
// (new TabMatcher("app")).matchedTabsFromOtherWindows();
|
||||
matchedTabsFromOtherWindows: function TabMatcher_matchedTabsFromOtherWindows(){
|
||||
matchedTabsFromOtherWindows: function TabMatcher_matchedTabsFromOtherWindows() {
|
||||
if (this.term.length < 2)
|
||||
return [];
|
||||
|
||||
var tabs = this._getTabsForOtherWindows();
|
||||
tabs = this._filterAndSortForMatches(tabs);
|
||||
return tabs;
|
||||
|
||||
let tabs = this._getTabsForOtherWindows();
|
||||
return this._filterAndSortForMatches(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.
|
||||
// If the term is less than 2 characters in length, it returns nothing.
|
||||
matched: function TabMatcher_matched() {
|
||||
if (this.term.length < 2)
|
||||
return [];
|
||||
|
||||
var tabs = TabItems.getItems();
|
||||
tabs = this._filterAndSortForMatches(tabs);
|
||||
return tabs;
|
||||
|
||||
let tabs = TabItems.getItems();
|
||||
return this._filterAndSortForMatches(tabs);
|
||||
},
|
||||
|
||||
|
||||
// ----------
|
||||
// Function: unmatched
|
||||
// Returns all of <TabItem>s that .matched() doesn't return.
|
||||
unmatched: function TabMatcher_unmatched() {
|
||||
var tabs = TabItems.getItems();
|
||||
let tabs = TabItems.getItems();
|
||||
if (this.term.length < 2)
|
||||
return tabs;
|
||||
|
||||
|
||||
return this._filterForUnmatches(tabs);
|
||||
},
|
||||
|
||||
@ -289,73 +229,222 @@ TabMatcher.prototype = {
|
||||
// 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();
|
||||
let matches = this.matched();
|
||||
let unmatched = this.unmatched();
|
||||
let otherMatches = this.matchedTabsFromOtherWindows();
|
||||
|
||||
matches.forEach(function(tab, i) {
|
||||
matchFunc(tab, i);
|
||||
});
|
||||
|
||||
otherMatches.forEach(function(tab,i) {
|
||||
otherFunc(tab, i+matches.length);
|
||||
otherFunc(tab, i+matches.length);
|
||||
});
|
||||
|
||||
|
||||
unmatched.forEach(function(tab, i) {
|
||||
unmatchFunc(tab, i);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: _scorePatternMatch
|
||||
// Given a pattern string, returns a score between 0 and 1 of how well
|
||||
// that pattern matches the original string. It mimics the heuristics
|
||||
// of the Mac application launcher Quicksilver.
|
||||
_scorePatternMatch: function TabMatcher__scorePatternMatch(pattern, matched, offset) {
|
||||
offset = offset || 0;
|
||||
pattern = pattern.toLowerCase();
|
||||
matched = matched.toLowerCase();
|
||||
|
||||
if (pattern.length == 0)
|
||||
return 0.9;
|
||||
if (pattern.length > matched.length)
|
||||
return 0.0;
|
||||
|
||||
for (let i = pattern.length; i > 0; i--) {
|
||||
let sub_pattern = pattern.substring(0,i);
|
||||
let index = matched.indexOf(sub_pattern);
|
||||
|
||||
if (index < 0)
|
||||
continue;
|
||||
if (index + pattern.length > matched.length + offset)
|
||||
continue;
|
||||
|
||||
let next_string = matched.substring(index+sub_pattern.length);
|
||||
let next_pattern = null;
|
||||
|
||||
if (i >= pattern.length)
|
||||
next_pattern = '';
|
||||
else
|
||||
next_pattern = pattern.substring(i);
|
||||
|
||||
let remaining_score = this._scorePatternMatch(next_pattern, next_string, offset + index);
|
||||
|
||||
if (remaining_score > 0) {
|
||||
let score = matched.length-next_string.length;
|
||||
|
||||
if (index != 0) {
|
||||
let c = matched.charCodeAt(index-1);
|
||||
if (c == 32 || c == 9) {
|
||||
for (let j = (index - 2); j >= 0; j--) {
|
||||
c = matched.charCodeAt(j);
|
||||
score -= ((c == 32 || c == 9) ? 1 : 0.15);
|
||||
}
|
||||
} else {
|
||||
score -= index;
|
||||
}
|
||||
}
|
||||
|
||||
score += remaining_score * next_string.length;
|
||||
score /= matched.length;
|
||||
return score;
|
||||
}
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
};
|
||||
|
||||
// ##########
|
||||
// Class: SearchEventHandlerClass
|
||||
// Class: TabHandlers
|
||||
//
|
||||
// A singleton class that handles all of the
|
||||
// event handlers.
|
||||
function SearchEventHandlerClass() {
|
||||
this.init();
|
||||
}
|
||||
// A object that handles all of the event handlers.
|
||||
let TabHandlers = {
|
||||
_mouseDownLocation: null,
|
||||
|
||||
// ---------
|
||||
// Function: onMatch
|
||||
// Adds styles and event listeners to the matched tab items.
|
||||
onMatch: function TabHandlers_onMatch(tab, index) {
|
||||
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.
|
||||
tab.$canvas
|
||||
.unbind("mousedown", TabHandlers._hideHandler)
|
||||
.unbind("mouseup", TabHandlers._showHandler);
|
||||
|
||||
tab.$canvas
|
||||
.mousedown(TabHandlers._hideHandler)
|
||||
.mouseup(TabHandlers._showHandler);
|
||||
},
|
||||
|
||||
// ---------
|
||||
// Function: onUnmatch
|
||||
// Removes styles and event listeners from the unmatched tab items.
|
||||
onUnmatch: function TabHandlers_onUnmatch(tab, index) {
|
||||
tab.$container.removeClass("onTop");
|
||||
tab.removeClass("notMainMatch");
|
||||
|
||||
tab.$canvas
|
||||
.unbind("mousedown", TabHandlers._hideHandler)
|
||||
.unbind("mouseup", TabHandlers._showHandler);
|
||||
},
|
||||
|
||||
// ---------
|
||||
// Function: onOther
|
||||
// Removes styles and event listeners from the unmatched tabs.
|
||||
onOther: function TabHandlers_onOther(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.
|
||||
let item = iQ("<div/>")
|
||||
.addClass("inlineMatch")
|
||||
.click(function TabHandlers_onOther_click(event) {
|
||||
Search.hide(event);
|
||||
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();
|
||||
},
|
||||
|
||||
// ---------
|
||||
// Function: _hideHandler
|
||||
// Performs when mouse down on a canvas of tab item.
|
||||
_hideHandler: function TabHandlers_hideHandler(event) {
|
||||
iQ("#search").fadeOut();
|
||||
iQ("#searchshade").fadeOut();
|
||||
TabHandlers._mouseDownLocation = {x:event.clientX, y:event.clientY};
|
||||
},
|
||||
|
||||
// ---------
|
||||
// Function: _showHandler
|
||||
// Performs when mouse up on a canvas of tab item.
|
||||
_showHandler: function TabHandlers_showHandler(event) {
|
||||
// If the user clicks on a tab without moving the mouse then
|
||||
// they are zooming into the tab and we need to exit search
|
||||
// mode.
|
||||
if (TabHandlers._mouseDownLocation.x == event.clientX &&
|
||||
TabHandlers._mouseDownLocation.y == event.clientY) {
|
||||
Search.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
iQ("#searchshade").show();
|
||||
iQ("#search").show();
|
||||
iQ("#searchbox")[0].focus();
|
||||
// Marshal the search.
|
||||
setTimeout(Search.perform, 0);
|
||||
}
|
||||
};
|
||||
|
||||
// ##########
|
||||
// Class: Search
|
||||
//
|
||||
// A object that handles the search feature.
|
||||
let Search = {
|
||||
_initiatedBy: "",
|
||||
|
||||
_currentHandler: null,
|
||||
|
||||
SearchEventHandlerClass.prototype = {
|
||||
// ----------
|
||||
// Function: toString
|
||||
// Prints [SearchEventHandler] for debug use
|
||||
toString: function SearchEventHandlerClass_toString() {
|
||||
return "[SearchEventHandler]";
|
||||
// Prints [Search] for debug use.
|
||||
toString: function Search_toString() {
|
||||
return "[Search]";
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: init
|
||||
// Initializes the searchbox to be focused, and everything
|
||||
// else to be hidden, and to have everything have the appropriate
|
||||
// event handlers;
|
||||
init: function () {
|
||||
// Initializes the searchbox to be focused, and everything else to be hidden,
|
||||
// and to have everything have the appropriate event handlers.
|
||||
init: function Search_init() {
|
||||
let self = this;
|
||||
iQ("#search").hide();
|
||||
iQ("#searchshade").hide().click(function(event) {
|
||||
if ( event.target.id != "searchbox")
|
||||
hideSearch();
|
||||
if (event.target.id != "searchbox")
|
||||
self.hide();
|
||||
});
|
||||
|
||||
|
||||
iQ("#searchbox").keyup(function() {
|
||||
performSearch();
|
||||
self.perform();
|
||||
});
|
||||
|
||||
|
||||
iQ("#searchbutton").mousedown(function() {
|
||||
self.initiatedBy = "buttonclick";
|
||||
ensureSearchShown();
|
||||
self.switchToInMode();
|
||||
self._initiatedBy = "buttonclick";
|
||||
self.ensureShown();
|
||||
self.switchToInMode();
|
||||
});
|
||||
|
||||
this.initiatedBy = "";
|
||||
this.currentHandler = null;
|
||||
|
||||
this.switchToBeforeMode();
|
||||
},
|
||||
|
||||
|
||||
// ----------
|
||||
// Function: beforeSearchKeyHandler
|
||||
// Function: _beforeSearchKeyHandler
|
||||
// Handles all keydown before the search interface is brought up.
|
||||
beforeSearchKeyHandler: function (event) {
|
||||
_beforeSearchKeyHandler: function Search__beforeSearchKeyHandler(event) {
|
||||
// Only match reasonable text-like characters for quick search.
|
||||
if (event.altKey || event.ctrlKey || event.metaKey)
|
||||
return;
|
||||
@ -384,28 +473,29 @@ SearchEventHandlerClass.prototype = {
|
||||
}
|
||||
|
||||
this.switchToInMode();
|
||||
this.initiatedBy = "keydown";
|
||||
ensureSearchShown(true);
|
||||
this._initiatedBy = "keydown";
|
||||
this.ensureShown(true);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: inSearchKeyHandler
|
||||
// Function: _inSearchKeyHandler
|
||||
// Handles all keydown while search mode.
|
||||
inSearchKeyHandler: function (event) {
|
||||
_inSearchKeyHandler: function Search__inSearchKeyHandler(event) {
|
||||
let term = iQ("#searchbox").val();
|
||||
if ((event.keyCode == event.DOM_VK_ESCAPE) ||
|
||||
(event.keyCode == event.DOM_VK_BACK_SPACE && term.length <= 1 && this.initiatedBy == "keydown")) {
|
||||
hideSearch(event);
|
||||
if ((event.keyCode == event.DOM_VK_ESCAPE) ||
|
||||
(event.keyCode == event.DOM_VK_BACK_SPACE && term.length <= 1 &&
|
||||
this._initiatedBy == "keydown")) {
|
||||
this.hide(event);
|
||||
return;
|
||||
}
|
||||
|
||||
let matcher = createSearchTabMacher();
|
||||
let matcher = this.createSearchTabMatcher();
|
||||
let matches = matcher.matched();
|
||||
let others = matcher.matchedTabsFromOtherWindows();
|
||||
if ((event.keyCode == event.DOM_VK_RETURN ||
|
||||
event.keyCode == event.DOM_VK_ENTER) &&
|
||||
if ((event.keyCode == event.DOM_VK_RETURN ||
|
||||
event.keyCode == event.DOM_VK_ENTER) &&
|
||||
(matches.length > 0 || others.length > 0)) {
|
||||
hideSearch(event);
|
||||
this.hide(event);
|
||||
if (matches.length > 0)
|
||||
matches[0].zoomIn();
|
||||
else
|
||||
@ -415,206 +505,135 @@ SearchEventHandlerClass.prototype = {
|
||||
|
||||
// ----------
|
||||
// Function: switchToBeforeMode
|
||||
// Make sure the event handlers are appropriate for
|
||||
// the before-search mode.
|
||||
switchToBeforeMode: function switchToBeforeMode() {
|
||||
// Make sure the event handlers are appropriate for the before-search mode.
|
||||
switchToBeforeMode: function Search_switchToBeforeMode() {
|
||||
let self = this;
|
||||
if (this.currentHandler)
|
||||
iQ(window).unbind("keydown", this.currentHandler);
|
||||
this.currentHandler = function(event) self.beforeSearchKeyHandler(event);
|
||||
iQ(window).keydown(this.currentHandler);
|
||||
if (this._currentHandler)
|
||||
iQ(window).unbind("keydown", this._currentHandler);
|
||||
this._currentHandler = function Search_switchToBeforeMode_handler(event) {
|
||||
self._beforeSearchKeyHandler(event);
|
||||
}
|
||||
iQ(window).keydown(this._currentHandler);
|
||||
},
|
||||
|
||||
|
||||
// ----------
|
||||
// Function: switchToInMode
|
||||
// Make sure the event handlers are appropriate for
|
||||
// the in-search mode.
|
||||
switchToInMode: function switchToInMode() {
|
||||
// Make sure the event handlers are appropriate for the in-search mode.
|
||||
switchToInMode: function Search_switchToInMode() {
|
||||
let self = this;
|
||||
if (this.currentHandler)
|
||||
iQ(window).unbind("keydown", this.currentHandler);
|
||||
this.currentHandler = function(event) self.inSearchKeyHandler(event);
|
||||
iQ(window).keydown(this.currentHandler);
|
||||
}
|
||||
};
|
||||
|
||||
var TabHandlers = {
|
||||
onMatch: function(tab, index){
|
||||
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.
|
||||
tab.$canvas
|
||||
.unbind("mousedown", TabHandlers._hideHandler)
|
||||
.unbind("mouseup", TabHandlers._showHandler);
|
||||
|
||||
tab.$canvas
|
||||
.mousedown(TabHandlers._hideHandler)
|
||||
.mouseup(TabHandlers._showHandler);
|
||||
if (this._currentHandler)
|
||||
iQ(window).unbind("keydown", this._currentHandler);
|
||||
this._currentHandler = function Search_switchToInMode_handler(event) {
|
||||
self._inSearchKeyHandler(event);
|
||||
}
|
||||
iQ(window).keydown(this._currentHandler);
|
||||
},
|
||||
|
||||
onUnmatch: function(tab, index){
|
||||
tab.$container.removeClass("onTop");
|
||||
tab.removeClass("notMainMatch");
|
||||
|
||||
tab.$canvas
|
||||
.unbind("mousedown", TabHandlers._hideHandler)
|
||||
.unbind("mouseup", TabHandlers._showHandler);
|
||||
createSearchTabMatcher: function Search_createSearchTabMatcher() {
|
||||
return new TabMatcher(iQ("#searchbox").val());
|
||||
},
|
||||
|
||||
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.
|
||||
let item = iQ("<div/>")
|
||||
.addClass("inlineMatch")
|
||||
.click(function(event){
|
||||
hideSearch(event);
|
||||
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();
|
||||
|
||||
// ----------
|
||||
// Function: isEnabled
|
||||
// Checks whether search mode is enabled or not.
|
||||
isEnabled: function Search_isEnabled() {
|
||||
return iQ("#search").css("display") != "none";
|
||||
},
|
||||
|
||||
_hideHandler: function(event){
|
||||
iQ("#search").fadeOut();
|
||||
iQ("#searchshade").fadeOut();
|
||||
TabHandlers._mouseDownLocation = {x:event.clientX, y:event.clientY};
|
||||
},
|
||||
|
||||
_showHandler: function(event){
|
||||
// If the user clicks on a tab without moving the mouse then
|
||||
// they are zooming into the tab and we need to exit search
|
||||
// mode.
|
||||
if (TabHandlers._mouseDownLocation.x == event.clientX &&
|
||||
TabHandlers._mouseDownLocation.y == event.clientY){
|
||||
hideSearch();
|
||||
|
||||
// ----------
|
||||
// Function: hide
|
||||
// Hides search mode.
|
||||
hide: function Search_hide(event) {
|
||||
if (!this.isEnabled())
|
||||
return;
|
||||
|
||||
iQ("#searchbox").val("");
|
||||
iQ("#searchshade").hide();
|
||||
iQ("#search").hide();
|
||||
|
||||
iQ("#searchbutton").css({ opacity:.8 });
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
UI.setTitlebarColors(true);
|
||||
#endif
|
||||
|
||||
this.perform();
|
||||
this.switchToBeforeMode();
|
||||
|
||||
if (event) {
|
||||
// when hiding the search mode, we need to prevent the keypress handler
|
||||
// in UI__setTabViewFrameKeyHandlers to handle the key press again. e.g. Esc
|
||||
// which is already handled by the key down in this class.
|
||||
if (event.type == "keydown")
|
||||
UI.ignoreKeypressForSearch = true;
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
iQ("#searchshade").show();
|
||||
iQ("#search").show();
|
||||
iQ("#searchbox")[0].focus();
|
||||
// Marshal the search.
|
||||
setTimeout(performSearch, 0);
|
||||
// Return focus to the tab window
|
||||
UI.blurAll();
|
||||
gTabViewFrame.contentWindow.focus();
|
||||
|
||||
let newEvent = document.createEvent("Events");
|
||||
newEvent.initEvent("tabviewsearchdisabled", false, false);
|
||||
dispatchEvent(newEvent);
|
||||
},
|
||||
|
||||
_mouseDownLocation: null
|
||||
};
|
||||
|
||||
function createSearchTabMacher() {
|
||||
return new TabMatcher(iQ("#searchbox").val());
|
||||
}
|
||||
// ----------
|
||||
// Function: perform
|
||||
// Performs a search.
|
||||
perform: function Search_perform() {
|
||||
let matcher = this.createSearchTabMatcher();
|
||||
|
||||
function hideSearch(event) {
|
||||
if (!isSearchEnabled())
|
||||
return;
|
||||
// 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"));
|
||||
|
||||
iQ("#searchbox").val("");
|
||||
iQ("#searchshade").hide();
|
||||
iQ("#search").hide();
|
||||
matcher.doSearch(TabHandlers.onMatch, TabHandlers.onUnmatch, TabHandlers.onOther);
|
||||
},
|
||||
|
||||
iQ("#searchbutton").css({ opacity:.8 });
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
UI.setTitlebarColors(true);
|
||||
#endif
|
||||
|
||||
performSearch();
|
||||
SearchEventHandler.switchToBeforeMode();
|
||||
|
||||
if (event) {
|
||||
// when hiding the search mode, we need to prevent the keypress handler
|
||||
// in UI__setTabViewFrameKeyHandlers to handle the key press again. e.g. Esc
|
||||
// which is already handled by the key down in this class.
|
||||
if (event.type == "keydown")
|
||||
UI.ignoreKeypressForSearch = true;
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
// Return focus to the tab window
|
||||
UI.blurAll();
|
||||
gTabViewFrame.contentWindow.focus();
|
||||
|
||||
let newEvent = document.createEvent("Events");
|
||||
newEvent.initEvent("tabviewsearchdisabled", false, false);
|
||||
dispatchEvent(newEvent);
|
||||
}
|
||||
|
||||
function performSearch() {
|
||||
let matcher = new TabMatcher(iQ("#searchbox").val());
|
||||
|
||||
// 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
|
||||
// Ensure the search feature is displayed. If not, display it.
|
||||
// Parameters:
|
||||
// - a boolean indicates whether this is triggered by a keypress or not
|
||||
function ensureSearchShown(activatedByKeypress) {
|
||||
var $search = iQ("#search");
|
||||
var $searchShade = iQ("#searchshade");
|
||||
var $searchbox = iQ("#searchbox");
|
||||
iQ("#searchbutton").css({ opacity: 1 });
|
||||
|
||||
if (!isSearchEnabled()) {
|
||||
$searchShade.show();
|
||||
$search.show();
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
UI.setTitlebarColors({active: "#717171", inactive: "#EDEDED"});
|
||||
#endif
|
||||
// ----------
|
||||
// Function: ensureShown
|
||||
// Ensures the search feature is displayed. If not, display it.
|
||||
// Parameters:
|
||||
// - a boolean indicates whether this is triggered by a keypress or not
|
||||
ensureShown: function Search_ensureShown(activatedByKeypress) {
|
||||
let $search = iQ("#search");
|
||||
let $searchShade = iQ("#searchshade");
|
||||
let $searchbox = iQ("#searchbox");
|
||||
iQ("#searchbutton").css({ opacity: 1 });
|
||||
|
||||
// NOTE: when this function is called by keydown handler, next keypress
|
||||
// event or composition events of IME will be fired on the focused editor.
|
||||
let dispatchTabViewSearchEnabledEvent = function dispatchTabViewSearchEnabledEvent() {
|
||||
function dispatchTabViewSearchEnabledEvent() {
|
||||
let newEvent = document.createEvent("Events");
|
||||
newEvent.initEvent("tabviewsearchenabled", false, false);
|
||||
dispatchEvent(newEvent);
|
||||
};
|
||||
|
||||
if (activatedByKeypress) {
|
||||
// set the focus so key strokes are entered into the textbox.
|
||||
$searchbox[0].focus();
|
||||
dispatchTabViewSearchEnabledEvent();
|
||||
} else {
|
||||
// marshal the focusing, otherwise it ends up with searchbox[0].focus gets
|
||||
// called before the search button gets the focus after being pressed.
|
||||
setTimeout(function setFocusAndDispatchSearchEnabledEvent() {
|
||||
if (!this.isEnabled()) {
|
||||
$searchShade.show();
|
||||
$search.show();
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
UI.setTitlebarColors({active: "#717171", inactive: "#EDEDED"});
|
||||
#endif
|
||||
|
||||
if (activatedByKeypress) {
|
||||
// set the focus so key strokes are entered into the textbox.
|
||||
$searchbox[0].focus();
|
||||
dispatchTabViewSearchEnabledEvent();
|
||||
}, 0);
|
||||
} else {
|
||||
// marshal the focusing, otherwise it ends up with searchbox[0].focus gets
|
||||
// called before the search button gets the focus after being pressed.
|
||||
setTimeout(function setFocusAndDispatchSearchEnabledEvent() {
|
||||
$searchbox[0].focus();
|
||||
dispatchTabViewSearchEnabledEvent();
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function isSearchEnabled() {
|
||||
return iQ("#search").css("display") != "none";
|
||||
}
|
||||
|
||||
var SearchEventHandler = new SearchEventHandlerClass();
|
||||
|
||||
// Features to add:
|
||||
// (1) Make sure this looks good on Windows. Bug 594429
|
||||
// (2) Group all of the highlighted tabs into a group? Bug 594434
|
||||
|
@ -609,7 +609,7 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
let $tabEl = this.$container;
|
||||
let $canvas = this.$canvas;
|
||||
|
||||
hideSearch();
|
||||
Search.hide();
|
||||
|
||||
UI.setActive(this);
|
||||
TabItems._update(this.tab, {force: true});
|
||||
|
@ -78,5 +78,5 @@ let AllTabs = {
|
||||
#include drag.js
|
||||
#include trench.js
|
||||
#include thumbnailStorage.js
|
||||
#include ui.js
|
||||
#include search.js
|
||||
#include ui.js
|
||||
|
@ -185,6 +185,9 @@ let UI = {
|
||||
this._storageSanity(data);
|
||||
this._pageBounds = data.pageBounds;
|
||||
|
||||
// ___ search
|
||||
Search.init();
|
||||
|
||||
// ___ currentTab
|
||||
this._currentTab = gBrowser.selectedTab;
|
||||
|
||||
@ -717,7 +720,7 @@ let UI = {
|
||||
}
|
||||
} else if (topic == "private-browsing-change-granted") {
|
||||
if (data == "enter" || data == "exit") {
|
||||
hideSearch();
|
||||
Search.hide();
|
||||
self._privateBrowsing.transitionMode = data;
|
||||
|
||||
// make sure to save all thumbnails that haven't been saved yet
|
||||
@ -1134,7 +1137,7 @@ let UI = {
|
||||
}
|
||||
}
|
||||
if ((iQ(":focus").length > 0 && iQ(":focus")[0].nodeName == "INPUT") ||
|
||||
isSearchEnabled() || self.ignoreKeypressForSearch) {
|
||||
Search.isEnabled() || self.ignoreKeypressForSearch) {
|
||||
self.ignoreKeypressForSearch = false;
|
||||
processBrowserKeys(event);
|
||||
return;
|
||||
@ -1247,9 +1250,9 @@ let UI = {
|
||||
// Function: enableSearch
|
||||
// Enables the search feature.
|
||||
enableSearch: function UI_enableSearch() {
|
||||
if (!isSearchEnabled()) {
|
||||
ensureSearchShown();
|
||||
SearchEventHandler.switchToInMode();
|
||||
if (!Search.isEnabled()) {
|
||||
Search.ensureShown();
|
||||
Search.switchToInMode();
|
||||
}
|
||||
},
|
||||
|
||||
@ -1516,15 +1519,15 @@ let UI = {
|
||||
let self = this;
|
||||
let zoomedIn = false;
|
||||
|
||||
if (isSearchEnabled()) {
|
||||
let matcher = createSearchTabMacher();
|
||||
if (Search.isEnabled()) {
|
||||
let matcher = Search.createSearchTabMatcher();
|
||||
let matches = matcher.matched();
|
||||
|
||||
if (matches.length > 0) {
|
||||
matches[0].zoomIn();
|
||||
zoomedIn = true;
|
||||
}
|
||||
hideSearch();
|
||||
Search.hide();
|
||||
}
|
||||
|
||||
if (!zoomedIn) {
|
||||
|
@ -110,6 +110,7 @@ _BROWSER_FILES = \
|
||||
browser_tabview_bug625195.js \
|
||||
browser_tabview_bug625269.js \
|
||||
browser_tabview_bug625424.js \
|
||||
browser_tabview_bug625955.js \
|
||||
browser_tabview_bug626368.js \
|
||||
browser_tabview_bug626455.js \
|
||||
browser_tabview_bug626525.js \
|
||||
|
@ -24,7 +24,7 @@ function test2() {
|
||||
ok(TabView.isVisible(), "Tab View is visible");
|
||||
|
||||
whenSearchIsEnabled(function() {
|
||||
ok(contentWindow.isSearchEnabled(), "The search is enabled")
|
||||
ok(contentWindow.Search.isEnabled(), "The search is enabled")
|
||||
|
||||
whenSearchIsDisabled(test3);
|
||||
hideSearch();
|
||||
@ -33,7 +33,7 @@ function test2() {
|
||||
}
|
||||
|
||||
function test3() {
|
||||
ok(!contentWindow.isSearchEnabled(), "The search is disabled")
|
||||
ok(!contentWindow.Search.isEnabled(), "The search is disabled")
|
||||
|
||||
is(gBrowser.tabs.length, 1, "There is one tab before cmd/ctrl + t is pressed");
|
||||
|
||||
|
@ -50,7 +50,7 @@ function testThree() {
|
||||
let tab = win.gBrowser.tabs[1];
|
||||
searchBox.val(tab._tabViewTabItem.$tabTitle[0].innerHTML);
|
||||
|
||||
cw.performSearch();
|
||||
cw.Search.perform();
|
||||
|
||||
whenTabViewIsHidden(function () {
|
||||
is(tab, win.gBrowser.selectedTab, "The search result tab is shown");
|
||||
|
@ -20,7 +20,7 @@ function onTabViewWindowLoaded() {
|
||||
executeSoon(function() {
|
||||
let searchBox = contentWindow.document.getElementById("searchbox");
|
||||
is(searchBox.value, number, "The seach box matches the number: " + number);
|
||||
contentWindow.hideSearch(null);
|
||||
contentWindow.Search.hide(null);
|
||||
});
|
||||
}
|
||||
let onSearchDisabled = function() {
|
||||
|
@ -52,7 +52,7 @@ function onTabViewWindowLoaded(win, tab) {
|
||||
let testClickOnOtherSearchResult = function () {
|
||||
// search for the tab from our main window
|
||||
searchbox.setAttribute('value', 'other');
|
||||
contentWindow.performSearch();
|
||||
contentWindow.Search.perform();
|
||||
|
||||
// prepare to finish when the main window gets focus back
|
||||
window.addEventListener('focus', function onFocus() {
|
||||
|
@ -0,0 +1,25 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
showTabView(onTabViewShown);
|
||||
}
|
||||
|
||||
function onTabViewShown() {
|
||||
let contentWindow = TabView.getContentWindow();
|
||||
is(contentWindow.GroupItems.groupItems.length, 1, "Has one groupItem only");
|
||||
|
||||
let groupItem = contentWindow.GroupItems.groupItems[0];
|
||||
let tabItems = groupItem.getChildren();
|
||||
is(tabItems.length, 1, "There is only one tabItems in the groupItem");
|
||||
|
||||
let bounds = groupItem.bounds;
|
||||
gBrowser.addTab();
|
||||
gBrowser.removeTab(gBrowser.tabs[1]);
|
||||
ok(bounds.equals(groupItem.bounds), 'Group bounds recovered');
|
||||
|
||||
is(tabItems.length, 1, "There is only one tabItem in the groupItem");
|
||||
|
||||
hideTabView(finish);
|
||||
}
|
@ -12,7 +12,7 @@ function test() {
|
||||
let keyCodes = [0, 91, 92];
|
||||
keyCodes.forEach(function(keyCode) {
|
||||
utils.sendKeyEvent("keydown", keyCode, 0, 0);
|
||||
ok(!cw.isSearchEnabled(), "search is not enabled with keyCode: " + keyCode);
|
||||
ok(!cw.Search.isEnabled(), "search is not enabled with keyCode: " + keyCode);
|
||||
});
|
||||
|
||||
hideTabView(finish);
|
||||
|
@ -9,14 +9,14 @@ function test() {
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
if (cw)
|
||||
cw.hideSearch();
|
||||
cw.Search.hide();
|
||||
|
||||
TabView.hide();
|
||||
pb.privateBrowsingEnabled = false;
|
||||
});
|
||||
|
||||
let enableSearch = function (callback) {
|
||||
if (cw.isSearchEnabled()) {
|
||||
if (cw.Search.isEnabled()) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
@ -26,7 +26,7 @@ function test() {
|
||||
executeSoon(callback);
|
||||
}, false);
|
||||
|
||||
cw.ensureSearchShown();
|
||||
cw.Search.ensureShown();
|
||||
};
|
||||
|
||||
let getSearchboxValue = function () {
|
||||
@ -34,7 +34,7 @@ function test() {
|
||||
};
|
||||
|
||||
let prepareSearchbox = function (callback) {
|
||||
ok(!cw.isSearchEnabled(), "search is disabled");
|
||||
ok(!cw.Search.isEnabled(), "search is disabled");
|
||||
|
||||
enableSearch(function () {
|
||||
cw.iQ("#searchbox").val("moz");
|
||||
@ -46,7 +46,7 @@ function test() {
|
||||
prepareSearchbox(function () {
|
||||
togglePrivateBrowsing(function () {
|
||||
showTabView(function () {
|
||||
ok(!cw.isSearchEnabled(), "search is disabled");
|
||||
ok(!cw.Search.isEnabled(), "search is disabled");
|
||||
is(getSearchboxValue(), "", "search box is empty");
|
||||
callback();
|
||||
});
|
||||
|
@ -14,11 +14,11 @@ function test() {
|
||||
})
|
||||
|
||||
whenSearchIsEnabled(function() {
|
||||
ok(cw.isSearchEnabled(), "The search is enabled before creating a new tab");
|
||||
ok(cw.Search.isEnabled(), "The search is enabled before creating a new tab");
|
||||
|
||||
whenTabViewIsHidden(function() {
|
||||
showTabView(function() {
|
||||
ok(!cw.isSearchEnabled(), "The search is disabled when entering Tabview");
|
||||
ok(!cw.Search.isEnabled(), "The search is disabled when entering Tabview");
|
||||
|
||||
hideTabView(finish);
|
||||
})
|
||||
|
@ -100,7 +100,7 @@ function searchTest(contentWindow) {
|
||||
|
||||
// part of titled
|
||||
searchBox.setAttribute("value", tabNames[0].substr(1));
|
||||
contentWindow.performSearch();
|
||||
contentWindow.Search.perform();
|
||||
matchResults = getMatchResults(contentWindow, searchBox.getAttribute("value"));
|
||||
is(matchResults.length, 1,
|
||||
"Match something when a part of title exists");
|
||||
@ -109,7 +109,7 @@ function searchTest(contentWindow) {
|
||||
}
|
||||
|
||||
function cleanup(contentWindow) {
|
||||
contentWindow.hideSearch(null);
|
||||
contentWindow.Search.hide(null);
|
||||
|
||||
let onTabViewHidden = function() {
|
||||
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
|
@ -93,21 +93,21 @@ function searchTest(contentWindow) {
|
||||
|
||||
// part of title
|
||||
searchBox.setAttribute("value", "search");
|
||||
contentWindow.performSearch();
|
||||
contentWindow.Search.perform();
|
||||
is(new contentWindow.TabMatcher(
|
||||
searchBox.getAttribute("value")).matched().length, 2,
|
||||
"Match something when a part of title exists");
|
||||
|
||||
// unique part of a url
|
||||
searchBox.setAttribute("value", "search1.html");
|
||||
contentWindow.performSearch();
|
||||
contentWindow.Search.perform();
|
||||
is(new contentWindow.TabMatcher(
|
||||
searchBox.getAttribute("value")).matched().length, 1,
|
||||
"Match something when a unique part of a url exists");
|
||||
|
||||
// common part of a url
|
||||
searchBox.setAttribute("value", "tabview");
|
||||
contentWindow.performSearch();
|
||||
contentWindow.Search.perform();
|
||||
is(new contentWindow.TabMatcher(
|
||||
searchBox.getAttribute("value")).matched().length, 2,
|
||||
"Match something when a common part of a url exists");
|
||||
@ -117,7 +117,7 @@ function searchTest(contentWindow) {
|
||||
|
||||
// ----------
|
||||
function cleanup(contentWindow) {
|
||||
contentWindow.hideSearch(null);
|
||||
contentWindow.Search.hide(null);
|
||||
let onTabViewHidden = function() {
|
||||
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
ok(!TabView.isVisible(), "Tab View is hidden");
|
||||
|
@ -199,7 +199,7 @@ function hideSearch(callback, win) {
|
||||
win = win || window;
|
||||
|
||||
let contentWindow = win.TabView.getContentWindow();
|
||||
if (!contentWindow.isSearchEnabled()) {
|
||||
if (!contentWindow.Search.isEnabled()) {
|
||||
if (callback)
|
||||
callback();
|
||||
return;
|
||||
@ -208,7 +208,7 @@ function hideSearch(callback, win) {
|
||||
if (callback)
|
||||
whenSearchIsDisabled(callback, win);
|
||||
|
||||
contentWindow.hideSearch();
|
||||
contentWindow.Search.hide();
|
||||
}
|
||||
|
||||
// ----------
|
||||
@ -216,7 +216,7 @@ function whenSearchIsEnabled(callback, win) {
|
||||
win = win || window;
|
||||
|
||||
let contentWindow = win.TabView.getContentWindow();
|
||||
if (contentWindow.isSearchEnabled()) {
|
||||
if (contentWindow.Search.isEnabled()) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
@ -232,7 +232,7 @@ function whenSearchIsDisabled(callback, win) {
|
||||
win = win || window;
|
||||
|
||||
let contentWindow = win.TabView.getContentWindow();
|
||||
if (!contentWindow.isSearchEnabled()) {
|
||||
if (!contentWindow.Search.isEnabled()) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
@ -303,6 +303,7 @@ Highlighter.prototype = {
|
||||
{
|
||||
this.browser.removeEventListener("scroll", this, true);
|
||||
this.browser.removeEventListener("resize", this, true);
|
||||
this._contentRect = null;
|
||||
this._highlightRect = null;
|
||||
this._highlighting = false;
|
||||
this.veilTopBox = null;
|
||||
@ -439,28 +440,41 @@ Highlighter.prototype = {
|
||||
*/
|
||||
highlightRectangle: function Highlighter_highlightRectangle(aRect)
|
||||
{
|
||||
let oldRect = this._highlightRect;
|
||||
let oldRect = this._contentRect;
|
||||
|
||||
if (oldRect && aRect.top == oldRect.top && aRect.left == oldRect.left &&
|
||||
aRect.width == oldRect.width && aRect.height == oldRect.height) {
|
||||
return this._highlighting; // same rectangle
|
||||
}
|
||||
|
||||
if (aRect.left >= 0 && aRect.top >= 0 &&
|
||||
aRect.width > 0 && aRect.height > 0) {
|
||||
// get page zoom factor, if any
|
||||
let zoom =
|
||||
this.win.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils)
|
||||
.screenPixelsPerCSSPixel;
|
||||
|
||||
// adjust rect for zoom scaling
|
||||
let aRectScaled = {};
|
||||
for (let prop in aRect) {
|
||||
aRectScaled[prop] = aRect[prop] * zoom;
|
||||
}
|
||||
|
||||
if (aRectScaled.left >= 0 && aRectScaled.top >= 0 &&
|
||||
aRectScaled.width > 0 && aRectScaled.height > 0) {
|
||||
// The bottom div and the right div are flexibles (flex=1).
|
||||
// We don't need to resize them.
|
||||
this.veilTopBox.style.height = aRect.top + "px";
|
||||
this.veilLeftBox.style.width = aRect.left + "px";
|
||||
this.veilMiddleBox.style.height = aRect.height + "px";
|
||||
this.veilTransparentBox.style.width = aRect.width + "px";
|
||||
this.veilTopBox.style.height = aRectScaled.top + "px";
|
||||
this.veilLeftBox.style.width = aRectScaled.left + "px";
|
||||
this.veilMiddleBox.style.height = aRectScaled.height + "px";
|
||||
this.veilTransparentBox.style.width = aRectScaled.width + "px";
|
||||
|
||||
this._highlighting = true;
|
||||
} else {
|
||||
this.unhighlight();
|
||||
}
|
||||
|
||||
this._highlightRect = aRect;
|
||||
this._contentRect = aRect; // save orig (non-scaled) rect
|
||||
this._highlightRect = aRectScaled; // and save the scaled rect.
|
||||
|
||||
return this._highlighting;
|
||||
},
|
||||
@ -588,18 +602,18 @@ Highlighter.prototype = {
|
||||
get highlitNode()
|
||||
{
|
||||
// Not highlighting? Bail.
|
||||
if (!this._highlighting || !this._highlightRect) {
|
||||
if (!this._highlighting || !this._contentRect) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let a = {
|
||||
x: this._highlightRect.left,
|
||||
y: this._highlightRect.top
|
||||
x: this._contentRect.left,
|
||||
y: this._contentRect.top
|
||||
};
|
||||
|
||||
let b = {
|
||||
x: a.x + this._highlightRect.width,
|
||||
y: a.y + this._highlightRect.height
|
||||
x: a.x + this._contentRect.width,
|
||||
y: a.y + this._contentRect.height
|
||||
};
|
||||
|
||||
// Get midpoint of diagonal line.
|
||||
|
@ -40,6 +40,7 @@
|
||||
|
||||
let doc;
|
||||
let h1;
|
||||
let div;
|
||||
|
||||
function createDocument()
|
||||
{
|
||||
@ -49,7 +50,7 @@ function createDocument()
|
||||
let p2 = doc.createElement("p");
|
||||
let div2 = doc.createElement("div");
|
||||
let p3 = doc.createElement("p");
|
||||
doc.title = "Inspector Tree Selection Test";
|
||||
doc.title = "Inspector Highlighter Meatballs";
|
||||
h1.textContent = "Inspector Tree Selection Test";
|
||||
p1.textContent = "This is some example text";
|
||||
p2.textContent = "Lorem ipsum dolor sit amet, consectetur adipisicing " +
|
||||
@ -66,19 +67,28 @@ function createDocument()
|
||||
"dolor in reprehenderit in voluptate velit esse cillum dolore eu " +
|
||||
"fugiat nulla pariatur. Excepteur sint occaecat cupidatat non " +
|
||||
"proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
|
||||
let div3 = doc.createElement("div");
|
||||
div3.id = "checkOutThisWickedSpread";
|
||||
div3.setAttribute("style", "position: absolute; top: 20px; right: 20px; height: 20px; width: 20px; background-color: yellow; border: 1px dashed black;");
|
||||
let p4 = doc.createElement("p");
|
||||
p4.setAttribute("style", "font-weight: 200; font-size: 8px; text-align: center;");
|
||||
p4.textContent = "Smörgåsbord!";
|
||||
div.appendChild(h1);
|
||||
div.appendChild(p1);
|
||||
div.appendChild(p2);
|
||||
div2.appendChild(p3);
|
||||
div3.appendChild(p4);
|
||||
doc.body.appendChild(div);
|
||||
doc.body.appendChild(div2);
|
||||
doc.body.appendChild(div3);
|
||||
|
||||
setupHighlighterTests();
|
||||
}
|
||||
|
||||
function setupHighlighterTests()
|
||||
{
|
||||
h1 = doc.querySelectorAll("h1")[0];
|
||||
ok(h1, "we have the header node");
|
||||
h1 = doc.querySelector("h1");
|
||||
ok(h1, "we have the header");
|
||||
Services.obs.addObserver(runSelectionTests,
|
||||
InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
|
||||
InspectorUI.toggleInspectorUI();
|
||||
@ -99,7 +109,7 @@ function runSelectionTests()
|
||||
function performTestComparisons(evt)
|
||||
{
|
||||
Services.obs.removeObserver(performTestComparisons,
|
||||
InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
|
||||
InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING);
|
||||
|
||||
InspectorUI.stopInspecting();
|
||||
ok(InspectorUI.highlighter.isHighlighting, "highlighter is highlighting");
|
||||
@ -107,7 +117,61 @@ function performTestComparisons(evt)
|
||||
is(InspectorUI.selection, h1, "selection matches node");
|
||||
is(InspectorUI.selection, InspectorUI.highlighter.highlitNode, "selection matches highlighter");
|
||||
|
||||
doc = h1 = null;
|
||||
Services.obs.addObserver(finishTestComparisons,
|
||||
InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
|
||||
|
||||
div = doc.querySelector("div#checkOutThisWickedSpread");
|
||||
|
||||
executeSoon(function() {
|
||||
InspectorUI.inspectNode(div);
|
||||
});
|
||||
}
|
||||
|
||||
function finishTestComparisons()
|
||||
{
|
||||
Services.obs.removeObserver(finishTestComparisons,
|
||||
InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING);
|
||||
|
||||
// get dimensions of div element
|
||||
let divDims = div.getBoundingClientRect();
|
||||
let divWidth = divDims.width;
|
||||
let divHeight = divDims.height;
|
||||
|
||||
// get dimensions of transparent veil box over element
|
||||
let veilBoxDims =
|
||||
InspectorUI.highlighter.veilTransparentBox.getBoundingClientRect();
|
||||
let veilBoxWidth = veilBoxDims.width;
|
||||
let veilBoxHeight = veilBoxDims.height;
|
||||
|
||||
is(veilBoxWidth, divWidth, "transparent veil box width matches dimensions of element (no zoom)");
|
||||
is(veilBoxHeight, divHeight, "transparent veil box height matches dimensions of element (no zoom)");
|
||||
// zoom the page by a factor of 2
|
||||
let contentViewer = InspectorUI.browser.docShell.contentViewer
|
||||
.QueryInterface(Ci.nsIMarkupDocumentViewer);
|
||||
contentViewer.fullZoom = 2;
|
||||
|
||||
// check what zoom factor we're at, should be 2
|
||||
let zoom =
|
||||
InspectorUI.win.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils)
|
||||
.screenPixelsPerCSSPixel;
|
||||
|
||||
is(zoom, 2, "zoom is 2?");
|
||||
|
||||
// simulate the zoomed dimensions of the div element
|
||||
let divDims = div.getBoundingClientRect();
|
||||
let divWidth = divDims.width * zoom;
|
||||
let divHeight = divDims.height * zoom;
|
||||
|
||||
// now zoomed, get new dimensions of transparent veil box over element
|
||||
let veilBoxDims = InspectorUI.highlighter.veilTransparentBox.getBoundingClientRect();
|
||||
let veilBoxWidth = veilBoxDims.width;
|
||||
let veilBoxHeight = veilBoxDims.height;
|
||||
|
||||
is(veilBoxWidth, divWidth, "transparent veil box width matches width of element (2x zoom)");
|
||||
is(veilBoxHeight, divHeight, "transparent veil box height matches width of element (2x zoom)");
|
||||
|
||||
doc = h1 = div = null;
|
||||
executeSoon(finishUp);
|
||||
}
|
||||
|
||||
|
@ -565,6 +565,10 @@ CssLogic.prototype = {
|
||||
this._unmatchedSelectors = [];
|
||||
|
||||
this.forEachSheet(function (aSheet) {
|
||||
if (aSheet.systemSheet) {
|
||||
return;
|
||||
}
|
||||
|
||||
aSheet.forEachRule(function (aRule) {
|
||||
aRule.selectors.forEach(function (aSelector) {
|
||||
if (aSelector._matchId != this._matchId) {
|
||||
@ -1441,10 +1445,6 @@ CssPropertyInfo.prototype = {
|
||||
_processUnmatchedSelector: function CPI_processUnmatchedSelector(aSelector)
|
||||
{
|
||||
let cssRule = aSelector._cssRule;
|
||||
if (cssRule.systemRule) {
|
||||
return;
|
||||
}
|
||||
|
||||
let value = cssRule.getPropertyValue(this.property);
|
||||
if (value) {
|
||||
let selectorInfo = new CssSelectorInfo(aSelector, this.property, value,
|
||||
@ -1469,30 +1469,24 @@ CssPropertyInfo.prototype = {
|
||||
let passId = ++this._cssLogic._passId;
|
||||
let ruleCount = 0;
|
||||
|
||||
if (this._matchedSelectors) {
|
||||
this._matchedSelectors.forEach(function(aSelectorInfo) {
|
||||
let cssRule = aSelectorInfo.selector._cssRule;
|
||||
if (cssRule._passId != passId) {
|
||||
if (cssRule.sheetAllowed) {
|
||||
ruleCount++;
|
||||
}
|
||||
cssRule._passId = passId;
|
||||
let iterator = function(aSelectorInfo) {
|
||||
let cssRule = aSelectorInfo.selector._cssRule;
|
||||
if (cssRule._passId != passId) {
|
||||
if (cssRule.sheetAllowed) {
|
||||
ruleCount++;
|
||||
}
|
||||
});
|
||||
cssRule._passId = passId;
|
||||
}
|
||||
};
|
||||
|
||||
if (this._matchedSelectors) {
|
||||
this._matchedSelectors.forEach(iterator);
|
||||
this._matchedRuleCount = ruleCount;
|
||||
}
|
||||
|
||||
if (this._unmatchedSelectors) {
|
||||
ruleCount = 0;
|
||||
this._unmatchedSelectors.forEach(function(aSelectorInfo) {
|
||||
let cssRule = aSelectorInfo.selector._cssRule;
|
||||
if (!cssRule.systemRule && cssRule._passId != passId) {
|
||||
if (cssRule.sheetAllowed) {
|
||||
ruleCount++;
|
||||
}
|
||||
cssRule._passId = passId;
|
||||
}
|
||||
});
|
||||
this._unmatchedSelectors.forEach(iterator);
|
||||
this._unmatchedRuleCount = ruleCount;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user