Bug 748894 - Move the bookmark star button outside of the location bar.
r=Mano
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// StarUI
|
||||
|
||||
var StarUI = {
|
||||
_itemId: -1,
|
||||
@@ -218,10 +220,6 @@ var StarUI = {
|
||||
gEditItemOverlay.uninitPanel(true);
|
||||
},
|
||||
|
||||
editButtonCommand: function SU_editButtonCommand() {
|
||||
this.showEditBookmarkPopup();
|
||||
},
|
||||
|
||||
cancelButtonOnCommand: function SU_cancelButtonOnCommand() {
|
||||
this._actionOnHide = "cancel";
|
||||
this.panel.hidePopup();
|
||||
@@ -241,6 +239,9 @@ var StarUI = {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// PlacesCommandHook
|
||||
|
||||
var PlacesCommandHook = {
|
||||
/**
|
||||
* Adds a bookmark to the page loaded in the given browser.
|
||||
@@ -293,28 +294,37 @@ var PlacesCommandHook = {
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
title, null, [descAnno]);
|
||||
PlacesUtils.transactionManager.doTransaction(txn);
|
||||
itemId = txn.item.id;
|
||||
// Set the character-set
|
||||
if (charset && !PrivateBrowsingUtils.isWindowPrivate(aBrowser.contentWindow))
|
||||
PlacesUtils.setCharsetForURI(uri, charset);
|
||||
itemId = PlacesUtils.getMostRecentBookmarkForURI(uri);
|
||||
}
|
||||
|
||||
// Revert the contents of the location bar
|
||||
if (gURLBar)
|
||||
gURLBar.handleRevert();
|
||||
|
||||
// dock the panel to the star icon when possible, otherwise dock
|
||||
// it to the content area
|
||||
if (aBrowser.contentWindow == window.content) {
|
||||
var starIcon = aBrowser.ownerDocument.getElementById("star-button");
|
||||
if (starIcon && isElementVisible(starIcon)) {
|
||||
if (aShowEditUI)
|
||||
StarUI.showEditBookmarkPopup(itemId, starIcon, "bottomcenter topright");
|
||||
return;
|
||||
}
|
||||
// If it was not requested to open directly in "edit" mode, we are done.
|
||||
if (!aShowEditUI)
|
||||
return;
|
||||
|
||||
// Try to dock the panel to:
|
||||
// 1. the bookmarks menu button
|
||||
// 2. the page-proxy-favicon
|
||||
// 3. the content area
|
||||
if (BookmarksMenuButton.anchor) {
|
||||
StarUI.showEditBookmarkPopup(itemId, BookmarksMenuButton.anchor,
|
||||
"bottomcenter topright");
|
||||
return;
|
||||
}
|
||||
|
||||
StarUI.showEditBookmarkPopup(itemId, aBrowser, "overlap");
|
||||
let pageProxyFavicon = document.getElementById("page-proxy-favicon");
|
||||
if (isElementVisible(pageProxyFavicon)) {
|
||||
StarUI.showEditBookmarkPopup(itemId, pageProxyFavicon,
|
||||
"bottomcenter topright");
|
||||
} else {
|
||||
StarUI.showEditBookmarkPopup(itemId, aBrowser, "overlap");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -460,6 +470,9 @@ var PlacesCommandHook = {
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// HistoryMenu
|
||||
|
||||
// View for the history menu.
|
||||
function HistoryMenu(aPopupShowingEvent) {
|
||||
// Workaround for Bug 610187. The sidebar does not include all the Places
|
||||
@@ -686,6 +699,9 @@ HistoryMenu.prototype = {
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// BookmarksEventHandler
|
||||
|
||||
/**
|
||||
* Functions for handling events in the Bookmarks Toolbar and menu.
|
||||
*/
|
||||
@@ -811,6 +827,8 @@ var BookmarksEventHandler = {
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// PlacesMenuDNDHandler
|
||||
|
||||
// Handles special drag and drop functionality for Places menus that are not
|
||||
// part of a Places view (e.g. the bookmarks menu in the menubar).
|
||||
@@ -829,26 +847,37 @@ var PlacesMenuDNDHandler = {
|
||||
if (!this._isStaticContainer(event.target))
|
||||
return;
|
||||
|
||||
let popup = event.target.lastChild;
|
||||
if (this._loadTimer || popup.state === "showing" || popup.state === "open")
|
||||
return;
|
||||
|
||||
this._loadTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
this._loadTimer.initWithCallback(function() {
|
||||
PlacesMenuDNDHandler._loadTimer = null;
|
||||
event.target.lastChild.setAttribute("autoopened", "true");
|
||||
event.target.lastChild.showPopup(event.target.lastChild);
|
||||
this._loadTimer.initWithCallback(() => {
|
||||
this._loadTimer = null;
|
||||
popup.setAttribute("autoopened", "true");
|
||||
popup.showPopup(popup);
|
||||
}, this._springLoadDelay, Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles dragexit on the <menu> element.
|
||||
* Handles dragleave on the <menu> element.
|
||||
* @returns true if the element is a container element (menu or
|
||||
* menu-toolbarbutton), false otherwise.
|
||||
*/
|
||||
onDragExit: function PMDH_onDragExit(event) {
|
||||
onDragLeave: function PMDH_onDragLeave(event) {
|
||||
// Handle menu-button separate targets.
|
||||
if (event.relatedTarget === event.currentTarget ||
|
||||
event.relatedTarget.parentNode === event.currentTarget)
|
||||
return;
|
||||
|
||||
// Closing menus in a Places popup is handled by the view itself.
|
||||
if (!this._isStaticContainer(event.target))
|
||||
return;
|
||||
|
||||
let popup = event.target.lastChild;
|
||||
|
||||
if (this._loadTimer) {
|
||||
this._loadTimer.cancel();
|
||||
this._loadTimer = null;
|
||||
@@ -862,10 +891,9 @@ var PlacesMenuDNDHandler = {
|
||||
inHierarchy = node == event.target;
|
||||
node = node.parentNode;
|
||||
}
|
||||
if (!inHierarchy && event.target.lastChild &&
|
||||
event.target.lastChild.hasAttribute("autoopened")) {
|
||||
event.target.lastChild.removeAttribute("autoopened");
|
||||
event.target.lastChild.hidePopup();
|
||||
if (!inHierarchy && popup && popup.hasAttribute("autoopened")) {
|
||||
popup.removeAttribute("autoopened");
|
||||
popup.hidePopup();
|
||||
}
|
||||
}, this._springLoadDelay, Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
},
|
||||
@@ -878,7 +906,8 @@ var PlacesMenuDNDHandler = {
|
||||
_isStaticContainer: function PMDH__isContainer(node) {
|
||||
let isMenu = node.localName == "menu" ||
|
||||
(node.localName == "toolbarbutton" &&
|
||||
node.getAttribute("type") == "menu");
|
||||
(node.getAttribute("type") == "menu" ||
|
||||
node.getAttribute("type") == "menu-button"));
|
||||
let isStatic = !("_placesNode" in node) && node.lastChild &&
|
||||
node.lastChild.hasAttribute("placespopup") &&
|
||||
!node.parentNode.hasAttribute("placespopup");
|
||||
@@ -915,179 +944,13 @@ var PlacesMenuDNDHandler = {
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// PlacesToolbarHelper
|
||||
|
||||
var PlacesStarButton = {
|
||||
_hasBookmarksObserver: false,
|
||||
uninit: function PSB_uninit()
|
||||
{
|
||||
if (this._hasBookmarksObserver) {
|
||||
PlacesUtils.removeLazyBookmarkObserver(this);
|
||||
}
|
||||
if (this._pendingStmt) {
|
||||
this._pendingStmt.cancel();
|
||||
delete this._pendingStmt;
|
||||
}
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([
|
||||
Ci.nsINavBookmarkObserver
|
||||
]),
|
||||
|
||||
get _starredTooltip()
|
||||
{
|
||||
delete this._starredTooltip;
|
||||
return this._starredTooltip =
|
||||
gNavigatorBundle.getString("starButtonOn.tooltip");
|
||||
},
|
||||
get _unstarredTooltip()
|
||||
{
|
||||
delete this._unstarredTooltip;
|
||||
return this._unstarredTooltip =
|
||||
gNavigatorBundle.getString("starButtonOff.tooltip");
|
||||
},
|
||||
|
||||
updateState: function PSB_updateState()
|
||||
{
|
||||
this._starIcon = document.getElementById("star-button");
|
||||
if (!this._starIcon || (this._uri && gBrowser.currentURI.equals(this._uri))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset tracked values.
|
||||
this._uri = gBrowser.currentURI;
|
||||
this._itemIds = [];
|
||||
|
||||
if (this._pendingStmt) {
|
||||
this._pendingStmt.cancel();
|
||||
delete this._pendingStmt;
|
||||
}
|
||||
|
||||
// We can load about:blank before the actual page, but there is no point in handling that page.
|
||||
if (isBlankPageURL(this._uri.spec)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._pendingStmt = PlacesUtils.asyncGetBookmarkIds(this._uri, function (aItemIds, aURI) {
|
||||
// Safety check that the bookmarked URI equals the tracked one.
|
||||
if (!aURI.equals(this._uri)) {
|
||||
Components.utils.reportError("PlacesStarButton did not receive current URI");
|
||||
return;
|
||||
}
|
||||
|
||||
// It's possible that onItemAdded gets called before the async statement
|
||||
// calls back. For such an edge case, retain all unique entries from both
|
||||
// arrays.
|
||||
this._itemIds = this._itemIds.filter(
|
||||
function (id) aItemIds.indexOf(id) == -1
|
||||
).concat(aItemIds);
|
||||
this._updateStateInternal();
|
||||
|
||||
// Start observing bookmarks if needed.
|
||||
if (!this._hasBookmarksObserver) {
|
||||
try {
|
||||
PlacesUtils.addLazyBookmarkObserver(this);
|
||||
this._hasBookmarksObserver = true;
|
||||
} catch(ex) {
|
||||
Components.utils.reportError("PlacesStarButton failed adding a bookmarks observer: " + ex);
|
||||
}
|
||||
}
|
||||
|
||||
delete this._pendingStmt;
|
||||
}, this);
|
||||
},
|
||||
|
||||
_updateStateInternal: function PSB__updateStateInternal()
|
||||
{
|
||||
if (!this._starIcon) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._itemIds.length > 0) {
|
||||
this._starIcon.setAttribute("starred", "true");
|
||||
this._starIcon.setAttribute("tooltiptext", this._starredTooltip);
|
||||
}
|
||||
else {
|
||||
this._starIcon.removeAttribute("starred");
|
||||
this._starIcon.setAttribute("tooltiptext", this._unstarredTooltip);
|
||||
}
|
||||
},
|
||||
|
||||
onClick: function PSB_onClick(aEvent)
|
||||
{
|
||||
// Ignore clicks on the star while we update its state.
|
||||
if (aEvent.button == 0 && !this._pendingStmt) {
|
||||
PlacesCommandHook.bookmarkCurrentPage(this._itemIds.length > 0);
|
||||
}
|
||||
// Don't bubble to the textbox, to avoid unwanted selection of the address.
|
||||
aEvent.stopPropagation();
|
||||
},
|
||||
|
||||
// nsINavBookmarkObserver
|
||||
onItemAdded:
|
||||
function PSB_onItemAdded(aItemId, aFolder, aIndex, aItemType, aURI)
|
||||
{
|
||||
if (!this._starIcon) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aURI && aURI.equals(this._uri)) {
|
||||
// If a new bookmark has been added to the tracked uri, register it.
|
||||
if (this._itemIds.indexOf(aItemId) == -1) {
|
||||
this._itemIds.push(aItemId);
|
||||
this._updateStateInternal();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onItemRemoved:
|
||||
function PSB_onItemRemoved(aItemId, aFolder, aIndex, aItemType)
|
||||
{
|
||||
if (!this._starIcon) {
|
||||
return;
|
||||
}
|
||||
|
||||
let index = this._itemIds.indexOf(aItemId);
|
||||
// If one of the tracked bookmarks has been removed, unregister it.
|
||||
if (index != -1) {
|
||||
this._itemIds.splice(index, 1);
|
||||
this._updateStateInternal();
|
||||
}
|
||||
},
|
||||
|
||||
onItemChanged:
|
||||
function PSB_onItemChanged(aItemId, aProperty, aIsAnnotationProperty,
|
||||
aNewValue, aLastModified, aItemType)
|
||||
{
|
||||
if (!this._starIcon) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aProperty == "uri") {
|
||||
let index = this._itemIds.indexOf(aItemId);
|
||||
// If the changed bookmark was tracked, check if it is now pointing to
|
||||
// a different uri and unregister it.
|
||||
if (index != -1 && aNewValue != this._uri.spec) {
|
||||
this._itemIds.splice(index, 1);
|
||||
this._updateStateInternal();
|
||||
}
|
||||
// If another bookmark is now pointing to the tracked uri, register it.
|
||||
else if (index == -1 && aNewValue == this._uri.spec) {
|
||||
this._itemIds.push(aItemId);
|
||||
this._updateStateInternal();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onBeginUpdateBatch: function () {},
|
||||
onEndUpdateBatch: function () {},
|
||||
onItemVisited: function () {},
|
||||
onItemMoved: function () {}
|
||||
};
|
||||
|
||||
|
||||
// This object handles the initialization and uninitialization of the bookmarks
|
||||
// toolbar. updateState is called when the browser window is opened and
|
||||
// after closing the toolbar customization dialog.
|
||||
/**
|
||||
* This object handles the initialization and uninitialization of the bookmarks
|
||||
* toolbar.
|
||||
*/
|
||||
let PlacesToolbarHelper = {
|
||||
_place: "place:folder=TOOLBAR",
|
||||
|
||||
@@ -1127,58 +990,95 @@ let PlacesToolbarHelper = {
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// BookmarksMenuButton
|
||||
|
||||
// Handles the bookmarks menu button shown when the main menubar is hidden.
|
||||
/**
|
||||
* Handles the bookmarks menu-button in the toolbar.
|
||||
*/
|
||||
let BookmarksMenuButton = {
|
||||
get button() {
|
||||
return document.getElementById("bookmarks-menu-button");
|
||||
if (!this._button) {
|
||||
this._button = document.getElementById("bookmarks-menu-button");
|
||||
}
|
||||
return this._button;
|
||||
},
|
||||
|
||||
get buttonContainer() {
|
||||
return document.getElementById("bookmarks-menu-button-container");
|
||||
get star() {
|
||||
if (!this._star && this.button) {
|
||||
this._star = document.getAnonymousElementByAttribute(this.button,
|
||||
"anonid",
|
||||
"button");
|
||||
}
|
||||
return this._star;
|
||||
},
|
||||
|
||||
get personalToolbar() {
|
||||
delete this.personalToolbar;
|
||||
return this.personalToolbar = document.getElementById("PersonalToolbar");
|
||||
get anchor() {
|
||||
if (!this._anchor && this.star && isElementVisible(this.star)) {
|
||||
// Anchor to the icon, so the panel looks more natural.
|
||||
this._anchor = document.getAnonymousElementByAttribute(this.star,
|
||||
"class",
|
||||
"toolbarbutton-icon");
|
||||
}
|
||||
return this._anchor;
|
||||
},
|
||||
|
||||
get bookmarksToolbarItem() {
|
||||
return document.getElementById("personal-bookmarks");
|
||||
STATUS_UPDATING: -1,
|
||||
STATUS_UNSTARRED: 0,
|
||||
STATUS_STARRED: 1,
|
||||
get status() {
|
||||
if (this._pendingStmt)
|
||||
return this.STATUS_UPDATING;
|
||||
return this.button &&
|
||||
this.button.hasAttribute("starred") ? this.STATUS_STARRED
|
||||
: this.STATUS_UNSTARRED;
|
||||
},
|
||||
|
||||
init: function BMB_init() {
|
||||
this.updatePosition();
|
||||
|
||||
// Any other stuff that does not regard the button itself should be
|
||||
// handled in the onPopupShowing handler, so it does not hit Ts.
|
||||
get _starredTooltip()
|
||||
{
|
||||
delete this._starredTooltip;
|
||||
return this._starredTooltip =
|
||||
gNavigatorBundle.getString("starButtonOn.tooltip");
|
||||
},
|
||||
|
||||
get _unstarredTooltip()
|
||||
{
|
||||
delete this._unstarredTooltip;
|
||||
return this._unstarredTooltip =
|
||||
gNavigatorBundle.getString("starButtonOff.tooltip");
|
||||
},
|
||||
|
||||
/**
|
||||
* The popup contents must be updated when the user customizes the UI, or
|
||||
* changes the personal toolbar collapsed status. In such a case, any needed
|
||||
* change should be handled in the popupshowing helper, for performance
|
||||
* reasons.
|
||||
*/
|
||||
_popupNeedsUpdate: true,
|
||||
onToolbarVisibilityChange: function BMB_onToolbarVisibilityChange() {
|
||||
this._popupNeedsUpdate = true;
|
||||
},
|
||||
|
||||
_popupNeedsUpdate: {},
|
||||
onPopupShowing: function BMB_onPopupShowing(event) {
|
||||
// Don't handle events for submenus.
|
||||
if (event.target != event.currentTarget)
|
||||
return;
|
||||
|
||||
let popup = event.target;
|
||||
let needsUpdate = this._popupNeedsUpdate[popup.id];
|
||||
|
||||
// Check if popup contents need to be updated. Note that if needsUpdate is
|
||||
// undefined we have never seen the popup, thus it should be updated.
|
||||
if (needsUpdate === false)
|
||||
if (!this._popupNeedsUpdate)
|
||||
return;
|
||||
this._popupNeedsUpdate[popup.id] = false;
|
||||
this._popupNeedsUpdate = false;
|
||||
|
||||
function getPlacesAnonymousElement(aAnonId)
|
||||
document.getAnonymousElementByAttribute(popup.parentNode,
|
||||
"placesanonid",
|
||||
aAnonId);
|
||||
let popup = event.target;
|
||||
let getPlacesAnonymousElement =
|
||||
aAnonId => document.getAnonymousElementByAttribute(popup.parentNode,
|
||||
"placesanonid",
|
||||
aAnonId);
|
||||
|
||||
let viewToolbarMenuitem = getPlacesAnonymousElement("view-toolbar");
|
||||
if (viewToolbarMenuitem) {
|
||||
// Update View bookmarks toolbar checkbox menuitem.
|
||||
viewToolbarMenuitem.setAttribute("checked",
|
||||
!this.personalToolbar.collapsed);
|
||||
let personalToolbar = document.getElementById("PersonalToolbar");
|
||||
viewToolbarMenuitem.setAttribute("checked", !personalToolbar.collapsed);
|
||||
}
|
||||
|
||||
let toolbarMenuitem = getPlacesAnonymousElement("toolbar-autohide");
|
||||
@@ -1186,68 +1086,44 @@ let BookmarksMenuButton = {
|
||||
// If bookmarks items are visible, hide Bookmarks Toolbar menu and the
|
||||
// separator after it.
|
||||
toolbarMenuitem.collapsed = toolbarMenuitem.nextSibling.collapsed =
|
||||
isElementVisible(this.bookmarksToolbarItem);
|
||||
isElementVisible(document.getElementById("personal-bookmarks"));
|
||||
}
|
||||
},
|
||||
|
||||
updatePosition: function BMB_updatePosition() {
|
||||
// Popups will have to be updated when the user customizes the UI, or
|
||||
// changes personal toolbar collapsed status. Both of those location call
|
||||
// updatePosition(), so this is the only point asking for popup updates.
|
||||
for (let popupId in this._popupNeedsUpdate) {
|
||||
this._popupNeedsUpdate[popupId] = true;
|
||||
/**
|
||||
* Handles star styling based on page proxy state changes.
|
||||
*/
|
||||
onPageProxyStateChanged: function BMB_onPageProxyStateChanged(aState) {
|
||||
if (!this.star) {
|
||||
return;
|
||||
}
|
||||
|
||||
let button = this.button;
|
||||
if (!button)
|
||||
return;
|
||||
|
||||
// If the toolbar containing bookmarks is visible, we want to move the
|
||||
// button to bookmarksToolbarItem.
|
||||
let bookmarksToolbarItem = this.bookmarksToolbarItem;
|
||||
let bookmarksOnVisibleToolbar = bookmarksToolbarItem &&
|
||||
!bookmarksToolbarItem.parentNode.collapsed &&
|
||||
bookmarksToolbarItem.parentNode.getAttribute("autohide") != "true";
|
||||
|
||||
// If the container has been moved by the user to the toolbar containing
|
||||
// bookmarks, we want to preserve the desired position.
|
||||
let container = this.buttonContainer;
|
||||
let containerNearBookmarks = container && bookmarksToolbarItem &&
|
||||
container.parentNode == bookmarksToolbarItem.parentNode;
|
||||
|
||||
if (bookmarksOnVisibleToolbar && !containerNearBookmarks) {
|
||||
if (button.parentNode != bookmarksToolbarItem) {
|
||||
this._uninitView();
|
||||
bookmarksToolbarItem.appendChild(button);
|
||||
}
|
||||
if (aState == "invalid") {
|
||||
this.star.setAttribute("disabled", "true");
|
||||
this.button.removeAttribute("starred");
|
||||
}
|
||||
else {
|
||||
if (container && button.parentNode != container) {
|
||||
this._uninitView();
|
||||
container.appendChild(button);
|
||||
}
|
||||
this.star.removeAttribute("disabled");
|
||||
}
|
||||
this._updateStyle();
|
||||
},
|
||||
|
||||
_updateStyle: function BMB__updateStyle() {
|
||||
let button = this.button;
|
||||
if (!button)
|
||||
if (!this.star) {
|
||||
return;
|
||||
}
|
||||
|
||||
let container = this.buttonContainer;
|
||||
let containerOnPersonalToolbar = container &&
|
||||
(container.parentNode == this.personalToolbar ||
|
||||
container.parentNode.parentNode == this.personalToolbar);
|
||||
let personalToolbar = document.getElementById("PersonalToolbar");
|
||||
let onPersonalToolbar = this.button.parentNode == personalToolbar ||
|
||||
this.button.parentNode.parentNode == personalToolbar;
|
||||
|
||||
if (button.parentNode == this.bookmarksToolbarItem ||
|
||||
containerOnPersonalToolbar) {
|
||||
button.classList.add("bookmark-item");
|
||||
button.classList.remove("toolbarbutton-1");
|
||||
if (onPersonalToolbar) {
|
||||
this.button.classList.add("bookmark-item");
|
||||
this.button.classList.remove("toolbarbutton-1");
|
||||
}
|
||||
else {
|
||||
button.classList.remove("bookmark-item");
|
||||
button.classList.add("toolbarbutton-1");
|
||||
this.button.classList.remove("bookmark-item");
|
||||
this.button.classList.add("toolbarbutton-1");
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1255,20 +1131,13 @@ let BookmarksMenuButton = {
|
||||
// When an element with a placesView attached is removed and re-inserted,
|
||||
// XBL reapplies the binding causing any kind of issues and possible leaks,
|
||||
// so kill current view and let popupshowing generate a new one.
|
||||
let button = this.button;
|
||||
if (button && button._placesView)
|
||||
button._placesView.uninit();
|
||||
if (this.button && this.button._placesView) {
|
||||
this.button._placesView.uninit();
|
||||
}
|
||||
},
|
||||
|
||||
customizeStart: function BMB_customizeStart() {
|
||||
this._uninitView();
|
||||
let button = this.button;
|
||||
let container = this.buttonContainer;
|
||||
if (button && container && button.parentNode != container) {
|
||||
// Move button back to the container, so user can move or remove it.
|
||||
container.appendChild(button);
|
||||
this._updateStyle();
|
||||
}
|
||||
},
|
||||
|
||||
customizeChange: function BMB_customizeChange() {
|
||||
@@ -1276,6 +1145,159 @@ let BookmarksMenuButton = {
|
||||
},
|
||||
|
||||
customizeDone: function BMB_customizeDone() {
|
||||
this.updatePosition();
|
||||
}
|
||||
delete this._button;
|
||||
delete this._star;
|
||||
delete this._anchor;
|
||||
this.onToolbarVisibilityChange();
|
||||
this._updateStyle();
|
||||
},
|
||||
|
||||
_hasBookmarksObserver: false,
|
||||
uninit: function BMB_uninit() {
|
||||
this._uninitView();
|
||||
|
||||
if (this._hasBookmarksObserver) {
|
||||
PlacesUtils.removeLazyBookmarkObserver(this);
|
||||
}
|
||||
|
||||
if (this._pendingStmt) {
|
||||
this._pendingStmt.cancel();
|
||||
delete this._pendingStmt;
|
||||
}
|
||||
},
|
||||
|
||||
updateStarState: function BMB_updateStarState() {
|
||||
if (!this.button || (this._uri && gBrowser.currentURI.equals(this._uri))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset tracked values.
|
||||
this._uri = gBrowser.currentURI;
|
||||
this._itemIds = [];
|
||||
|
||||
if (this._pendingStmt) {
|
||||
this._pendingStmt.cancel();
|
||||
delete this._pendingStmt;
|
||||
}
|
||||
|
||||
// We can load about:blank before the actual page, but there is no point in handling that page.
|
||||
if (isBlankPageURL(this._uri.spec)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._pendingStmt = PlacesUtils.asyncGetBookmarkIds(this._uri, function (aItemIds, aURI) {
|
||||
// Safety check that the bookmarked URI equals the tracked one.
|
||||
if (!aURI.equals(this._uri)) {
|
||||
Components.utils.reportError("BookmarksMenuButton did not receive current URI");
|
||||
return;
|
||||
}
|
||||
|
||||
// It's possible that onItemAdded gets called before the async statement
|
||||
// calls back. For such an edge case, retain all unique entries from both
|
||||
// arrays.
|
||||
this._itemIds = this._itemIds.filter(
|
||||
function (id) aItemIds.indexOf(id) == -1
|
||||
).concat(aItemIds);
|
||||
|
||||
this._updateStar();
|
||||
|
||||
// Start observing bookmarks if needed.
|
||||
if (!this._hasBookmarksObserver) {
|
||||
try {
|
||||
PlacesUtils.addLazyBookmarkObserver(this);
|
||||
this._hasBookmarksObserver = true;
|
||||
} catch(ex) {
|
||||
Components.utils.reportError("BookmarksMenuButton failed adding a bookmarks observer: " + ex);
|
||||
}
|
||||
}
|
||||
|
||||
delete this._pendingStmt;
|
||||
}, this);
|
||||
},
|
||||
|
||||
_updateStar: function BMB__updateStar() {
|
||||
if (!this.button) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._itemIds.length > 0) {
|
||||
this.button.setAttribute("starred", "true");
|
||||
this.button.setAttribute("tooltiptext", this._starredTooltip);
|
||||
}
|
||||
else {
|
||||
this.button.removeAttribute("starred");
|
||||
this.button.setAttribute("tooltiptext", this._unstarredTooltip);
|
||||
}
|
||||
},
|
||||
|
||||
onCommand: function BMB_onCommand(aEvent) {
|
||||
if (aEvent.target != aEvent.currentTarget) {
|
||||
return;
|
||||
}
|
||||
// Ignore clicks on the star if we are updating its state.
|
||||
if (!this._pendingStmt) {
|
||||
PlacesCommandHook.bookmarkCurrentPage(this._itemIds.length > 0);
|
||||
}
|
||||
},
|
||||
|
||||
// nsINavBookmarkObserver
|
||||
onItemAdded: function BMB_onItemAdded(aItemId, aParentId, aIndex, aItemType,
|
||||
aURI) {
|
||||
if (!this.button) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aURI && aURI.equals(this._uri)) {
|
||||
// If a new bookmark has been added to the tracked uri, register it.
|
||||
if (this._itemIds.indexOf(aItemId) == -1) {
|
||||
this._itemIds.push(aItemId);
|
||||
this._updateStar();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onItemRemoved: function BMB_onItemRemoved(aItemId) {
|
||||
if (!this.button) {
|
||||
return;
|
||||
}
|
||||
|
||||
let index = this._itemIds.indexOf(aItemId);
|
||||
// If one of the tracked bookmarks has been removed, unregister it.
|
||||
if (index != -1) {
|
||||
this._itemIds.splice(index, 1);
|
||||
this._updateStar();
|
||||
}
|
||||
},
|
||||
|
||||
onItemChanged: function BMB_onItemChanged(aItemId, aProperty,
|
||||
aIsAnnotationProperty, aNewValue) {
|
||||
if (!this.button) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aProperty == "uri") {
|
||||
let index = this._itemIds.indexOf(aItemId);
|
||||
// If the changed bookmark was tracked, check if it is now pointing to
|
||||
// a different uri and unregister it.
|
||||
if (index != -1 && aNewValue != this._uri.spec) {
|
||||
this._itemIds.splice(index, 1);
|
||||
this._updateStar();
|
||||
}
|
||||
// If another bookmark is now pointing to the tracked uri, register it.
|
||||
else if (index == -1 && aNewValue == this._uri.spec) {
|
||||
this._itemIds.push(aItemId);
|
||||
this._updateStar();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onBeginUpdateBatch: function () {},
|
||||
onEndUpdateBatch: function () {},
|
||||
onBeforeItemRemoved: function () {},
|
||||
onItemVisited: function () {},
|
||||
onItemMoved: function () {},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([
|
||||
Ci.nsINavBookmarkObserver
|
||||
]),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user