Merge mozilla-central to mozilla-inbound

This commit is contained in:
Ed Morley 2012-10-31 14:11:12 +00:00
commit d14cc688a2
13 changed files with 124 additions and 576 deletions

View File

@ -203,21 +203,9 @@ var PlacesOrganizer = {
// and update the back/forward buttons by setting location.
if (this._content.place != placeURI || !resetSearchBox) {
this._content.place = placeURI;
PlacesSearchBox.hideSearchUI();
this.location = node.uri;
}
// Update the selected folder title where it appears in the UI: the folder
// scope button, and the search box emptytext.
// They must be updated even if the selection hasn't changed --
// specifically when node's title changes. In that case a selection event
// is generated, this method is called, but the selection does not change.
var folderButton = document.getElementById("scopeBarFolder");
var folderTitle = node.title || folderButton.getAttribute("emptytitle");
folderButton.setAttribute("label", folderTitle);
if (PlacesSearchBox.filterCollection == "collection")
PlacesSearchBox.updateCollectionTitle(folderTitle);
// When we invalidate a container we use suppressSelectionEvent, when it is
// unset a select event is fired, in many cases the selection did not really
// change, so we should check for it, and return early in such a case. Note
@ -245,30 +233,17 @@ var PlacesOrganizer = {
_setSearchScopeForNode: function PO__setScopeForNode(aNode) {
let itemId = aNode.itemId;
// Set default buttons status.
let bookmarksButton = document.getElementById("scopeBarAll");
bookmarksButton.hidden = false;
let downloadsButton = document.getElementById("scopeBarDownloads");
downloadsButton.hidden = true;
if (PlacesUtils.nodeIsHistoryContainer(aNode) ||
itemId == PlacesUIUtils.leftPaneQueries["History"]) {
PlacesQueryBuilder.setScope("history");
}
else if (itemId == PlacesUIUtils.leftPaneQueries["Downloads"]) {
downloadsButton.hidden = false;
bookmarksButton.hidden = true;
PlacesQueryBuilder.setScope("downloads");
}
else {
// Default to All Bookmarks for all other nodes, per bug 469437.
PlacesQueryBuilder.setScope("bookmarks");
}
// Enable or disable the folder scope button.
let folderButton = document.getElementById("scopeBarFolder");
folderButton.hidden = !PlacesUtils.nodeIsFolder(aNode) ||
itemId == PlacesUIUtils.allBookmarksFolderId;
},
/**
@ -755,50 +730,6 @@ var PlacesOrganizer = {
additionalInfoBroadcaster.setAttribute("hidden", "true");
}
},
/**
* Save the current search (or advanced query) to the bookmarks root.
*/
saveSearch: function PO_saveSearch() {
// Get the place: uri for the query.
// If the advanced query builder is showing, use that.
var options = this.getCurrentOptions();
var queries = this.getCurrentQueries();
var placeSpec = PlacesUtils.history.queriesToQueryString(queries,
queries.length,
options);
var placeURI = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService).
newURI(placeSpec, null, null);
// Prompt the user for a name for the query.
// XXX - using prompt service for now; will need to make
// a real dialog and localize when we're sure this is the UI we want.
var title = PlacesUIUtils.getString("saveSearch.title");
var inputLabel = PlacesUIUtils.getString("saveSearch.inputLabel");
var defaultText = PlacesUIUtils.getString("saveSearch.inputDefaultText");
var prompts = Cc["@mozilla.org/embedcomp/prompt-service;1"].
getService(Ci.nsIPromptService);
var check = {value: false};
var input = {value: defaultText};
var save = prompts.prompt(null, title, inputLabel, input, null, check);
// Don't add the query if the user cancels or clears the seach name.
if (!save || input.value == "")
return;
// Add the place: uri as a bookmark under the bookmarks root.
var txn = new PlacesCreateBookmarkTransaction(placeURI,
PlacesUtils.bookmarksMenuFolderId,
PlacesUtils.bookmarks.DEFAULT_INDEX,
input.value);
PlacesUtils.transactionManager.doTransaction(txn);
// select and load the new query
this._places.selectPlaceURI(placeSpec);
}
};
/**
@ -812,16 +743,17 @@ var PlacesSearchBox = {
get searchFilter() {
return document.getElementById("searchFilter");
},
/**
* Folders to include when searching.
*/
_folders: [],
get folders() {
if (this._folders.length == 0)
if (this._folders.length == 0) {
this._folders.push(PlacesUtils.bookmarksMenuFolderId,
PlacesUtils.unfiledBookmarksFolderId,
PlacesUtils.toolbarFolderId);
}
return this._folders;
},
set folders(aFolders) {
@ -850,50 +782,42 @@ var PlacesSearchBox = {
var currentOptions = PO.getCurrentOptions();
var content = PO._content;
// Search according to the current scope and folders, which were set by
// Search according to the current scope, which was set by
// PQB_setScope()
switch (PlacesSearchBox.filterCollection) {
case "collection":
content.applyFilter(filterString, this.folders);
// XXX changing the button text is badness
//var scopeBtn = document.getElementById("scopeBarFolder");
//scopeBtn.label = PlacesOrganizer._places.selectedNode.title;
break;
case "bookmarks":
content.applyFilter(filterString, this.folders);
break;
case "history":
if (currentOptions.queryType != Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY) {
var query = PlacesUtils.history.getNewQuery();
query.searchTerms = filterString;
var options = currentOptions.clone();
// Make sure we're getting uri results.
options.resultType = currentOptions.RESULT_TYPE_URI;
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY;
content.load([query], options);
}
else {
content.applyFilter(filterString);
}
break;
case "downloads": {
let query = PlacesUtils.history.getNewQuery();
query.searchTerms = filterString;
query.setTransitions([Ci.nsINavHistoryService.TRANSITION_DOWNLOAD], 1);
let options = currentOptions.clone();
// Make sure we're getting uri results.
options.resultType = currentOptions.RESULT_TYPE_URI;
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY;
content.load([query], options);
break;
case "bookmarks":
content.applyFilter(filterString, this.folders);
break;
case "history":
if (currentOptions.queryType != Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY) {
var query = PlacesUtils.history.getNewQuery();
query.searchTerms = filterString;
var options = currentOptions.clone();
// Make sure we're getting uri results.
options.resultType = currentOptions.RESULT_TYPE_URI;
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY;
content.load([query], options);
}
else {
content.applyFilter(filterString);
}
break;
case "downloads": {
let query = PlacesUtils.history.getNewQuery();
query.searchTerms = filterString;
query.setTransitions([Ci.nsINavHistoryService.TRANSITION_DOWNLOAD], 1);
let options = currentOptions.clone();
// Make sure we're getting uri results.
options.resultType = currentOptions.RESULT_TYPE_URI;
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY;
content.load([query], options);
break;
}
default:
throw "Invalid filterCollection on search";
break;
}
PlacesSearchBox.showSearchUI();
// Update the details panel
PlacesOrganizer.onContentTreeSelect();
},
@ -923,24 +847,15 @@ var PlacesSearchBox = {
*/
updateCollectionTitle: function PSB_updateCollectionTitle(aTitle) {
let title = "";
// This is needed when a user performs a folder-specific search
// using the scope bar, removes the search-string, and unfocuses
// the search box, at least until the removal of the scope bar.
if (aTitle) {
title = PlacesUIUtils.getFormattedString("searchCurrentDefault",
[aTitle]);
}
else {
switch (this.filterCollection) {
case "history":
title = PlacesUIUtils.getString("searchHistory");
break;
case "downloads":
title = PlacesUIUtils.getString("searchDownloads");
break;
default:
title = PlacesUIUtils.getString("searchBookmarks");
}
switch (this.filterCollection) {
case "history":
title = PlacesUIUtils.getString("searchHistory");
break;
case "downloads":
title = PlacesUIUtils.getString("searchDownloads");
break;
default:
title = PlacesUIUtils.getString("searchBookmarks");
}
this.searchFilter.placeholder = title;
},
@ -956,14 +871,8 @@ var PlacesSearchBox = {
return collectionName;
this.searchFilter.setAttribute("collection", collectionName);
this.updateCollectionTitle();
var newGrayText = null;
if (collectionName == "collection") {
newGrayText = PlacesOrganizer._places.selectedNode.title ||
document.getElementById("scopeBarFolder").
getAttribute("emptytitle");
}
this.updateCollectionTitle(newGrayText);
return collectionName;
},
@ -990,17 +899,6 @@ var PlacesSearchBox = {
set value(value) {
return this.searchFilter.value = value;
},
showSearchUI: function PSB_showSearchUI() {
// Hide the advanced search controls when the user hasn't searched
var searchModifiers = document.getElementById("searchModifiers");
searchModifiers.hidden = false;
},
hideSearchUI: function PSB_hideSearchUI() {
var searchModifiers = document.getElementById("searchModifiers");
searchModifiers.hidden = true;
}
};
/**
@ -1011,31 +909,6 @@ var PlacesQueryBuilder = {
queries: [],
queryOptions: null,
/**
* Called when a scope button in the scope bar is clicked.
* @param aButton
* the scope button that was selected
*/
onScopeSelected: function PQB_onScopeSelected(aButton) {
switch (aButton.id) {
case "scopeBarHistory":
this.setScope("history");
break;
case "scopeBarFolder":
this.setScope("collection");
break;
case "scopeBarDownloads":
this.setScope("downloads");
break;
case "scopeBarAll":
this.setScope("bookmarks");
break;
default:
throw "Invalid search scope button ID";
break;
}
},
/**
* Sets the search scope. This can be called when no search is active, and
* in that case, when the user does begin a search aScope will be used (see
@ -1049,44 +922,24 @@ var PlacesQueryBuilder = {
// Determine filterCollection, folders, and scopeButtonId based on aScope.
var filterCollection;
var folders = [];
var scopeButtonId;
switch (aScope) {
case "history":
filterCollection = "history";
scopeButtonId = "scopeBarHistory";
break;
case "collection":
// The folder scope button can only become hidden upon selecting a new
// folder in the left pane, and the disabled state will remain unchanged
// until a new folder is selected. See PO__setScopeForNode().
if (!document.getElementById("scopeBarFolder").hidden) {
filterCollection = "collection";
scopeButtonId = "scopeBarFolder";
folders.push(PlacesUtils.getConcreteItemId(
PlacesOrganizer._places.selectedNode));
case "history":
filterCollection = "history";
break;
case "bookmarks":
filterCollection = "bookmarks";
folders.push(PlacesUtils.bookmarksMenuFolderId,
PlacesUtils.toolbarFolderId,
PlacesUtils.unfiledBookmarksFolderId);
break;
case "downloads":
filterCollection = "downloads";
break;
default:
throw "Invalid search scope";
break;
}
// Fall through. If collection scope doesn't make sense for the
// selected node, choose bookmarks scope.
case "bookmarks":
filterCollection = "bookmarks";
scopeButtonId = "scopeBarAll";
folders.push(PlacesUtils.bookmarksMenuFolderId,
PlacesUtils.toolbarFolderId,
PlacesUtils.unfiledBookmarksFolderId);
break;
case "downloads":
filterCollection = "downloads";
scopeButtonId = "scopeBarDownloads";
break;
default:
throw "Invalid search scope";
break;
}
// Check the appropriate scope button in the scope bar.
document.getElementById(scopeButtonId).checked = true;
// Update the search box. Re-search if there's an active search.
PlacesSearchBox.filterCollection = filterCollection;
PlacesSearchBox.folders = folders;

View File

@ -31,8 +31,8 @@
]>
<window id="places"
title="&places.library.title;"
windowtype="Places:Organizer"
title="&places.library.title;"
windowtype="Places:Organizer"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
onload="PlacesOrganizer.init();"
@ -87,12 +87,12 @@
<keyset id="placesOrganizerKeyset">
<!-- Instantiation Keys -->
<key id="placesKey_close" key="&cmd.close.key;" modifiers="accel"
<key id="placesKey_close" key="&cmd.close.key;" modifiers="accel"
oncommand="close();"/>
<!-- Command Keys -->
<key id="placesKey_find:all"
command="OrganizerCommand_find:all"
command="OrganizerCommand_find:all"
key="&cmd.find.key;"
modifiers="accel"/>
@ -241,9 +241,9 @@
<menuseparator id="orgCloseSeparator"/>
<menuitem id="orgClose"
key="placesKey_close"
key="placesKey_close"
label="&file.close.label;"
accesskey="&file.close.accesskey;"
accesskey="&file.close.accesskey;"
oncommand="close();"/>
#endif
</menupopup>
@ -258,7 +258,7 @@
tooltiptext="&views.tooltip;">
<menupopup id="viewMenuPopup">
<menu id="viewColumns"
<menu id="viewColumns"
label="&view.columns.label;" accesskey="&view.columns.accesskey;">
<menupopup onpopupshowing="ViewMenu.fillWithColumns(event, null, null, 'checkbox', null);"
oncommand="ViewMenu.showHideColumn(event.target); event.stopPropagation();"/>
@ -268,14 +268,14 @@
accesskey="&view.sort.accesskey;">
<menupopup onpopupshowing="ViewMenu.populateSortMenu(event);"
oncommand="ViewMenu.setSortColumn(event.target.column, null);">
<menuitem id="viewUnsorted" type="radio" name="columns"
<menuitem id="viewUnsorted" type="radio" name="columns"
label="&view.unsorted.label;" accesskey="&view.unsorted.accesskey;"
oncommand="ViewMenu.setSortColumn(null, null);"/>
<menuseparator id="directionSeparator"/>
<menuitem id="viewSortAscending" type="radio" name="direction"
<menuitem id="viewSortAscending" type="radio" name="direction"
label="&view.sortAscending.label;" accesskey="&view.sortAscending.accesskey;"
oncommand="ViewMenu.setSortColumn(null, 'ascending'); event.stopPropagation();"/>
<menuitem id="viewSortDescending" type="radio" name="direction"
<menuitem id="viewSortDescending" type="radio" name="direction"
label="&view.sortDescending.label;" accesskey="&view.sortDescending.accesskey;"
oncommand="ViewMenu.setSortColumn(null, 'descending'); event.stopPropagation();"/>
</menupopup>
@ -358,38 +358,6 @@
</tree>
<splitter collapse="none" persist="state"></splitter>
<vbox id="contentView" flex="4">
<toolbox id="searchModifiers" hidden="true">
<toolbar id="organizerScopeBar" class="chromeclass-toolbar" align="center">
<label id="scopeBarTitle" value="&search.in.label;"/>
<toolbarbutton id="scopeBarAll" class="small-margin"
type="radio" group="scopeBar"
oncommand="PlacesQueryBuilder.onScopeSelected(this);"
label="&search.scopeBookmarks.label;"
accesskey="&search.scopeBookmarks.accesskey;"/>
<toolbarbutton id="scopeBarHistory" class="small-margin"
type="radio" group="scopeBar"
oncommand="PlacesQueryBuilder.onScopeSelected(this);"
label="&search.scopeHistory.label;"
accesskey="&search.scopeHistory.accesskey;"/>
<toolbarbutton id="scopeBarDownloads" class="small-margin"
type="radio" group="scopeBar"
oncommand="PlacesQueryBuilder.onScopeSelected(this);"
label="&search.scopeDownloads.label;"
accesskey="&search.scopeDownloads.accesskey;"/>
<toolbarbutton id="scopeBarFolder" class="small-margin"
type="radio" group="scopeBar"
oncommand="PlacesQueryBuilder.onScopeSelected(this);"
accesskey="&search.scopeFolder.accesskey;"
emptytitle="&search.scopeFolder.label;" flex="1"/>
<!-- The folder scope button should flex but not take up more room
than its label needs. The only simple way to do that is to
set a really big flex on the spacer, e.g., 2^31 - 1. -->
<spacer flex="2147483647"/>
<button id="saveSearch" class="small-margin"
label="&saveSearch.label;" accesskey="&saveSearch.accesskey;"
command="OrganizerCommand_search:save"/>
</toolbar>
</toolbox>
<tree id="placeContent"
class="plain placesTree"
context="placesContext"

View File

@ -19,9 +19,6 @@
* 2. performs a search and ensures that the content tree is correct for the
* folder and search and that the search UI is visible and appropriate to
* folder,
* 3. ensures that the folder scope button is disabled appropriate to the
* folder,
* 4. if the folder scope button is enabled clicks it,
* 5. resets the search and ensures that the content tree is correct and that
* the search UI is hidden, and
* 6. if folder scope was clicked, searches again and ensures folder scope
@ -37,61 +34,16 @@ let testCases = [
function allBookmarksScope() {
let defScope = getDefaultScope(PlacesUIUtils.allBookmarksFolderId);
search(PlacesUIUtils.allBookmarksFolderId, "dummy", defScope);
ok(!selectScope("scopeBarFolder"),
"Folder scope should be disabled for All Bookmarks");
ok(selectScope("scopeBarAll"),
"Bookmarks scope should be enabled for All Bookmarks");
resetSearch("scopeBarAll");
},
function historyScope() {
let defScope = getDefaultScope(PlacesUIUtils.leftPaneQueries["History"]);
search(PlacesUIUtils.leftPaneQueries["History"], "dummy", defScope);
ok(!selectScope("scopeBarFolder"),
"Folder scope should be disabled for History");
ok(selectScope("scopeBarAll"),
"Bookmarks scope should be enabled for History");
resetSearch("scopeBarAll");
},
function downloadsScope() {
let defScope = getDefaultScope(PlacesUIUtils.leftPaneQueries["Downloads"]);
search(PlacesUIUtils.leftPaneQueries["Downloads"], "dummy", defScope);
ok(!selectScope("scopeBarFolder"),
"Folder scope should be disabled for Downloads");
ok(!selectScope("scopeBarAll"),
"Bookmarks scope should be disabled for Downloads");
resetSearch(defScope);
},
function toolbarFolderScope() {
let defScope = getDefaultScope(PlacesUtils.toolbarFolderId);
search(PlacesUtils.toolbarFolderId, "dummy", defScope);
ok(selectScope("scopeBarAll"),
"Bookmarks scope should be enabled for toolbar folder");
ok(selectScope("scopeBarFolder"),
"Folder scope should be enabled for toolbar folder");
// Ensure that folder scope is still selected after resetting and searching
// again.
resetSearch("scopeBarFolder");
search(PlacesUtils.toolbarFolderId, "dummy", "scopeBarFolder");
},
function subFolderScope() {
let folderId = PlacesUtils.bookmarks.createFolder(PlacesUtils.toolbarFolderId,
"dummy folder",
PlacesUtils.bookmarks.DEFAULT_INDEX);
let defScope = getDefaultScope(folderId);
search(folderId, "dummy", defScope);
ok(selectScope("scopeBarAll"),
"Bookmarks scope should be enabled for regularfolder");
ok(selectScope("scopeBarFolder"),
"Folder scope should be enabled for regular subfolder");
// Ensure that folder scope is still selected after resetting and searching
// again.
resetSearch("scopeBarFolder");
search(folderId, "dummy", "scopeBarFolder");
PlacesUtils.bookmarks.removeItem(folderId);
},
];
@ -115,21 +67,6 @@ function getDefaultScope(aFolderId) {
}
}
/**
* Returns the ID of the search scope button that is currently checked.
*
* @return the ID of the selected scope folder button
*/
function getSelectedScopeButtonId() {
let doc = gLibrary.document;
let scopeButtons = doc.getElementById("organizerScopeBar").childNodes;
for (let i = 0; i < scopeButtons.length; i++) {
if (scopeButtons[i].checked)
return scopeButtons[i].id;
}
return null;
}
/**
* Returns the single nsINavHistoryQuery represented by a given place URI.
*
@ -200,63 +137,11 @@ function search(aFolderId, aSearchStr, aExpectedScopeButtonId) {
if (aSearchStr) {
is(query.searchTerms, aSearchStr,
"Content tree's searchTerms should be text in search box");
is(doc.getElementById("searchModifiers").hidden, false,
"Scope bar should not be hidden after searching");
let scopeButtonId = getSelectedScopeButtonId();
if (scopeButtonId == "scopeBarDownloads" ||
scopeButtonId == "scopeBarHistory" ||
scopeButtonId == "scopeBarAll" ||
aFolderId == PlacesUtils.unfiledBookmarksFolderId) {
// Check that the target node exists in the tree's search results.
let url, count;
if (scopeButtonId == "scopeBarDownloads") {
url = TEST_DOWNLOAD_URL;
count = 1;
}
else {
url = TEST_URL;
count = scopeButtonId == "scopeBarHistory" ? 2 : 1;
}
is(contentTree.view.rowCount, count, "Found correct number of results");
let node = null;
for (let i = 0; i < contentTree.view.rowCount; i++) {
node = contentTree.view.nodeForTreeIndex(i);
if (node.uri === url)
break;
}
isnot(node, null, "At least the target node should be in the tree");
is(node.uri, url, "URI of node should match target URL");
}
}
else {
is(query.hasSearchTerms, false,
"Content tree's searchTerms should not exist after search reset");
ok(doc.getElementById("searchModifiers").hidden,
"Scope bar should be hidden after search reset");
}
is(getSelectedScopeButtonId(), aExpectedScopeButtonId,
"Proper scope button should be selected after searching or resetting");
}
/**
* Clicks the given search scope button if it is enabled.
*
* @param aScopeButtonId
* the button with this ID will be clicked
* @return true if the button is enabled, false otherwise
*/
function selectScope(aScopeButtonId) {
let doc = gLibrary.document;
let button = doc.getElementById(aScopeButtonId);
isnot(button, null,
"Sanity check: scope button with ID " + aScopeButtonId + " should exist");
// Bug 469436 may hide an inappropriate scope button instead of disabling it.
if (button.disabled || button.hidden)
return false;
button.click();
return true;
}
/**

View File

@ -91,18 +91,6 @@
<!ENTITY search.label "Search:">
<!ENTITY search.accesskey "S">
<!ENTITY search.in.label "Search in:">
<!ENTITY search.scopeFolder.label "Selected Folder">
<!ENTITY search.scopeFolder.accesskey "r">
<!ENTITY search.scopeBookmarks.label "Bookmarks">
<!ENTITY search.scopeBookmarks.accesskey "k">
<!ENTITY search.scopeDownloads.label "Downloads">
<!ENTITY search.scopeDownloads.accesskey "D">
<!ENTITY search.scopeHistory.label "History">
<!ENTITY search.scopeHistory.accesskey "H">
<!ENTITY saveSearch.label "Save">
<!ENTITY saveSearch.accesskey "S">
<!ENTITY cmd.find.key "f">
<!ENTITY maintenance.label "Import and Backup">

View File

@ -47,7 +47,6 @@ view.sortBy.tags.accesskey=T
searchBookmarks=Search Bookmarks
searchHistory=Search History
searchDownloads=Search Downloads
searchCurrentDefault=Search in '%S'
tabs.openWarningTitle=Confirm open
tabs.openWarningMultipleBranded=You are about to open %S tabs. This might slow down %S while the pages are loading. Are you sure you want to continue?
@ -57,10 +56,6 @@ tabs.openWarningPromptMeBranded=Warn me when opening multiple tabs might slow do
SelectImport=Import Bookmarks File
EnterExport=Export Bookmarks File
saveSearch.title=Save Search
saveSearch.inputLabel=Name:
saveSearch.inputDefaultText=New Search
detailsPane.noItems=No items
# LOCALIZATION NOTE (detailsPane.itemsCountLabel): Semi-colon list of plural forms.
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals

View File

@ -77,14 +77,6 @@
-moz-padding-start: 2px;
}
#searchModifiers {
padding-right: 3px;
}
#saveSearch {
list-style-image: url("moz-icon://stock/gtk-save?size=menu");
}
/**** menuitem stock icons ****/
#orgClose {
list-style-image: url("moz-icon://stock/gtk-close?size=menu");

View File

@ -231,118 +231,6 @@
border-color: transparent;
}
/* Scope Bar */
#advancedSearch > hbox,
#advancedSearchRows > row {
background-color: #E8E8E8;
border-top: 1px solid #F8F8F8;
border-bottom: 1px solid #BABABA;
}
#advancedSearchRows > row,
#searchActions {
-moz-padding-start: 2px;
-moz-padding-end: 8px;
}
#organizerScopeBar {
padding: 3px;
-moz-appearance: none;
background: @scopeBarBackground@;
border-bottom: @scopeBarSeparatorBorder@;
}
#scopeBarTitle {
font: icon;
color: @scopeBarTitleColor@;
font-weight: bold;
text-shadow: @loweredShadow@;
margin: 0 6px 1px;
}
#organizerScopeBar > toolbarbutton {
border: 0;
font: icon;
font-weight: bold;
color: #2D2D2D;
border-radius: 10000px;
padding: 0 10px 1px;
margin: 1px;
font-weight: bold;
}
#organizerScopeBar > toolbarbutton > .toolbarbutton-text {
margin: 0 !important;
}
#organizerScopeBar > toolbarbutton:hover,
#organizerScopeBar > toolbarbutton[checked="true"] {
color: #FFF !important; /* !imp because of [checked="true"] (see toolbarbutton.css) */
text-shadow: 0 1px rgba(0, 0, 0, .4);
background-color: rgba(0, 0, 0, .32);
}
#organizerScopeBar > toolbarbutton:active:hover,
#organizerScopeBar > toolbarbutton[checked="true"] {
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.4), 0 1px rgba(255, 255,
255, 0.4);
}
#organizerScopeBar > toolbarbutton:active:hover {
background-color: rgba(0, 0, 0, .5);
}
#organizerScopeBarExpander {
margin: 0;
padding: 0;
-moz-padding-end: 2px;
}
#organizerScopeBar > .expander-up {
list-style-image: url("chrome://browser/skin/places/plus.png") !important;
}
#organizerScopeBar > .expander-up:hover:active {
list-style-image: url("chrome://browser/skin/places/plus-active.png") !important;
}
#organizerScopeBar > .expander-down {
list-style-image: url("chrome://browser/skin/places/minus.png") !important;
}
#organizerScopeBar > .expander-down:hover:active {
list-style-image: url("chrome://browser/skin/places/minus-active.png") !important;
}
#saveSearch {
margin: 0 4px;
padding: 0 10px;
-moz-appearance: none;
border-radius: 10000px;
border: @roundButtonBorder@;
text-shadow: @loweredShadow@;
background: @roundButtonBackground@;
box-shadow: @roundButtonShadow@;
}
#saveSearch > .button-box > .button-text {
margin: 0 !important;
}
#saveSearch:active:hover {
background: @roundButtonPressedBackground@;
box-shadow: @roundButtonPressedShadow@;
}
#saveSearch:focus {
box-shadow: @focusRingShadow@, @roundButtonShadow@;
}
#saveSearch:active:hover:focus {
box-shadow: @focusRingShadow@, @roundButtonPressedShadow@;
}
/**** expanders ****/
.expander-up,

View File

@ -37,7 +37,6 @@
@media (-moz-windows-default-theme) {
#placesView,
#searchModifiers,
#infoPane,
#placesList,
#placeContent {
@ -59,15 +58,6 @@
position: relative;
}
#searchModifiers {
border-bottom: 1px solid #A9B7C9;
}
#organizerScopeBar {
-moz-appearance: none;
border: none;
}
#detailsDeck {
border-top-color: #A9B7C9;
}

View File

@ -124,37 +124,6 @@
-moz-padding-start: 2px;
}
#organizerScopeBar {
padding: 2px 0;
-moz-padding-end: 3px;
}
#organizerScopeBar > toolbarbutton {
-moz-appearance: none;
border: 1px solid transparent;
border-radius: 2px;
padding: 0 !important;
margin: 0 1px;
}
#organizerScopeBar > toolbarbutton > .toolbarbutton-icon {
padding: 0;
margin: 0;
}
#organizerScopeBar > toolbarbutton > .toolbarbutton-text {
margin: 0;
padding: 2px 5px;
}
#organizerScopeBar > toolbarbutton:not([disabled="true"]):not([checked="true"]):hover {
border-color: ThreeDShadow;
}
#organizerScopeBar > toolbarbutton[checked="true"] {
border-color: ThreeDDarkShadow !important;
}
#searchFilter {
margin: 0;
}

View File

@ -66,23 +66,28 @@ public class DoorHangerPopup extends PopupWindow
public void handleMessage(String event, JSONObject geckoObject) {
try {
if (event.equals("Doorhanger:Add")) {
int tabId = geckoObject.getInt("tabID");
String value = geckoObject.getString("value");
String message = geckoObject.getString("message");
JSONArray buttons = geckoObject.getJSONArray("buttons");
JSONObject options = geckoObject.getJSONObject("options");
final int tabId = geckoObject.getInt("tabID");
final String value = geckoObject.getString("value");
final String message = geckoObject.getString("message");
final JSONArray buttons = geckoObject.getJSONArray("buttons");
final JSONObject options = geckoObject.getJSONObject("options");
addDoorHanger(tabId, value, message, buttons, options);
} else if (event.equals("Doorhanger:Remove")) {
int tabId = geckoObject.getInt("tabID");
String value = geckoObject.getString("value");
DoorHanger doorHanger = getDoorHanger(tabId, value);
if (doorHanger == null)
return;
removeDoorHanger(doorHanger);
mActivity.runOnUiThread(new Runnable() {
public void run() {
addDoorHanger(tabId, value, message, buttons, options);
}
});
} else if (event.equals("Doorhanger:Remove")) {
final int tabId = geckoObject.getInt("tabID");
final String value = geckoObject.getString("value");
mActivity.runOnUiThread(new Runnable() {
public void run() {
DoorHanger doorHanger = getDoorHanger(tabId, value);
if (doorHanger == null)
return;
removeDoorHanger(doorHanger);
updatePopup();
}
});
@ -92,7 +97,8 @@ public class DoorHangerPopup extends PopupWindow
}
}
public void onTabChanged(Tab tab, Tabs.TabEvents msg, Object data) {
// This callback is automatically executed on the UI thread.
public void onTabChanged(final Tab tab, final Tabs.TabEvents msg, final Object data) {
switch(msg) {
case CLOSED:
// Remove any doorhangers for a tab when it's closed (make
@ -140,6 +146,11 @@ public class DoorHangerPopup extends PopupWindow
mInflated = true;
}
/**
* Adds a doorhanger.
*
* This method must be called on the UI thread.
*/
void addDoorHanger(final int tabId, final String value, final String message,
final JSONArray buttons, final JSONObject options) {
// Don't add a doorhanger for a tab that doesn't exist
@ -154,22 +165,22 @@ public class DoorHangerPopup extends PopupWindow
final DoorHanger newDoorHanger = new DoorHanger(mActivity, this, tabId, value);
mDoorHangers.add(newDoorHanger);
// Update the UI bits on the main thread
mActivity.runOnUiThread(new Runnable() {
public void run() {
if (!mInflated)
init();
if (!mInflated)
init();
newDoorHanger.init(message, buttons, options);
mContent.addView(newDoorHanger);
newDoorHanger.init(message, buttons, options);
mContent.addView(newDoorHanger);
// Only update the popup if we're adding a notifcation to the selected tab
if (tabId == Tabs.getInstance().getSelectedTab().getId())
updatePopup();
}
});
// Only update the popup if we're adding a notifcation to the selected tab
if (tabId == Tabs.getInstance().getSelectedTab().getId())
updatePopup();
}
/**
* Gets a doorhanger.
*
* This method must be called on the UI thread.
*/
DoorHanger getDoorHanger(int tabId, String value) {
for (DoorHanger dh : mDoorHangers) {
if (dh.getTabId() == tabId && dh.getValue().equals(value))
@ -180,17 +191,21 @@ public class DoorHangerPopup extends PopupWindow
return null;
}
/**
* Removes a doorhanger.
*
* This method must be called on the UI thread.
*/
void removeDoorHanger(final DoorHanger doorHanger) {
mDoorHangers.remove(doorHanger);
// Update the UI on the main thread
mActivity.runOnUiThread(new Runnable() {
public void run() {
mContent.removeView(doorHanger);
}
});
mContent.removeView(doorHanger);
}
/**
* Removes doorhangers for a given tab.
*
* This method must be called on the UI thread.
*/
void removeTransientDoorHangers(int tabId) {
// Make a temporary set to avoid a ConcurrentModificationException
HashSet<DoorHanger> doorHangersToRemove = new HashSet<DoorHanger>();
@ -205,6 +220,11 @@ public class DoorHangerPopup extends PopupWindow
}
}
/**
* Updates the popup state.
*
* This method must be called on the UI thread.
*/
void updatePopup() {
// Bail if the selected tab is null, if there are no active doorhangers,
// or if we haven't inflated the layout yet (this can happen if updatePopup()

View File

@ -562,6 +562,7 @@ public class AllPagesTab extends AwesomeBarTab implements GeckoEventListener {
Log.e(LOGTAG, "Error getting search engine JSON", e);
}
mCursorAdapter.notifyDataSetChanged();
filterSuggestions(mSearchTerm);
}

View File

@ -6945,10 +6945,7 @@ var Telemetry = {
link: {
label: learnMoreLabel,
url: learnMoreUrl
},
// We're adding this doorhanger during startup, before the initial onLocationChange
// event fires, so we need to set persistence to make sure it doesn't disappear.
persistence: 1
}
};
NativeWindow.doorhanger.show(message, "telemetry-optin", buttons, BrowserApp.selectedTab.id, options);
},

View File

@ -5,5 +5,7 @@
"dom/tests/mochitest/dom-level2-core": "",
"dom/tests/mochitest/dom-level2-html": ""
},
"excludetests": {}
"excludetests": {
"dom/tests/mochitest/dom-level0/test_innerWidthHeight_script.html": "bug 807137"
}
}