+ Simple image:
+
+ Linked image:
+
+ Simple image with alt:
+
+ Linked image with alt:
+
+ Simple image with title:
+
+ Linked image with title:
+
+ Simple image with empty alt:
+
+ Linked image with empty alt:
+
+ Simple image with empty alt and title:
+
+ Linked image with empty alt and title:
+
+
+
diff --git a/accessible/tests/mochitest/test_table_indexes.html b/accessible/tests/mochitest/test_table_indexes.html
index 41e4d056527b..a291a5e19d75 100644
--- a/accessible/tests/mochitest/test_table_indexes.html
+++ b/accessible/tests/mochitest/test_table_indexes.html
@@ -89,7 +89,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=410052
if (cellAcc) {
var attrs = cellAcc.attributes;
- is (parseInt(attrs.getStringProperty("cell-index")), index,
+ is (parseInt(attrs.getStringProperty("table-cell-index")), index,
aId + ": cell index from object attributes of cell accessible isn't corrent.");
}
}
diff --git a/browser/app/Makefile.in b/browser/app/Makefile.in
index e1c6d4b05128..0fc19f4740ee 100644
--- a/browser/app/Makefile.in
+++ b/browser/app/Makefile.in
@@ -76,6 +76,9 @@ ifdef MOZ_MEMORY
ifeq ($(OS_ARCH),Darwin)
LIBS += -ljemalloc
endif
+ifeq ($(OS_ARCH),SunOS)
+SOLARIS_JEMALLOC_LDFLAGS = -L$(LIBXUL_DIST)/bin -lxul
+endif
endif
ifdef LIBXUL_SDK
diff --git a/browser/app/blocklist.xml b/browser/app/blocklist.xml
index bd22b625bf03..30fa1b987507 100644
--- a/browser/app/blocklist.xml
+++ b/browser/app/blocklist.xml
@@ -16,4 +16,11 @@
+
+
+
+
+
+
+
diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js
index 0eecba0c657d..b2da7a5a1741 100644
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -80,7 +80,7 @@ pref("extensions.getAddons.search.url", "https://services.addons.mozilla.org/%LO
// Blocklist preferences
pref("extensions.blocklist.enabled", true);
pref("extensions.blocklist.interval", 86400);
-pref("extensions.blocklist.url", "https://addons.mozilla.org/blocklist/1/%APP_ID%/%APP_VERSION%/");
+pref("extensions.blocklist.url", "https://addons.mozilla.org/blocklist/2/%APP_ID%/%APP_VERSION%/%PRODUCT%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/");
pref("extensions.blocklist.detailsURL", "http://%LOCALE%.www.mozilla.com/%LOCALE%/blocklist/");
// Dictionary download preference
@@ -213,7 +213,10 @@ pref("browser.urlbar.doubleClickSelectsAll", false);
#endif
pref("browser.urlbar.autoFill", false);
pref("browser.urlbar.matchOnlyTyped", false);
-pref("browser.urlbar.matchOnWordBoundary", true);
+// 0: Match anywhere (e.g., middle of words)
+// 1: Match on word boundaries and then try matching anywhere
+// 2: Match only on word boundaries (e.g., after / or .)
+pref("browser.urlbar.matchBehavior", 1);
pref("browser.urlbar.filter.javascript", true);
// the maximum number of results to show in autocomplete when doing richResults
@@ -632,7 +635,7 @@ pref("urlclassifier.gethashtables", "goog-phish-shavar,goog-malware-shavar");
pref("urlclassifier.confirm-age", 2700);
// URL for checking the reason for a malware warning.
-pref("browser.safebrowsing.malware.reportURL", "http://www.stopbadware.org/reports/container?source=@APP_UA_NAME@&version=@APP_VERSION@&reportname=");
+pref("browser.safebrowsing.malware.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
#endif
diff --git a/browser/base/content/browser-menubar.inc b/browser/base/content/browser-menubar.inc
index fe68132547c7..07795f184b7d 100644
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -131,7 +131,8 @@
accesskey="&deleteCmd.accesskey;"
command="cmd_delete"/>
-
diff --git a/browser/base/content/browser-sets.inc b/browser/base/content/browser-sets.inc
index 123c254a0642..1cd7744491f0 100644
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -294,9 +294,12 @@
command="viewHistorySidebar"/>
+
+
+
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
index a9d01403656d..16de01e1114b 100644
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -2324,11 +2324,14 @@ function BrowserOnCommand(event) {
// This is the "Why is this site blocked" button. For malware,
// we can fetch a site-specific report, for phishing, we redirect
// to the generic page describing phishing protection.
+ var formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"]
+ .getService(Components.interfaces.nsIURLFormatter);
+
if (/e=malwareBlocked/.test(errorDoc.documentURI)) {
// Get the stop badware "why is this blocked" report url,
// append the current url, and go there.
try {
- var reportURL = gPrefService.getCharPref("browser.safebrowsing.malware.reportURL");
+ var reportURL = formatter.formatURLPref("browser.safebrowsing.malware.reportURL");
reportURL += errorDoc.location.href;
content.location = reportURL;
} catch (e) {
@@ -2337,9 +2340,7 @@ function BrowserOnCommand(event) {
}
else if (/e=phishingBlocked/.test(errorDoc.documentURI)) {
try {
- content.location = Cc["@mozilla.org/toolkit/URLFormatterService;1"]
- .getService(Components.interfaces.nsIURLFormatter)
- .formatURLPref("browser.safebrowsing.warning.infoURL");
+ content.location = formatter.formatURLPref("browser.safebrowsing.warning.infoURL");
} catch (e) {
Components.utils.reportError("Couldn't get phishing info URL: " + e);
}
@@ -6562,7 +6563,9 @@ IdentityHandler.prototype = {
// for certs that are trusted because of a security exception.
var tooltip = this._stringBundle.getFormattedString("identity.identified.verifier",
[iData.caOrg]);
- if (this._overrideService.hasMatchingOverride(lookupHost, iData.cert, {}, {}))
+ if (this._overrideService.hasMatchingOverride(this._lastLocation.hostname,
+ this._lastLocation.port,
+ iData.cert, {}, {}))
tooltip = this._stringBundle.getString("identity.identified.verified_by_you");
}
else if (newMode == this.IDENTITY_MODE_IDENTIFIED) {
diff --git a/browser/base/content/browser.xul b/browser/base/content/browser.xul
index 86ecc03225a4..d6042ef92295 100644
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -191,7 +191,8 @@
+ onpopuphidden="focusAndSelectUrlBar();" norestorefocus="true"
+ chromedir="&locale.dir;">
@@ -237,7 +238,7 @@
-
diff --git a/browser/base/content/credits.xhtml b/browser/base/content/credits.xhtml
index e7b1a2f7f451..aabaeb73f7f5 100644
--- a/browser/base/content/credits.xhtml
+++ b/browser/base/content/credits.xhtml
@@ -217,12 +217,19 @@
Josh Aas
Robert Accettura
+
Ehsan Akhgari
+
Sean Alamares
+
Harvey Anderson
+
Smokey Ardisson
+
Rob Arnold
Tomoya Asai
Dietrich Ayala
Mitchell Baker
-
Adam Barea
+
Rhian Baker
+
Jan Bambas
Jason Barnabe
David Baron
+
Colin Barrett
Christopher Beard
Glen Beasley
Juan Becerra
@@ -231,185 +238,229 @@
Mic Berman
Uri Bernstein
Christian Biesinger
+
Al Billings
Seth Bindernagel
Chris Blizzard
Jamey Boje
Nelson Bolyard
+
Marco Bonardo
Carsten Book
Paul Booker
+
Dan Born
+
Ondřej Brablc
+
Catherine Brady
+
Dave Bragsalla
Igor Bukanov
Simon Bünzli
+
Lapo Calamandrei
+
Dave Camp
Rob Campbell
Regis Caspar
-
Marco Casteleijn
-
Biswatosh Chakraborty
+
Garrett Casto
Tony Chang
Wan-Teh Chang
+
Emily Chen
Ginn Chen
Pascal Chevrel
+
Tony Chung
Bob Clary
Wil Clouser
Mary Colvig
Majken Connor
Mike Connor
Chris Cooper
-
Michael Daumling
+
Brian Crowder
+
John Daggett
+
Michael Davis
Neil Deakin
-
Sherman Dickman
+
Julie Deroche
+
Justin Dolske
Stephen Donner
Asa Dotzler
-
Rafael Ebron
+
Chris Double
Brendan Eich
-
Ximon Eighteen
Kai Engert
Steve England
+
Madhava Enros
+
Eleka Etimad
+
Jason Evans
+
Alex Faaborg
+
Jane Finette
+
Mark Finkle
Darin Fisher
Jayson Fittipaldi
Justin Fitzhugh
Ryan Flint
-
Justin Frankel
-
Simon Fraser
+
Alix Franquet
Eli Friedman
-
Alex Fritze
-
Lisa Gansky
-
Mike Gao
Steven Garrity
-
Michael Glenn
-
Jay Goldman
-
Ben Goodger
+
Kevin Gerich
+
Taras Glek
+
Aravind Gottipati
Dão Gottwald
Zak Greant
-
Pam Greene
+
Matthew Gregan
Adam Guthrie
-
Vidar Haarr
Andrei Hajdukewycz
-
Mark Hammond
+
Trevor Hardcastle
Basil Hashem
Ian Hayward
+
Ben Hearsum
Axel Hecht
Frank Hecker
Robert Helmer
Jon Hicks
-
Ian Hickson
Graydon Hoare
Chris Hofmann
+
Timothy Hogan
+
Daniel Holbert
Mike Hommey
-
Joe Hughes
-
Ed Hume
-
Ivan Icin
+
Stephen Horlander
+
David Humphrey
+
Takeshi Ichimaru
+
Chris Ilias
+
Eri Inoue
Joichi Ito
+
Laurent Jouanneau
Gen Kanai
+
Masanori Kaneko
Blake Kaplan
Michael Kaply
Mitch Kapor
-
Peter Kasting
+
Kazuyoshi Kato
Alfred Kayser
Paul Kim
Masatoshi Kimura
Ria Klaassen
-
Andrea Knight
Marcia Knous
-
Dave Laundon
+
Gary Kwong
+
David Lanham
+
Edward Lee
Raymond Lee
+
Garrett LeSage
Aaron Leventhal
-
Mark Liddell
-
Dave Liebreich
Anne-Julie Ligneau
John Lilly
Zach Lipton
-
Nian Liu
+
Kai Liu
Reed Loden
+
Lars Lohn
Robert Longson
-
Scott MacGregor
+
Bob Lord
+
Phil Machalski
Ere Maijala
Gervase Markham
Sean Martell
+
Jim Mathies
Heather Meeker
Myk Melez
+
Federico Mena-Quintero
Mark Mentovai
-
Alex Menzies
Steven Michaud
+
Ted Mielczarek
Bernd Mielke
-
Joey Minta
+
Dave Miller
+
Dan Mills
+
Michael Monreal
Simon Montagu
Mike Morgan
-
Scooter Morris
+
Dan Mosedale
+
Michael Moy
Masayuki Nakano
Marria Nazif
-
Ian Neal
+
Kev Needham
Kaori Negoro
+
Johnathan Nightingale
+
Andreas Nilsson
Tristan Nitot
Alice Nodelman
+
Michal Novotny
Robert O'Callahan
+
John O'Duinn
+
Jan Odvárko
+
Tomoyuki Okazaki
+
Jeremy Orem
+
Hideo Oshima
Mats Palmgren
Stuart Parmenter
Jay Patel
-
Igor Pavlov
+
Chris Pearce
Javier Pedemonte
Alfred Peng
Christian Persch
+
Kalle Persson
+
Ulisse Perusin
Olli Pettay
-
Chase Phillips
Julien Pierre
-
Mark Pilgrim
-
Mike Pinkerton
Alex Polvi
Nickolay Ponomarev
+
Dan Portillo
Karen Prescott
-
Feng Qian
-
Robert Rainwater
-
Brian Rakowski
+
Florian Quèze
Neil Rashbrook
+
Bret Reckard
J. Paul Reed
Robert Relyea
+
John Resig
Deb Richardson
Tim Riley
Phil Ringnalda
+
Julien Rivaud
David Rolnitzky
Asaf Romano
-
Doron Rosenberg
-
Blake Ross
-
James Ross
Tim Rowley
-
Cameron Roy
Jesse Ruderman
Brian Ryner
Alexander Sack
Hideo Saito
+
Eiko Sakuma
Ken Saunders
Robert Sayre
-
Fritz Schneider
Mike Schroepfer
-
Phil Schwan
+
Kurt Schultz
Justin Scott
-
Chris Seawood
-
Leon Sha
+
Hiroshi Sekiya
+
Tara Shahian
+
Melissa Shapiro
Gavin Sharp
Mike Shaver
Eric Shepherd
-
Hiroshi Shimoda
+
Atsushi Shimono
Jungshik Shin
Jonas Sicking
+
Damon Sicore
Roger B. Sidje
+
Samuel Sidler
+
Henrik Skupin
+
John Slater
Benjamin Smedberg
-
Jon Smirl
+
Andrew Smith
+
Mark Smith
+
Window Snyder
Josh Soref
+
Ian Spence
Seth Spitzer
+
Markus Stange
+
Jakub Steiner
Johnny Stenback
-
Luke Stone
+
Brandon Sterne
Robert Strong
-
Annie Sullivan
-
Amir Szekely
-
Dave Townsend
+
Vicky Sun
+
Clint Talbert
+
David Tenser
Chris Thomas
+
Nick Thomas
+
Laura Thomson
+
Karl Tomlinson
+
Dave Townsend
Ben Turner
Doug Turner
Peter Van der Beken
Peter van der Woude
+
Teune van Steeg
+
Ryan VanderMeulen
Daniel Veditz
Michael Ventnor
-
Joost Verburg
-
Jorge Villalobos
Alexei Volkov
Vladimir Vukicevic
Håkan Waara
@@ -417,12 +468,19 @@
Tracy Walker
Martijn Wargers
Jonathan Watt
+
Frédéric Wenzel
Steffen Wilberg
-
Brett Wilson
+
Shawn Wilsher
+
Dan Witte
+
Steve Won
Michael Wu
+
Masahiro Yamada
Satoko Takita Yamaguchi (Chibi)
+
Christine Yen
Kohei Yoshino
+
Shigeru Yoshitake
Boris Zbarsky
+
Matthew Zeier
&credit.translation;
diff --git a/browser/base/content/downloadManagerOverlay.xul b/browser/base/content/downloadManagerOverlay.xul
index 9aeb9ce8f203..a882d0f26f5d 100644
--- a/browser/base/content/downloadManagerOverlay.xul
+++ b/browser/base/content/downloadManagerOverlay.xul
@@ -46,11 +46,16 @@
#include browserMountPoints.inc
diff --git a/browser/base/content/overrides/app-license.html b/browser/base/content/overrides/app-license.html
index 67e71a2a034d..0a66b44cd288 100644
--- a/browser/base/content/overrides/app-license.html
+++ b/browser/base/content/overrides/app-license.html
@@ -2,4 +2,4 @@
Mozilla Corporation
are made available under
the corresponding
- EULA.
+ EULA.
diff --git a/browser/base/content/test/Makefile.in b/browser/base/content/test/Makefile.in
index ada7d820781b..1624d1182014 100644
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -60,6 +60,11 @@ _BROWSER_FILES = browser_bug321000.js \
browser_getshortcutoruri.js \
$(NULL)
+ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
+_BROWSER_FILES += browser_customize.js \
+ $(NULL)
+endif
+
# disable tests on linux for now..
ifneq ($(OS_ARCH),Linux)
_BROWSER_FILES += \
diff --git a/browser/base/content/test/browser_customize.js b/browser/base/content/test/browser_customize.js
new file mode 100644
index 000000000000..13e3f510ff3e
--- /dev/null
+++ b/browser/base/content/test/browser_customize.js
@@ -0,0 +1,38 @@
+function test()
+{
+ waitForExplicitFinish();
+ var panel = document.getElementById("customizeToolbarSheetPopup");
+ panel.addEventListener("popupshown", testCustomizePopupShown, false);
+ document.getElementById("cmd_CustomizeToolbars").doCommand();
+}
+
+function testCustomizePopupShown()
+{
+ var panel = document.getElementById("customizeToolbarSheetPopup");
+ panel.removeEventListener("popupshown", testCustomizePopupShown, false);
+ panel.addEventListener("popuphidden", testCustomizePopupHidden, false);
+
+ var frame = document.getElementById("customizeToolbarSheetIFrame").contentDocument;
+ frame.addEventListener("load", testCustomizeFrameLoaded, true);
+}
+
+function testCustomizeFrameLoaded()
+{
+ var frame = document.getElementById("customizeToolbarSheetIFrame");
+ frame.removeEventListener("load", testCustomizeFrameLoaded, true);
+
+ var menu = document.getElementById("bookmarksMenuPopup");
+ ok("getResult" in menu, "menu has binding");
+
+ var framedoc = document.getElementById("customizeToolbarSheetIFrame").contentDocument;
+ var b = framedoc.getElementById("donebutton");
+
+ framedoc.getElementById("donebutton").doCommand();
+}
+
+function testCustomizePopupHidden()
+{
+ var panel = document.getElementById("customizeToolbarSheetPopup");
+ panel.removeEventListener("popuphidden", testCustomizePopupHidden, false);
+ finish();
+}
diff --git a/browser/base/content/utilityOverlay.js b/browser/base/content/utilityOverlay.js
index 82271b959cd1..5548ab4830ce 100644
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -204,12 +204,34 @@ function openUILinkIn( url, where, allowThirdPartyFixup, postData, referrerUrl )
saveURL(url, null, null, true, null, referrerUrl);
return;
}
+ const Cc = Components.classes;
+ const Ci = Components.interfaces;
var w = getTopWin();
if (!w || where == "window") {
- openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no", url,
- null, referrerUrl, postData, allowThirdPartyFixup);
+ var sa = Cc["@mozilla.org/supports-array;1"].
+ createInstance(Ci.nsISupportsArray);
+
+ var wuri = Cc["@mozilla.org/supports-string;1"].
+ createInstance(Ci.nsISupportsString);
+ wuri.data = url;
+
+ sa.AppendElement(wuri);
+ sa.AppendElement(null);
+ sa.AppendElement(referrerUrl);
+ sa.AppendElement(postData);
+ sa.AppendElement(allowThirdPartyFixup);
+
+ var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
+ getService(Ci.nsIWindowWatcher);
+
+ ww.openWindow(w || window,
+ getBrowserURL(),
+ null,
+ "chrome,dialog=no,all",
+ sa);
+
return;
}
diff --git a/browser/components/migration/src/nsSeamonkeyProfileMigrator.cpp b/browser/components/migration/src/nsSeamonkeyProfileMigrator.cpp
index cece72569cd4..78fb84be8eb6 100644
--- a/browser/components/migration/src/nsSeamonkeyProfileMigrator.cpp
+++ b/browser/components/migration/src/nsSeamonkeyProfileMigrator.cpp
@@ -50,6 +50,7 @@
#include "nsNetUtil.h"
#include "nsSeamonkeyProfileMigrator.h"
#include "nsVoidArray.h"
+#include "nsIProfileMigrator.h"
///////////////////////////////////////////////////////////////////////////////
// nsSeamonkeyProfileMigrator
@@ -103,6 +104,15 @@ nsSeamonkeyProfileMigrator::Migrate(PRUint16 aItems, nsIProfileStartup* aStartup
COPY_DATA(CopyHistory, aReplace, nsIBrowserProfileMigrator::HISTORY);
COPY_DATA(CopyPasswords, aReplace, nsIBrowserProfileMigrator::PASSWORDS);
COPY_DATA(CopyOtherData, aReplace, nsIBrowserProfileMigrator::OTHERDATA);
+
+ // Need to do startup before trying to copy bookmarks, since bookmarks
+ // import requires a profile. Can't do it earlier because services might
+ // end up creating the files we try to copy above.
+ if (aStartup) {
+ rv = aStartup->DoStartup();
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
COPY_DATA(CopyBookmarks, aReplace, nsIBrowserProfileMigrator::BOOKMARKS);
if (aReplace &&
@@ -724,10 +734,25 @@ nsresult
nsSeamonkeyProfileMigrator::CopyBookmarks(PRBool aReplace)
{
if (aReplace) {
+ // Initialize the default bookmarks
nsresult rv = InitializeBookmarks(mTargetProfile);
NS_ENSURE_SUCCESS(rv, rv);
- return CopyFile(FILE_NAME_BOOKMARKS, FILE_NAME_BOOKMARKS);
+
+ // Merge in the bookmarks from the source profile
+ nsCOMPtr sourceFile;
+ mSourceProfile->Clone(getter_AddRefs(sourceFile));
+ sourceFile->Append(FILE_NAME_BOOKMARKS);
+ rv = ImportBookmarksHTML(sourceFile, PR_TRUE, PR_FALSE, EmptyString().get());
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // we need to set this pref so that on startup
+ // we don't blow away what we just imported
+ nsCOMPtr pref(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return pref->SetBoolPref("browser.places.importBookmarksHTML", PR_FALSE);
}
+
return ImportNetscapeBookmarks(FILE_NAME_BOOKMARKS,
NS_LITERAL_STRING("sourceNameSeamonkey").get());
}
diff --git a/browser/components/nsBrowserGlue.js b/browser/components/nsBrowserGlue.js
index 3236dc1cc16d..0dc093d5e060 100644
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -467,12 +467,14 @@ BrowserGlue.prototype = {
var importer = Cc["@mozilla.org/browser/places/import-export-service;1"].
getService(Ci.nsIPlacesImportExportService);
importer.importHTMLFromFile(bookmarksFile, true /* overwrite existing */);
- } finally {
- prefBranch.setBoolPref("browser.places.importBookmarksHTML", false);
- if (restoreDefaultBookmarks)
- prefBranch.setBoolPref("browser.bookmarks.restore_default_bookmarks",
- false);
+ } catch (err) {
+ // Report the error, but ignore it.
+ Cu.reportError(err);
}
+ prefBranch.setBoolPref("browser.places.importBookmarksHTML", false);
+ if (restoreDefaultBookmarks)
+ prefBranch.setBoolPref("browser.bookmarks.restore_default_bookmarks",
+ false);
}
}
diff --git a/browser/components/places/content/bookmarkProperties.js b/browser/components/places/content/bookmarkProperties.js
index 62c8a67addfd..48e354e899fd 100755
--- a/browser/components/places/content/bookmarkProperties.js
+++ b/browser/components/places/content/bookmarkProperties.js
@@ -22,6 +22,7 @@
* Joe Hughes
* Dietrich Ayala
* Asaf Romano
+ * Marco Bonardo
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -70,9 +71,9 @@
* - "edit" - for editing a bookmark item or a folder.
* @ type (String). Possible values:
* - "bookmark"
- * @ bookmarkId (Integer) - the id of the bookmark item.
+ * @ itemId (Integer) - the id of the bookmark item.
* - "folder" (also applies to livemarks)
- * @ folderId (Integer) - the id of the folder.
+ * @ itemId (Integer) - the id of the folder.
* @ hiddenRows (Strings array) - optional, list of rows to be hidden
* regardless of the item edited or added by the dialog.
* Possible values:
@@ -80,7 +81,7 @@
* - "location"
* - "description"
* - "keyword"
- * - "load in sidebar"
+ * - "loadInSidebar"
* - "feedURI"
* - "siteURI"
* - "folder picker" - hides both the tree and the menu.
@@ -115,9 +116,8 @@ var BookmarkPropertiesPanel = {
_action: null,
_itemType: null,
- _folderId: null,
- _bookmarkId: -1,
- _bookmarkURI: null,
+ _itemId: -1,
+ _uri: null,
_loadBookmarkInSidebar: false,
_itemTitle: "",
_itemDescription: "",
@@ -201,14 +201,14 @@ var BookmarkPropertiesPanel = {
if ("uri" in dialogInfo) {
NS_ASSERT(dialogInfo.uri instanceof Ci.nsIURI,
"uri property should be a uri object");
- this._bookmarkURI = dialogInfo.uri;
+ this._uri = dialogInfo.uri;
}
if (typeof(this._itemTitle) != "string") {
- if (this._bookmarkURI) {
+ if (this._uri) {
this._itemTitle =
- this._getURITitleFromHistory(this._bookmarkURI);
+ this._getURITitleFromHistory(this._uri);
if (!this._itemTitle)
- this._itemTitle = this._bookmarkURI.spec;
+ this._itemTitle = this._uri.spec;
}
else
this._itemTitle = this._strings.getString("newBookmarkDefault");
@@ -268,47 +268,45 @@ var BookmarkPropertiesPanel = {
switch (dialogInfo.type) {
case "bookmark":
- NS_ASSERT("bookmarkId" in dialogInfo);
+ NS_ASSERT("itemId" in dialogInfo);
this._action = ACTION_EDIT;
this._itemType = BOOKMARK_ITEM;
- this._bookmarkId = dialogInfo.bookmarkId;
+ this._itemId = dialogInfo.itemId;
- this._bookmarkURI = bookmarks.getBookmarkURI(this._bookmarkId);
- this._itemTitle = bookmarks.getItemTitle(this._bookmarkId);
+ this._uri = bookmarks.getBookmarkURI(this._itemId);
+ this._itemTitle = bookmarks.getItemTitle(this._itemId);
// keyword
this._bookmarkKeyword =
- bookmarks.getKeywordForBookmark(this._bookmarkId);
+ bookmarks.getKeywordForBookmark(this._itemId);
// Load In Sidebar
this._loadBookmarkInSidebar =
- annos.itemHasAnnotation(this._bookmarkId, LOAD_IN_SIDEBAR_ANNO);
+ annos.itemHasAnnotation(this._itemId, LOAD_IN_SIDEBAR_ANNO);
break;
case "folder":
- NS_ASSERT("folderId" in dialogInfo);
+ NS_ASSERT("itemId" in dialogInfo);
this._action = ACTION_EDIT;
- this._folderId = dialogInfo.folderId;
+ this._itemId = dialogInfo.itemId;
const livemarks = PlacesUtils.livemarks;
- if (livemarks.isLivemark(this._folderId)) {
+ if (livemarks.isLivemark(this._itemId)) {
this._itemType = LIVEMARK_CONTAINER;
- this._feedURI = livemarks.getFeedURI(this._folderId);
- this._siteURI = livemarks.getSiteURI(this._folderId);
+ this._feedURI = livemarks.getFeedURI(this._itemId);
+ this._siteURI = livemarks.getSiteURI(this._itemId);
}
else
this._itemType = BOOKMARK_FOLDER;
- this._itemTitle = bookmarks.getItemTitle(this._folderId);
+ this._itemTitle = bookmarks.getItemTitle(this._itemId);
break;
}
// Description
- // XXXmano: unify the two id fields
- var itemId = dialogInfo.type == "bookmark" ? this._bookmarkId : this._folderId;
- if (annos.itemHasAnnotation(itemId, DESCRIPTION_ANNO)) {
- this._itemDescription = annos.getItemAnnotation(itemId,
+ if (annos.itemHasAnnotation(this._itemId, DESCRIPTION_ANNO)) {
+ this._itemDescription = annos.getItemAnnotation(this._itemId,
DESCRIPTION_ANNO);
}
}
@@ -339,7 +337,6 @@ var BookmarkPropertiesPanel = {
onDialogLoad: function BPP_onDialogLoad() {
this._determineItemInfo();
this._populateProperties();
- this._forceHideRows();
this.validateChanges();
this._folderMenuList = this._element("folderMenuList");
@@ -453,30 +450,34 @@ var BookmarkPropertiesPanel = {
},
/**
- * Hides fields which were explicitly set hidden by the the dialog opener
- * (see documentation at the top of this file).
+ * Show or hides fields based on item type.
*/
- _forceHideRows: function BPP__forceHideRows() {
- var hiddenRows = window.arguments[0].hiddenRows;
- if (!hiddenRows)
- return;
+ _showHideRows: function BPP__showHideRows() {
+ var hiddenRows = window.arguments[0].hiddenRows || new Array();
- if (hiddenRows.indexOf("title") != -1)
- this._element("namePicker").hidden = true;
- if (hiddenRows.indexOf("location") != -1)
- this._element("locationRow").hidden = true;
- if (hiddenRows.indexOf("keyword") != -1)
- this._element("keywordRow").hidden = true;
- if (hiddenRows.indexOf("description")!= -1)
- this._element("descriptionRow").hidden = true;
- if (hiddenRows.indexOf("folder picker") != -1)
- this._element("folderRow").hidden = true;
- if (hiddenRows.indexOf("feedURI") != -1)
- this._element("livemarkFeedLocationRow").hidden = true;
- if (hiddenRows.indexOf("siteURI") != -1)
- this._element("livemarkSiteLocationRow").hidden = true;
- if (hiddenRows.indexOf("load in sidebar") != -1)
- this._element("loadInSidebarCheckbox").hidden = true;
+ var isBookmark = this._itemType == BOOKMARK_ITEM;
+ var isLivemark = this._itemType == LIVEMARK_CONTAINER;
+
+ var isQuery = false;
+ if (this._uri)
+ isQuery = this._uri.schemeIs("place");
+
+ this._element("namePicker").hidden =
+ hiddenRows.indexOf("title") != -1;
+ this._element("locationRow").hidden =
+ hiddenRows.indexOf("location") != -1 || isQuery || !isBookmark;
+ this._element("keywordRow").hidden =
+ hiddenRows.indexOf("location") != -1 || isQuery || !isBookmark;
+ this._element("descriptionRow").hidden =
+ hiddenRows.indexOf("description")!= -1
+ this._element("folderRow").hidden =
+ hiddenRows.indexOf("folder picker") != -1 || this._action == ACTION_EDIT;
+ this._element("livemarkFeedLocationRow").hidden =
+ hiddenRows.indexOf("feedURI") != -1 || !isLivemark;
+ this._element("livemarkSiteLocationRow").hidden =
+ hiddenRows.indexOf("siteURI") != -1 || !isLivemark;
+ this._element("loadInSidebarCheckbox").hidden =
+ hiddenRows.indexOf("loadInSidebar") != -1 || isQuery || !isBookmark;
},
/**
@@ -490,8 +491,8 @@ var BookmarkPropertiesPanel = {
this._element("descriptionTextfield").value = this._itemDescription;
if (this._itemType == BOOKMARK_ITEM) {
- if (this._bookmarkURI)
- this._element("editURLBar").value = this._bookmarkURI.spec;
+ if (this._uri)
+ this._element("editURLBar").value = this._uri.spec;
if (typeof(this._bookmarkKeyword) == "string")
this._element("keywordTextfield").value = this._bookmarkKeyword;
@@ -499,11 +500,6 @@ var BookmarkPropertiesPanel = {
if (this._loadBookmarkInSidebar)
this._element("loadInSidebarCheckbox").checked = true;
}
- else {
- this._element("locationRow").hidden = true;
- this._element("keywordRow").hidden = true;
- this._element("loadInSidebarCheckbox").hidden = true;
- }
if (this._itemType == LIVEMARK_CONTAINER) {
if (this._feedURI)
@@ -511,13 +507,8 @@ var BookmarkPropertiesPanel = {
if (this._siteURI)
this._element("feedSiteLocationTextfield").value = this._siteURI.spec;
}
- else {
- this._element("livemarkFeedLocationRow").hidden = true;
- this._element("livemarkSiteLocationRow").hidden = true;
- }
- if (this._action == ACTION_EDIT)
- this._element("folderRow").hidden = true;
+ this._showHideRows();
},
_createMicrosummaryMenuItem:
@@ -554,15 +545,15 @@ var BookmarkPropertiesPanel = {
var namePicker = this._element("namePicker");
const annos = PlacesUtils.annotations;
- if (annos.itemHasAnnotation(this._bookmarkId, STATIC_TITLE_ANNO)) {
- userEnteredNameField.label = annos.getItemAnnotation(this._bookmarkId,
+ if (annos.itemHasAnnotation(this._itemId, STATIC_TITLE_ANNO)) {
+ userEnteredNameField.label = annos.getItemAnnotation(this._itemId,
STATIC_TITLE_ANNO);
}
else
userEnteredNameField.label = this._itemTitle;
// Non-bookmark items always use the item-title itself
- if (this._itemType != BOOKMARK_ITEM || !this._bookmarkURI) {
+ if (this._itemType != BOOKMARK_ITEM || !this._uri) {
namePicker.selectedItem = userEnteredNameField;
return;
}
@@ -570,8 +561,8 @@ var BookmarkPropertiesPanel = {
var itemToSelect = userEnteredNameField;
try {
this._microsummaries =
- PlacesUIUtils.microsummaries.getMicrosummaries(this._bookmarkURI,
- this._bookmarkId);
+ PlacesUIUtils.microsummaries.getMicrosummaries(this._uri,
+ this._itemId);
}
catch(ex) {
// getMicrosummaries will throw an exception if the page to which the URI
@@ -594,7 +585,7 @@ var BookmarkPropertiesPanel = {
if (this._action == ACTION_EDIT &&
PlacesUIUtils.microsummaries
- .isMicrosummary(this._bookmarkId, microsummary))
+ .isMicrosummary(this._itemId, microsummary))
itemToSelect = menuItem;
menupopup.appendChild(menuItem);
@@ -800,11 +791,7 @@ var BookmarkPropertiesPanel = {
* was open.
*/
_saveChanges: function BPP__saveChanges() {
- var itemId;
- if (this._itemType == BOOKMARK_ITEM)
- itemId = this._bookmarkId;
- else
- itemId = this._folderId;
+ var itemId = this._itemId;
var transactions = [];
@@ -824,7 +811,7 @@ var BookmarkPropertiesPanel = {
if (this._itemType == BOOKMARK_ITEM) {
// location
var url = PlacesUIUtils.createFixedURI(this._element("editURLBar").value);
- if (!this._bookmarkURI.equals(url))
+ if (!this._uri.equals(url))
transactions.push(PlacesUIUtils.ptm.editBookmarkURI(itemId, url));
// keyword transactions
@@ -864,7 +851,7 @@ var BookmarkPropertiesPanel = {
var feedURI = PlacesUIUtils.createFixedURI(feedURIString);
if (!this._feedURI.equals(feedURI)) {
transactions.push(
- PlacesUIUtils.ptm.editLivemarkFeedURI(this._folderId, feedURI));
+ PlacesUIUtils.ptm.editLivemarkFeedURI(this._itemId, feedURI));
}
// Site Location is empty, we can set its URI to null
@@ -876,7 +863,7 @@ var BookmarkPropertiesPanel = {
if ((!newSiteURI && this._siteURI) ||
(newSiteURI && (!this._siteURI || !this._siteURI.equals(newSiteURI)))) {
transactions.push(
- PlacesUIUtils.ptm.editLivemarkSiteURI(this._folderId, newSiteURI));
+ PlacesUIUtils.ptm.editLivemarkSiteURI(this._itemId, newSiteURI));
}
}
@@ -940,7 +927,7 @@ var BookmarkPropertiesPanel = {
}
if (this._charSet)
- PlacesUtils.history.setCharsetForURI(this._bookmarkURI, this._charSet);
+ PlacesUtils.history.setCharsetForURI(this._uri, this._charSet);
var transactions = [PlacesUIUtils.ptm.createItem(uri, aContainer, aIndex,
title, keyword,
@@ -1111,14 +1098,8 @@ var BookmarkPropertiesPanel = {
if (!selectedNode)
return;
- var folderId = selectedNode.itemId;
- // Don't set the selected item if the static item for the folder is
- // already selected
- var oldSelectedItem = this._folderMenuList.selectedItem;
- if ((oldSelectedItem.id == "toolbarFolderItem" &&
- folderId == PlacesUtils.toolbarFolderId) ||
- (oldSelectedItem.id == "bookmarksRootItem" &&
- folderId == PlacesUtils.bookmarksMenuFolderId))
+ var folderId = PlacesUtils.getConcreteItemId(selectedNode);
+ if (this._getFolderIdFromMenuList() == folderId)
return;
var folderItem = this._getFolderMenuItem(folderId);
diff --git a/browser/components/places/content/controller.js b/browser/components/places/content/controller.js
index 8e955518452d..09a08dd1e2e4 100755
--- a/browser/components/places/content/controller.js
+++ b/browser/components/places/content/controller.js
@@ -77,16 +77,33 @@ const REMOVE_PAGES_MAX_SINGLEREMOVES = 10;
* is provided for informational purposes only!
* @param [optional] aIsTag
* Indicates if parent container is a tag
+ * @param [optional] aDropNearItemId
+ * When defined we will calculate index based on this itemId
* @constructor
*/
-function InsertionPoint(aItemId, aIndex, aOrientation, aIsTag) {
+function InsertionPoint(aItemId, aIndex, aOrientation, aIsTag,
+ aDropNearItemId) {
this.itemId = aItemId;
- this.index = aIndex;
+ this._index = aIndex;
this.orientation = aOrientation;
this.isTag = aIsTag;
+ this.dropNearItemId = aDropNearItemId;
}
-InsertionPoint.prototype.toString = function IP_toString() {
- return "[object InsertionPoint(folder:" + this.itemId + ",index:" + this.index + ",orientation:" + this.orientation + ",isTag:" + this.isTag + ")]";
+
+InsertionPoint.prototype = {
+ set index(val) {
+ return this._index = val;
+ },
+
+ get index() {
+ if (this.dropNearItemId > 0) {
+ // If dropNearItemId is set up we must calculate the real index of
+ // the item near which we will drop.
+ var index = PlacesUtils.bookmarks.getItemIndex(this.dropNearItemId);
+ return this.orientation == Ci.nsITreeView.DROP_BEFORE ? index : index + 1;
+ }
+ return this._index;
+ }
};
/**
@@ -147,6 +164,8 @@ PlacesController.prototype = {
var selectedNode = this._view.selectedNode;
if (selectedNode) {
if (PlacesUtils.nodeIsFolder(selectedNode) ||
+ (PlacesUtils.nodeIsQuery(selectedNode) &&
+ selectedNode.itemId != -1) ||
(PlacesUtils.nodeIsBookmark(selectedNode) &&
!PlacesUtils.nodeIsLivemarkItem(selectedNode)))
return true;
@@ -264,9 +283,9 @@ PlacesController.prototype = {
* is a policy decision that a removable item not be placed inside a non-
* removable item.
* @param aIsMoveCommand
- * True if thecommand for which this method is called only moves the
+ * True if the command for which this method is called only moves the
* selected items to another container, false otherwise.
- * @returns true if the there's a selection which has no nodes that cannot be removed,
+ * @returns true if all nodes in the selection can be removed,
* false otherwise.
*/
_hasRemovableSelection: function PC__hasRemovableSelection(aIsMoveCommand) {
@@ -278,17 +297,8 @@ PlacesController.prototype = {
if (nodes[i] == root)
return false;
- // Disallow removing shortcuts from the left pane
- var nodeItemId = nodes[i].itemId;
- if (PlacesUtils.annotations
- .itemHasAnnotation(nodeItemId, ORGANIZER_QUERY_ANNO))
- return false;
-
- // Disallow removing the toolbar, menu and unfiled-bookmarks folders
- if (!aIsMoveCommand &&
- (nodeItemId == PlacesUtils.toolbarFolderId ||
- nodeItemId == PlacesUtils.unfiledBookmarksFolderId ||
- nodeItemId == PlacesUtils.bookmarksMenuFolderId))
+ if (PlacesUtils.nodeIsFolder(nodes[i]) &&
+ !PlacesControllerDragHelper.canMoveContainerNode(nodes[i]))
return false;
// We don't call nodeIsReadOnly here, because nodeIsReadOnly means that
@@ -383,13 +393,13 @@ PlacesController.prototype = {
* "link" node is a URI
* "bookmark" node is a bookamrk
* "livemarkChild" node is a child of a livemark
+ * "tagChild" node is a child of a tag
* "folder" node is a folder
* "query" node is a query
* "dynamiccontainer" node is a dynamic container
* "separator" node is a separator line
* "host" node is a host
- * "mutable" node can have items inserted or reordered
- *
+ *
* @returns an array of objects corresponding the selected nodes. Each
* object has each of the properties above set if its corresponding
* node matches the rule. In addition, the annotations names for each
@@ -446,25 +456,22 @@ PlacesController.prototype = {
uri = PlacesUtils._uri(node.uri);
if (PlacesUtils.nodeIsBookmark(node)) {
nodeData["bookmark"] = true;
+ PlacesUtils.nodeIsTagQuery(node.parent)
var mss = PlacesUIUtils.microsummaries;
if (mss.hasMicrosummary(node.itemId))
nodeData["microsummary"] = true;
- else if (node.parent &&
- PlacesUtils.nodeIsLivemarkContainer(node.parent))
- nodeData["livemarkChild"] = true;
+
+ var parentNode = node.parent;
+ if (parentNode) {
+ if (PlacesUtils.nodeIsTagQuery(parentNode))
+ nodeData["tagChild"] = true;
+ else if (PlacesUtils.nodeIsLivemarkContainer(parentNode))
+ nodeData["livemarkChild"] = true;
+ }
}
break;
}
- // Mutability is whether or not a container can have selected items
- // inserted or reordered. It does _not_ dictate whether or not the
- // container can have items removed from it, since some containers that
- // aren't reorderable can have items removed from them, e.g. a history
- // list.
- if (!PlacesUtils.nodeIsReadOnly(node) &&
- !PlacesUtils.isReadonlyFolder(node.parent || root))
- nodeData["mutable"] = true;
-
// annotations
if (uri) {
var names = PlacesUtils.annotations.getPageAnnotationNames(uri, {});
@@ -509,8 +516,12 @@ PlacesController.prototype = {
}
}
- if (aMenuItem.hasAttribute("selection")) {
- var showRules = aMenuItem.getAttribute("selection").split("|");
+ var selectionAttr = aMenuItem.getAttribute("selection");
+ if (selectionAttr) {
+ if (selectionAttr == "any")
+ return true;
+
+ var showRules = selectionAttr.split("|");
var anyMatched = false;
function metaDataNodeMatches(metaDataNode, rules) {
for (var i=0; i < rules.length; i++) {
@@ -553,9 +564,11 @@ PlacesController.prototype = {
* selection attribute. A menu-item would be hidden if at least one of the
* given rules apply to one of the selected nodes. The rules should be
* separated with the | character.
- * 5) The visibility state of a menu-item is unchanged if none of these
+ * 5) The "hideifnoinsetionpoint" attribute may be set on a menu-item to
+ * true if it should be hidden when there's no insertion point
+ * 6) The visibility state of a menu-item is unchanged if none of these
* attribute are set.
- * 6) These attributes should not be set on separators for which the
+ * 7) These attributes should not be set on separators for which the
* visibility state is "auto-detected."
* @param aPopup
* The menupopup to build children into.
@@ -563,6 +576,8 @@ PlacesController.prototype = {
*/
buildContextMenu: function PC_buildContextMenu(aPopup) {
var metadata = this._buildSelectionMetadata();
+ var ip = this._view.insertionPoint;
+ var noIp = !ip || ip.isTag;
var separator = null;
var visibleItemsBeforeSep = false;
@@ -570,7 +585,9 @@ PlacesController.prototype = {
for (var i = 0; i < aPopup.childNodes.length; ++i) {
var item = aPopup.childNodes[i];
if (item.localName != "menuseparator") {
- item.hidden = !this._shouldShowMenuItem(item, metadata);
+ item.hidden = (item.getAttribute("hideifnoinsetionpoint") == "true" && noIp) ||
+ !this._shouldShowMenuItem(item, metadata);
+
if (!item.hidden) {
visibleItemsBeforeSep = true;
anyVisible = true;
@@ -631,9 +648,10 @@ PlacesController.prototype = {
return;
if (PlacesUtils.nodeIsFolder(node))
- PlacesUIUtils.showFolderProperties(node.itemId);
- else if (PlacesUtils.nodeIsBookmark(node))
- PlacesUIUtils.showBookmarkProperties(node.itemId);
+ PlacesUIUtils.showItemProperties(node.itemId, "folder");
+ else if (PlacesUtils.nodeIsBookmark(node) ||
+ PlacesUtils.nodeIsQuery(node))
+ PlacesUIUtils.showItemProperties(node.itemId, "bookmark");
},
/**
@@ -866,6 +884,15 @@ PlacesController.prototype = {
transactions.push(PlacesUIUtils.ptm.untagURI(uri, [tagItemId]));
continue;
}
+ else if (PlacesUtils.nodeIsQuery(node.parent) &&
+ asQuery(node.parent).queryOptions.queryType ==
+ Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY &&
+ node.uri) {
+ // remove page from history, history deletes are not undoable
+ var bhist = PlacesUtils.history.QueryInterface(Ci.nsIBrowserHistory);
+ bhist.removePage(PlacesUtils._uri(node.uri));
+ continue;
+ }
transactions.push(PlacesUIUtils.ptm.removeItem(node.itemId));
}
@@ -990,6 +1017,7 @@ PlacesController.prototype = {
* elsewhere.
*/
getTransferData: function PC_getTransferData(dragAction) {
+ var copy = dragAction == Ci.nsIDragService.DRAGDROP_ACTION_COPY;
var result = this._view.getResult();
var oldViewer = result.viewer;
try {
@@ -1009,7 +1037,7 @@ PlacesController.prototype = {
var data = new TransferData();
function addData(type, overrideURI) {
data.addDataForFlavour(type, PlacesUIUtils._wrapString(
- PlacesUtils.wrapNode(node, type, overrideURI)));
+ PlacesUtils.wrapNode(node, type, overrideURI, copy)));
}
function addURIData(overrideURI) {
@@ -1077,7 +1105,8 @@ PlacesController.prototype = {
uri) + suffix);
var placeSuffix = i < (nodes.length - 1) ? "," : "";
- return PlacesUtils.wrapNode(node, type, overrideURI) + placeSuffix;
+ var resolveShortcuts = !PlacesControllerDragHelper.canMoveContainerNode(node);
+ return PlacesUtils.wrapNode(node, type, overrideURI, resolveShortcuts) + placeSuffix;
}
// all items wrapped as TYPE_X_MOZ_PLACE
@@ -1241,7 +1270,7 @@ var PlacesControllerDragHelper = {
/**
* @returns The current active drag session. Returns null if there is none.
*/
- getSession: function VO__getSession() {
+ getSession: function PCDH__getSession() {
var dragService = Cc["@mozilla.org/widget/dragservice;1"].
getService(Ci.nsIDragService);
return dragService.getCurrentSession();
@@ -1301,6 +1330,71 @@ var PlacesControllerDragHelper = {
return true;
},
+ /**
+ * Determines if a container node can be moved.
+ *
+ * @param aNode
+ * A bookmark folder node.
+ * @param [optional] aInsertionPoint
+ * The insertion point of the drop target.
+ * @returns True if the container can be moved.
+ */
+ canMoveContainerNode:
+ function PCDH_canMoveContainerNode(aNode, aInsertionPoint) {
+ // can't move query root
+ if (!aNode.parent)
+ return false;
+
+ var targetId = aInsertionPoint ? aInsertionPoint.itemId : -1;
+ var parentId = PlacesUtils.getConcreteItemId(aNode.parent);
+ var concreteId = PlacesUtils.getConcreteItemId(aNode);
+
+ // can't move tag containers
+ if (PlacesUtils.nodeIsTagQuery(aNode))
+ return false;
+
+ // check is child of a read-only container
+ if (PlacesUtils.nodeIsReadOnly(aNode.parent))
+ return false;
+
+ // check for special folders, etc
+ if (!this.canMoveContainer(aNode.itemId, parentId))
+ return false;
+
+ return true;
+ },
+
+ /**
+ * Determines if a container node can be moved.
+ *
+ * @param aId
+ * A bookmark folder id.
+ * @param [optional] aParentId
+ * The parent id of the folder.
+ * @returns True if the container can be moved to the target.
+ */
+ canMoveContainer:
+ function PCDH_canMoveContainer(aId, aParentId) {
+ if (aId == -1)
+ return false;
+
+ // Disallow moving of roots and special folders
+ const ROOTS = [PlacesUtils.placesRootId, PlacesUtils.bookmarksMenuFolderId,
+ PlacesUtils.tagsFolderId, PlacesUtils.unfiledBookmarksFolderId,
+ PlacesUtils.toolbarFolderId];
+ if (ROOTS.indexOf(aId) != -1)
+ return false;
+
+ // Get parent id if necessary
+ if (aParentId == null || aParentId == -1)
+ aParentId = PlacesUtils.bookmarks.getFolderIdForItem(aId);
+
+ if(PlacesUtils.bookmarks.getFolderReadonly(aParentId))
+ return false;
+
+ return true;
+ },
+
/**
* Creates a Transferable object that can be filled with data of types
* supported by a view.
@@ -1327,6 +1421,8 @@ var PlacesControllerDragHelper = {
*/
onDrop: function PCDH_onDrop(insertionPoint) {
var session = this.getSession();
+ // XXX dragAction is not valid, so we also set copy below by checking
+ // whether the dropped item is moveable, before creating the transaction
var copy = session.dragAction & Ci.nsIDragService.DRAGDROP_ACTION_COPY;
var transactions = [];
var xferable = this._initTransferable(session);
@@ -1344,13 +1440,13 @@ var PlacesControllerDragHelper = {
// There's only ever one in the D&D case.
var unwrapped = PlacesUtils.unwrapNodes(data.value.data,
flavor.value)[0];
+
var index = insertionPoint.index;
// Adjust insertion index to prevent reversal of dragged items. When you
// drag multiple elts upward: need to increment index or each successive
// elt will be inserted at the same index, each above the previous.
- if ((index != -1) && ((index < unwrapped.index) ||
- (unwrapped.folder && (index < unwrapped.folder.index)))) {
+ if (index != -1 && index < unwrapped.index) {
index = index + movedCount;
movedCount++;
}
@@ -1362,6 +1458,12 @@ var PlacesControllerDragHelper = {
transactions.push(PlacesUIUtils.ptm.tagURI(uri,[tagItemId]));
}
else {
+ if (unwrapped.id && !this.canMoveContainer(unwrapped.id, null))
+ copy = true;
+ else if (unwrapped.concreteId &&
+ !this.canMoveContainer(unwrapped.concreteId, null))
+ copy = true;
+
transactions.push(PlacesUIUtils.makeTransaction(unwrapped,
flavor.value, insertionPoint.itemId,
index, copy));
diff --git a/browser/components/places/content/editBookmarkOverlay.js b/browser/components/places/content/editBookmarkOverlay.js
index 888839872a3b..b0d55687c64f 100644
--- a/browser/components/places/content/editBookmarkOverlay.js
+++ b/browser/components/places/content/editBookmarkOverlay.js
@@ -67,21 +67,25 @@ var gEditItemOverlay = {
},
_showHideRows: function EIO__showHideRows() {
- var isBookmark = this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK;
+ var isBookmark = this._itemId != -1 &&
+ this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK;
+ var isQuery = false;
+ if (this._uri)
+ isQuery = this._uri.schemeIs("place");
this._element("nameRow").collapsed = this._hiddenRows.indexOf("name") != -1;
this._element("folderRow").collapsed =
- this._hiddenRows.indexOf("folderPicker") != -1;
- this._element("tagsRow").collapsed = !isBookmark ||
- this._hiddenRows.indexOf("tags") != -1;
+ this._hiddenRows.indexOf("folderPicker") != -1 || this._readOnly;
+
+ this._element("tagsRow").collapsed = !this._uri ||
+ this._hiddenRows.indexOf("tags") != -1 || isQuery;
this._element("descriptionRow").collapsed =
- this._hiddenRows.indexOf("description") != -1 ||
- this._readOnly;
+ this._hiddenRows.indexOf("description") != -1 || this._readOnly;
this._element("keywordRow").collapsed = !isBookmark || this._readOnly ||
- this._hiddenRows.indexOf("keyword") != -1;
- this._element("locationRow").collapsed = !isBookmark ||
+ this._hiddenRows.indexOf("keyword") != -1 || isQuery;
+ this._element("locationRow").collapsed = !isBookmark || isQuery ||
this._hiddenRows.indexOf("location") != -1;
- this._element("loadInSidebarCheckbox").collapsed = !isBookmark ||
+ this._element("loadInSidebarCheckbox").collapsed = !isBookmark || isQuery ||
this._readOnly || this._hiddenRows.indexOf("loadInSidebar") != -1;
this._element("feedLocationRow").collapsed = !this._isLivemark ||
this._hiddenRows.indexOf("feedLocation") != -1;
@@ -91,8 +95,10 @@ var gEditItemOverlay = {
/**
* Initialize the panel
- * @param aItemId
- * a places-itemId of a bookmark, folder or a live bookmark.
+ * @param aFor
+ * Either a places-itemId (of a bookmark, folder or a live bookmark),
+ * or a URI object (in which case, the panel would be initialized in
+ * read-only mode).
* @param [optional] aInfo
* JS object which stores additional info for the panel
* initialization. The following properties may bet set:
@@ -103,21 +109,57 @@ var gEditItemOverlay = {
* * forceReadOnly - set this flag to initialize the panel to its
* read-only (view) mode even if the given item is editable.
*/
- initPanel: function EIO_initPanel(aItemId, aInfo) {
- const bms = PlacesUtils.bookmarks;
-
+ initPanel: function EIO_initPanel(aFor, aInfo) {
this._folderMenuList = this._element("folderMenuList");
this._folderTree = this._element("folderTree");
- this._itemId = aItemId;
- this._itemType = bms.getItemType(this._itemId);
- this._determineInfo(aInfo);
- var container = bms.getFolderIdForItem(this._itemId);
- if (this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK) {
- this._uri = bms.getBookmarkURI(this._itemId);
+ this._determineInfo(aInfo);
+ if (aFor instanceof Ci.nsIURI) {
+ this._itemId = -1;
+ this._uri = aFor;
+ this._readOnly = true;
+ }
+ else {
+ this._itemId = aFor;
+ var container = PlacesUtils.bookmarks.getFolderIdForItem(this._itemId);
+ this._itemType = PlacesUtils.bookmarks.getItemType(this._itemId);
+ if (this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK) {
+ this._uri = PlacesUtils.bookmarks.getBookmarkURI(this._itemId);
+ if (!this._readOnly) // If readOnly wasn't forced through aInfo
+ this._readOnly = PlacesUtils.livemarks.isLivemark(container);
+ this._initTextField("keywordField",
+ PlacesUtils.bookmarks
+ .getKeywordForBookmark(this._itemId));
+ // Load In Sidebar checkbox
+ this._element("loadInSidebarCheckbox").checked =
+ PlacesUtils.annotations.itemHasAnnotation(this._itemId,
+ LOAD_IN_SIDEBAR_ANNO);
+ }
+ else {
+ if (!this._readOnly) // If readOnly wasn't forced through aInfo
+ this._readOnly = false;
+
+ this._uri = null;
+ this._isLivemark = PlacesUtils.livemarks.isLivemark(this._itemId);
+ if (this._isLivemark) {
+ var feedURI = PlacesUtils.livemarks.getFeedURI(this._itemId);
+ var siteURI = PlacesUtils.livemarks.getSiteURI(this._itemId);
+ this._initTextField("feedLocationField", feedURI.spec);
+ this._initTextField("siteLocationField", siteURI ? siteURI.spec : "");
+ }
+ }
+
+ // folder picker
+ this._initFolderMenuList(container);
+
+ // description field
+ this._initTextField("descriptionField",
+ PlacesUIUtils.getItemDescription(this._itemId));
+ }
+
+ if (this._itemId == -1 ||
+ this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK) {
this._isLivemark = false;
- if (!this._readOnly) // If readOnly wasn't forced through aInfo
- this._readOnly = PlacesUtils.livemarks.isLivemark(container);
this._initTextField("locationField", this._uri.spec);
this._initTextField("tagsField",
@@ -127,43 +169,17 @@ var gEditItemOverlay = {
// tags selector
this._rebuildTagsSelectorList();
-
- this._initTextField("keywordField",
- bms.getKeywordForBookmark(this._itemId));
-
- // Load In Sidebar checkbox
- this._element("loadInSidebarCheckbox").checked =
- PlacesUtils.annotations.itemHasAnnotation(this._itemId,
- LOAD_IN_SIDEBAR_ANNO);
}
- else {
- if (!this._readOnly) // If readOnly wasn't forced through aInfo
- this._readOnly = false;
- this._isLivemark = PlacesUtils.livemarks.isLivemark(this._itemId);
- if (this._isLivemark) {
- var feedURI = PlacesUtils.livemarks.getFeedURI(this._itemId);
- var siteURI = PlacesUtils.livemarks.getSiteURI(this._itemId);
- this._initTextField("feedLocationField", feedURI.spec);
- this._initTextField("siteLocationField", siteURI ? siteURI.spec : "");
- }
- this._uri = null;
- }
-
- // folder picker
- this._initFolderMenuList(container);
// name picker
this._initNamePicker();
-
- // description field
- this._initTextField("descriptionField",
- PlacesUIUtils.getItemDescription(this._itemId));
this._showHideRows();
// observe changes
if (!this._observersAdded) {
- PlacesUtils.bookmarks.addObserver(this, false);
+ if (this._itemId != -1)
+ PlacesUtils.bookmarks.addObserver(this, false);
window.addEventListener("unload", this, false);
this._observersAdded = true;
}
@@ -309,13 +325,14 @@ var gEditItemOverlay = {
},
_getItemStaticTitle: function EIO__getItemStaticTitle() {
+ if (this._itemId == -1)
+ return PlacesUtils.history.getPageTitle(this._uri);
+
const annos = PlacesUtils.annotations;
if (annos.itemHasAnnotation(this._itemId, STATIC_TITLE_ANNO))
return annos.getItemAnnotation(this._itemId, STATIC_TITLE_ANNO);
- var title = PlacesUtils.bookmarks.getItemTitle(this._itemId);
- if (title === null)
- return PlacesUtils.history.getPageTitle(this._uri);
- return title;
+
+ return PlacesUtils.bookmarks.getItemTitle(this._itemId);
},
_initNamePicker: function EIO_initNamePicker() {
@@ -337,7 +354,8 @@ var gEditItemOverlay = {
var itemToSelect = userEnteredNameField;
try {
- if (this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK &&
+ if (this._itemId != -1 &&
+ this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK &&
!this._readOnly)
this._microsummaries = PlacesUIUtils.microsummaries
.getMicrosummaries(this._uri, -1);
@@ -433,7 +451,9 @@ var gEditItemOverlay = {
}
if (this._observersAdded) {
- PlacesUtils.bookmarks.removeObserver(this);
+ if (this._itemId != -1)
+ PlacesUtils.bookmarks.removeObserver(this);
+
this._observersAdded = false;
}
if (this._microsummaries) {
@@ -441,6 +461,7 @@ var gEditItemOverlay = {
this._microsummaries = null;
}
this._itemId = -1;
+ this._uri = null;
},
onTagsFieldBlur: function EIO_onTagsFieldBlur() {
diff --git a/browser/components/places/content/history-panel.js b/browser/components/places/content/history-panel.js
index 6c6d631b776f..6742cebcc17b 100644
--- a/browser/components/places/content/history-panel.js
+++ b/browser/components/places/content/history-panel.js
@@ -68,20 +68,6 @@ function HistorySidebarInit()
}
function initContextMenu() {
- // Force-hide items in the context menu which never apply to this view
- var alwaysHideElements = ["placesContext_new:bookmark",
- "placesContext_new:folder",
- "placesContext_new:separator",
- "placesContext_cut",
- "placesContext_paste",
- "placesContext_sortBy:name"];
- for (var i=0; i < alwaysHideElements.length; i++) {
- var elt = document.getElementById(alwaysHideElements[i]);
- elt.removeAttribute("selection");
- elt.removeAttribute("forcehideselection");
- elt.hidden = true;
- }
-
// Insert "Bookmark This Link" right before the copy item
document.getElementById("placesContext")
.insertBefore(document.getElementById("addBookmarkContextItem"),
diff --git a/browser/components/places/content/menu.xml b/browser/components/places/content/menu.xml
index 90167a07bcfb..e6f9f56cbec6 100755
--- a/browser/components/places/content/menu.xml
+++ b/browser/components/places/content/menu.xml
@@ -147,7 +147,7 @@
newMarginTop = scrollBoxObject.height;
// set the new marginTop based on arrowscrollbox
- newMarginTop += scrollBoxObject.y - this.boxObject.y;
+ newMarginTop += scrollBoxObject.y - this._scrollBox.boxObject.y;
this._indicatorBar.firstChild.style.marginTop = newMarginTop + "px";
this._indicatorBar.hidden = false;
]]>
diff --git a/browser/components/places/content/places.js b/browser/components/places/content/places.js
index 1d5e9fe6df84..59bfcaaef915 100755
--- a/browser/components/places/content/places.js
+++ b/browser/components/places/content/places.js
@@ -104,6 +104,10 @@ var PlacesOrganizer = {
var historyMenuForward = document.getElementById("historyMenuForward");
historyMenuForward.removeAttribute("key");
#endif
+
+ // remove the "Properties" context-menu item, we've our own details pane
+ document.getElementById("placesContext")
+ .removeChild(document.getElementById("placesContext_show:info"));
},
QueryInterface: function PO_QueryInterface(aIID) {
@@ -208,13 +212,15 @@ var PlacesOrganizer = {
options.excludeItems = false;
var placeURI = PlacesUtils.history.queriesToQueryString(queries, queries.length, options);
- // update the right-pane contents
- if (this._content.place != placeURI)
+ // Update the right-pane contents.
+ // We must update also if the user clears the search box, in that case
+ // we are called with resetSearchBox == false.
+ if (this._content.place != placeURI || !resetSearchBox) {
this._content.place = placeURI;
- // This just updates the back/forward buttons, it doesn't call us back
- // because node.uri is our current selection.
- this.location = node.uri;
+ // Update the back/forward buttons.
+ this.location = node.uri;
+ }
// Make sure the search UI is hidden.
PlacesSearchBox.hideSearchUI();
@@ -224,6 +230,7 @@ var PlacesOrganizer = {
}
this._setSearchScopeForNode(node);
+ this._fillDetailsPane(node);
},
/**
@@ -305,6 +312,18 @@ var PlacesOrganizer = {
}
},
+ /**
+ * Handle focus changes on the trees.
+ * When moving focus between panes we should update the details pane contents.
+ * @param aEvent
+ * The mouse event.
+ */
+ onTreeFocus: function PO_onTreeFocus(aEvent) {
+ var currentView = aEvent.currentTarget;
+ var selectedNode = currentView.selectedNode;
+ this._fillDetailsPane(selectedNode);
+ },
+
openFlatContainer: function PO_openFlatContainerFlatContainer(aContainer) {
if (aContainer.itemId != -1)
this._places.selectItems([aContainer.itemId]);
@@ -572,9 +591,10 @@ var PlacesOrganizer = {
*/
var infoBox = document.getElementById("infoBox");
var infoBoxExpander = document.getElementById("infoBoxExpander");
- if ((PlacesUtils.nodeIsFolder(aNode) &&
- !PlacesUtils.nodeIsLivemarkContainer(aNode)) ||
- PlacesUtils.nodeIsLivemarkItem(aNode)) {
+ if (aNode.itemId != -1 &&
+ ((PlacesUtils.nodeIsFolder(aNode) &&
+ !PlacesUtils.nodeIsLivemarkContainer(aNode)) ||
+ PlacesUtils.nodeIsLivemarkItem(aNode))) {
if (infoBox.getAttribute("minimal") == "true")
infoBox.setAttribute("wasminimal", "true");
infoBox.removeAttribute("minimal");
@@ -599,6 +619,13 @@ var PlacesOrganizer = {
},
onContentTreeSelect: function PO_onContentTreeSelect() {
+ this._fillDetailsPane(this._content.selectedNode);
+ },
+
+ _fillDetailsPane: function PO__fillDetailsPane(aSelectedNode) {
+ var infoBox = document.getElementById("infoBox");
+ var detailsDeck = document.getElementById("detailsDeck");
+
// If a textbox within a panel is focused, force-blur it so its contents
// are saved
if (gEditItemOverlay.itemId != -1) {
@@ -607,39 +634,33 @@ var PlacesOrganizer = {
focusedElement instanceof HTMLTextAreaElement) &&
/^editBMPanel.*/.test(focusedElement.parentNode.parentNode.id))
focusedElement.blur();
- }
- var infoBox = document.getElementById("infoBox");
- var detailsDeck = document.getElementById("detailsDeck");
- detailsDeck.selectedIndex = 1;
- var selectedNode = this._content.selectedNode;
- if (selectedNode) {
- infoBox.hidden = false;
- if (selectedNode.itemId != -1 &&
- !PlacesUtils.nodeIsSeparator(selectedNode)) {
- if (this._paneDisabled) {
- this._setDetailsFieldsDisabledState(false);
- this._paneDisabled = false;
- }
-
- // Using the concrete itemId is arguably wrong. The bookmarks API
- // does allow setting properties for folder shortcuts as well, but since
- // the UI does not distinct between the couple, we better just show
- // the concrete item properties.
- if (selectedNode.type ==
- Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT) {
- gEditItemOverlay.initPanel(asQuery(selectedNode).folderItemId,
- { hiddenRows: ["folderPicker"],
- forceReadOnly: true });
- }
- else {
- gEditItemOverlay.initPanel(selectedNode.itemId,
- { hiddenRows: ["folderPicker"] });
- }
-
- this._detectAndSetDetailsPaneMinimalState(selectedNode);
+ // don't update the panel if we are already editing this node
+ if (aSelectedNode && gEditItemOverlay.itemId == aSelectedNode.itemId &&
+ detailsDeck.selectedIndex == 1)
return;
+ }
+
+ if (aSelectedNode && !PlacesUtils.nodeIsSeparator(aSelectedNode)) {
+ detailsDeck.selectedIndex = 1;
+ infoBox.hidden = false;
+ // Using the concrete itemId is arguably wrong. The bookmarks API
+ // does allow setting properties for folder shortcuts as well, but since
+ // the UI does not distinct between the couple, we better just show
+ // the concrete item properties.
+ if (aSelectedNode.type ==
+ Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT) {
+ gEditItemOverlay.initPanel(asQuery(aSelectedNode).folderItemId,
+ { hiddenRows: ["folderPicker"],
+ forceReadOnly: true });
}
+ else {
+ var itemId = PlacesUtils.getConcreteItemId(aSelectedNode);
+ gEditItemOverlay.initPanel(itemId != -1 ? itemId :
+ PlacesUtils._uri(aSelectedNode.uri),
+ { hiddenRows: ["folderPicker"] });
+ }
+ this._detectAndSetDetailsPaneMinimalState(aSelectedNode);
}
else {
detailsDeck.selectedIndex = 0;
@@ -664,13 +685,6 @@ var PlacesOrganizer = {
}
}
}
-
- // Nothing to do if the pane was already disabled
- if (!this._paneDisabled) {
- gEditItemOverlay.uninitPanel();
- this._setDetailsFieldsDisabledState(true);
- this._paneDisabled = true;
- }
},
// NOT YET USED
@@ -716,13 +730,12 @@ var PlacesOrganizer = {
saveSearch: function PO_saveSearch() {
// Get the place: uri for the query.
// If the advanced query builder is showing, use that.
- var queries = PlacesQueryBuilder.queries;
var options = this.getCurrentOptions();
-#ifndef PLACES_QUERY_BUILDER
- var query = PlacesUtils.history.getNewQuery();
- query.searchTerms = PlacesSearchBox.value;
- queries.push(query);
+#ifdef PLACES_QUERY_BUILDER
+ var queries = PlacesQueryBuilder.queries;
+#else
+ var queries = this.getCurrentQueries();
#endif
var placeSpec = PlacesUtils.history.queriesToQueryString(queries,
@@ -1424,14 +1437,6 @@ var PlacesQueryBuilder = {
// update collection type and get folders
var folders = [];
switch (id) {
- case "scopeBarToolbar":
- PlacesSearchBox.filterCollection = "collection";
- folders.push(PlacesUtils.toolbarFolderId);
- break;
- case "scopeBarMenu":
- PlacesSearchBox.filterCollection = "collection";
- folders.push(PlacesUtils.bookmarksMenuFolderId);
- break;
case "scopeBarHistory":
PlacesSearchBox.filterCollection = "history";
folders = [];
diff --git a/browser/components/places/content/places.xul b/browser/components/places/content/places.xul
index 9da1e43b09de..558ed04deac6 100755
--- a/browser/components/places/content/places.xul
+++ b/browser/components/places/content/places.xul
@@ -181,10 +181,13 @@
+
-
+
-
-
+
diff --git a/browser/components/places/content/placesOverlay.xul b/browser/components/places/content/placesOverlay.xul
index 02a930d23619..4369fdee98a8 100644
--- a/browser/components/places/content/placesOverlay.xul
+++ b/browser/components/places/content/placesOverlay.xul
@@ -137,45 +137,49 @@
command="placesCmd_new:bookmark"
label="&cmd.new_bookmark.label;"
accesskey="&cmd.new_bookmark.accesskey;"
- selection="mutable"/>
+ selection="any"
+ hideifnoinsetionpoint="true"/>
+ selection="any"
+ hideifnoinsetionpoint="true"/>
+ selection="any"
+ hideifnoinsetionpoint="true"/>
+ selection="bookmark|folder|separator|query"
+ forcehideselection="tagChild|livemarkChild"/>
+ selection="any"/>
+ selection="any"
+ hideifnoinsetionpoint="true"/>
+ selection="folder"/>
diff --git a/browser/components/places/content/toolbar.xml b/browser/components/places/content/toolbar.xml
index 60797170c29f..b2c4d73018c7 100755
--- a/browser/components/places/content/toolbar.xml
+++ b/browser/components/places/content/toolbar.xml
@@ -384,26 +384,28 @@
@@ -449,7 +451,7 @@
if (this._self._result != val) {
this._self._containerNodesMap = [];
this._self._result = val;
- if (val) // this calls _rebuild through invalidateContainer
+ if (val) // this calls _rebuild through invalidateContainer
val.root.containerOpen = true;
}
return val;
@@ -916,6 +918,8 @@
if (this._overFolder.node)
this._overFolder.closeTimer = this._setTimer(this._overFolder.hoverTime);
PlacesControllerDragHelper.currentDropTarget = null;
+
+ this._self._draggedNode = null;
},
getSupportedFlavours: function TBV_DO_getSupportedFlavours() {
diff --git a/browser/components/places/content/tree.xml b/browser/components/places/content/tree.xml
index 527f56480adf..279958f795b0 100644
--- a/browser/components/places/content/tree.xml
+++ b/browser/components/places/content/tree.xml
@@ -440,7 +440,7 @@
return this._cachedInsertionPoint = null;
}
- var orientation = Ci.nsITreeView.DROP_AFTER;
+ var orientation = Ci.nsITreeView.DROP_BEFORE;
// If there is no selection, insert at the end of the container.
if (!this.hasSelection) {
var index = this.view.rowCount - 1;
@@ -451,9 +451,9 @@
// This is a two-part process. The first part is determining the drop
// orientation.
- // * The default orientation is to drop _after_ the selected item.
- // * If the selected item is an open container, the default
- // orientation is to drop _into_ that container.
+ // * The default orientation is to drop _before_ the selected item.
+ // * If the selected item is a container, the default orientation
+ // is to drop _into_ that container.
//
// Warning: It may be tempting to use tree indexes in this code, but
// you must not, since the tree is nested and as your tree
@@ -468,18 +468,18 @@
var min = { }, max = { };
selection.getRangeAt(rc - 1, min, max);
- // If the sole selection is an open container, insert into it rather
- // than adjacent to it. Note that this only applies to _single_
- // selections - if the last element within a multi-selection is an
- // open folder, insert _adajacent_ to the selection.
+ // If the sole selection is a container, and we are not in
+ // a flatlist, insert into it.
+ // Note that this only applies to _single_ selections,
+ // if the last element within a multi-selection is a
+ // container, insert _adjacent_ to the selection.
//
// If the sole selection is the bookmarks toolbar folder, we insert
// into it even if it is not opened
var itemId =
PlacesUtils.getConcreteItemId(resultView.nodeForTreeIndex(max.value));
if (selection.count == 1 && resultView.isContainer(max.value) &&
- (resultView.isContainerOpen(max.value) ||
- itemId == PlacesUtils.bookmarksMenuFolderId))
+ !this.flatList)
orientation = Ci.nsITreeView.DROP_ON;
this._cachedInsertionPoint =
@@ -507,6 +507,7 @@
var result = this.getResult();
var resultview = this.getResultView();
var container = result.root;
+ var dropNearItemId = -1;
NS_ASSERT(container, "null container");
// When there's no selection, assume the container is the container
// the view is populated from (i.e. the result's itemId).
@@ -520,7 +521,8 @@
}
else if (!this._disallowInsertion(lastSelected) &&
lastSelected.containerOpen &&
- orientation == Ci.nsITreeView.DROP_AFTER) {
+ orientation == Ci.nsITreeView.DROP_AFTER &&
+ lastSelected.hasChildren) {
// If the last selected item is an open container and the user is
// trying to drag into it as a first item, really insert into it.
container = lastSelected;
@@ -539,12 +541,19 @@
return null;
var queryOptions = asQuery(result.root).queryOptions;
- if (queryOptions.excludeItems || queryOptions.excludeQueries ||
- queryOptions.excludeReadOnlyFolders ||
- queryOptions.sortingMode != Ci.nsINavHistoryQueryOptions.SORT_BY_NONE) {
- // If we are within either a sorted view or a view in which
- // some items may be invisible, insert at the end
- index = -1;
+ if (queryOptions.sortingMode !=
+ Ci.nsINavHistoryQueryOptions.SORT_BY_NONE) {
+ // If we are within a sorted view, insert at the end
+ index = -1;
+ }
+ else if (queryOptions.excludeItems ||
+ queryOptions.excludeQueries ||
+ queryOptions.excludeReadOnlyFolders) {
+ // Some item may be invisible, insert near last selected one.
+ // We don't replace index here to avoid requests to the db,
+ // instead it will be calculated later by the controller.
+ index = -1;
+ dropNearItemId = lastSelected.itemId;
}
else {
var lsi = PlacesUtils.getIndexOfNode(lastSelected);
@@ -558,7 +567,8 @@
return new InsertionPoint(PlacesUtils.getConcreteItemId(container),
index, orientation,
- PlacesUtils.nodeIsTagQuery(container));
+ PlacesUtils.nodeIsTagQuery(container),
+ dropNearItemId);
]]>