JavaScript error while leaving File Bookmark dialog (treecols has no properties) git-svn-id: svn://10.0.0.236/trunk@134620 18797224-902f-48f8-a5cc-f745e15eee43
2184 lines
96 KiB
XML
2184 lines
96 KiB
XML
<?xml version="1.0"?>
|
|
|
|
<!-- -*- Mode: HTML; indent-tabs-mode: nil; -*- -->
|
|
<!--
|
|
|
|
The contents of this file are subject to the Netscape Public
|
|
License Version 1.1 (the "License"); you may not use this file
|
|
except in compliance with the License. You may obtain a copy of
|
|
the License at http://www.mozilla.org/NPL/
|
|
|
|
Software distributed under the License is distributed on an "AS
|
|
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
implied. See the License for the specific language governing
|
|
rights and limitations under the License.
|
|
|
|
The Original Code is mozilla.org code.
|
|
|
|
The Initial Developer of the Original Code is Netscape
|
|
Communications Corporation. Portions created by Netscape are
|
|
Copyright (C) 1998 Netscape Communications Corporation. All
|
|
Rights Reserved.
|
|
|
|
Contributor(s):
|
|
Ben Goodger <ben@netscape.com> (Original Author)
|
|
Blake Ross <blakeross@telocity.com>
|
|
|
|
-->
|
|
<!DOCTYPE window [
|
|
<!ENTITY % bookmarksDTD SYSTEM "chrome://communicator/locale/bookmarks/bookmarks.dtd" >
|
|
%bookmarksDTD;
|
|
]>
|
|
|
|
<bindings id="bookmarksBindings"
|
|
xmlns="http://www.mozilla.org/xbl"
|
|
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
xmlns:xbl="http://www.mozilla.org/xbl">
|
|
|
|
<binding id="bookmarksBase">
|
|
<implementation>
|
|
<!-- RDF Namespace URIs -->
|
|
<field name="RDF_NS">"http://www.w3.org/1999/02/22-rdf-syntax-ns#"</field>
|
|
<field name="NC_NS">"http://home.netscape.com/NC-rdf#"</field>
|
|
<field name="NC_NS_CMD">this.NC_NS + "command?cmd=";</field>
|
|
<property name="rdfContainer">
|
|
<getter><![CDATA[
|
|
const kRDFCContractID = "@mozilla.org/rdf/container;1";
|
|
const kRDFCIID = Components.interfaces.nsIRDFContainer;
|
|
return Components.classes[kRDFCContractID].getService(kRDFCIID);
|
|
]]></getter>
|
|
</property>
|
|
<field name="_rdf">null</field>
|
|
<property name="rdf">
|
|
<getter><![CDATA[
|
|
if (!this._rdf) {
|
|
const kRDFContractID = "@mozilla.org/rdf/rdf-service;1";
|
|
const kRDFIID = Components.interfaces.nsIRDFService;
|
|
this._rdf = Components.classes[kRDFContractID].getService(kRDFIID);
|
|
}
|
|
return this._rdf;
|
|
]]></getter>
|
|
</property>
|
|
<field name="_bundle">null</field>
|
|
<field name="_bookmarksDS">null</field>
|
|
<property name="bookmarksDS">
|
|
<getter><![CDATA[
|
|
if (!this._bookmarksDS)
|
|
this._bookmarksDS = this.rdf.GetDataSource("rdf:bookmarks");
|
|
return this._bookmarksDS;
|
|
]]></getter>
|
|
</property>
|
|
<method name="flushBMDatasource">
|
|
<body><![CDATA[
|
|
var remoteDS = this.bookmarksDS.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
|
|
remoteDS.Flush();
|
|
]]></body>
|
|
</method>
|
|
</implementation>
|
|
</binding>
|
|
|
|
<binding id="bookmarks-tree"
|
|
extends="chrome://communicator/content/bookmarks/bookmarks.xml#bookmarksBase">
|
|
<implementation>
|
|
<constructor><![CDATA[
|
|
var bookmarksSvc = Components.classes["@mozilla.org/browser/bookmarks-service;1"].getService(Components.interfaces.nsIBookmarksService);
|
|
// This function only reads in the bookmarks from disk if they have not already been read.
|
|
bookmarksSvc.ReadBookmarks();
|
|
|
|
// We implement nsIController
|
|
this.tree.controllers.appendController(this.controller);
|
|
var olb = document.getAnonymousElementByAttribute(this, "anonid", "bookmarks-tree");
|
|
olb = olb.builder.QueryInterface(Components.interfaces.nsIXULTreeBuilder);
|
|
olb.addObserver(this.builderObserver);
|
|
|
|
// need to create string bundle manually instead of using <xul:stringbundle/>
|
|
// see bug 63370 for details
|
|
var localeService = Components.classes["@mozilla.org/intl/nslocaleservice;1"]
|
|
.getService(Components.interfaces.nsILocaleService);
|
|
var stringBundleService = Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Components.interfaces.nsIStringBundleService);
|
|
var bundleURL = "chrome://communicator/locale/bookmarks/bookmark.properties";
|
|
this._bundle = stringBundleService.createBundle(bundleURL, localeService.GetApplicationLocale());
|
|
|
|
|
|
// Load column settings from persisted attribute
|
|
var colinfostr = this.getAttribute("colinfo");
|
|
var colinfo = colinfostr.split(" ");
|
|
for (var i = 0; i < colinfo.length; ++i) {
|
|
if (colinfo[i] == "") continue;
|
|
|
|
var querymarker = colinfo[i].indexOf("?");
|
|
var anonid = colinfo[i].substring(4, querymarker);
|
|
var col = document.getAnonymousElementByAttribute(this, "id", anonid);
|
|
|
|
if (!anonid || !col) break;
|
|
|
|
var attrstring = colinfo[i].substr(querymarker + 1);
|
|
|
|
var attrpairs = attrstring.split("&");
|
|
for (var j = 0; j < attrpairs.length; ++j) {
|
|
var pair = attrpairs[j].split("=");
|
|
col.setAttribute(pair[0], pair[1]);
|
|
}
|
|
}
|
|
|
|
// Load sort data from preferences
|
|
this.refreshSort();
|
|
|
|
// Observe for changes in sort from other concurrent UI
|
|
const kPrefSvcContractID = "@mozilla.org/preferences;1";
|
|
const kPrefSvcIID = Components.interfaces.nsIPrefService;
|
|
var prefSvc = Components.classes[kPrefSvcContractID].getService(kPrefSvcIID);
|
|
var prefs = prefSvc.getBranch(null);
|
|
const kPrefBranchInternalIID = Components.interfaces.nsIPrefBranchInternal;
|
|
var bookmarksPrefsInternal = prefs.QueryInterface(kPrefBranchInternalIID);
|
|
bookmarksPrefsInternal.addObserver(this.sortChangedObserver.domain,
|
|
this.sortChangedObserver, false);
|
|
]]></constructor>
|
|
<destructor><![CDATA[
|
|
|
|
this.treeBuilder.removeObserver(this.builderObserver);
|
|
this.tree.controllers.removeController(this.controller);
|
|
|
|
// Save column settings and sort info to persisted attribute
|
|
var persistString = "";
|
|
|
|
var sortResource = this.NC_NS + "Name";
|
|
var sortDirection = "none";
|
|
|
|
var treecols = document.getAnonymousElementByAttribute(this, "anonid", "treecols");
|
|
var child = treecols.firstChild;
|
|
while (child) {
|
|
if (child.localName != "splitter") {
|
|
var formatString = " col:%1%?width=%2%&hidden=%3%&ordinal=%6%";
|
|
formatString = formatString.replace(/%1%/, child.getAttribute("id"));
|
|
formatString = formatString.replace(/%2%/, child.getAttribute("width"));
|
|
formatString = formatString.replace(/%3%/, child.getAttribute("hidden"));
|
|
|
|
// While we're walking the columns, if we discover the column that represents the
|
|
// field sorted by, save the resource associated with that column so that we
|
|
// can save that in prefs (see below)
|
|
if (child.getAttribute("sortActive") == "true") {
|
|
sortResource = child.getAttribute("sort");
|
|
sortDirection = child.getAttribute("sortDirection");
|
|
}
|
|
formatString = formatString.replace(/%6%/, child.getAttribute("ordinal"));
|
|
persistString += formatString;
|
|
}
|
|
child = child.nextSibling;
|
|
}
|
|
this.setAttribute("colinfo", persistString);
|
|
|
|
document.persist(this.id, "colinfo");
|
|
|
|
// Unhook the sort change observer for this tree
|
|
const kPrefSvcContractID = "@mozilla.org/preferences;1";
|
|
const kPrefSvcIID = Components.interfaces.nsIPrefService;
|
|
var prefSvc = Components.classes[kPrefSvcContractID].getService(kPrefSvcIID);
|
|
var prefs = prefSvc.getBranch(null);
|
|
const kPrefBranchInternalIID = Components.interfaces.nsIPrefBranchInternal;
|
|
var bookmarksPrefsInternal = prefs.QueryInterface(kPrefBranchInternalIID);
|
|
bookmarksPrefsInternal.removeObserver(this.sortChangedObserver.domain,
|
|
this.sortChangedObserver);
|
|
|
|
]]></destructor>
|
|
|
|
<field name="sortChangedObserver">
|
|
<![CDATA[
|
|
({
|
|
outer: this,
|
|
domain: "browser.bookmarks.sort",
|
|
observe: function BMOL_sortChangedObserver(aSubject, aTopic, aPrefName)
|
|
{
|
|
if (aTopic != "nsPref:changed") return;
|
|
if (aPrefName.substr(0, this.domain.length) != this.domain) return;
|
|
|
|
this.outer.refreshSort();
|
|
}
|
|
})
|
|
]]>
|
|
</field>
|
|
|
|
<field name="sorted">false</field>
|
|
<method name="refreshSort">
|
|
<body>
|
|
<![CDATA[
|
|
const kPrefSvcContractID = "@mozilla.org/preferences;1";
|
|
const kPrefSvcIID = Components.interfaces.nsIPrefService;
|
|
var prefSvc = Components.classes[kPrefSvcContractID].getService(kPrefSvcIID);
|
|
var bookmarksSortPrefs = prefSvc.getBranch("browser.bookmarks.sort.");
|
|
|
|
// This ensures that we don't sort twice in the tree that is clicked on
|
|
// as a result of 1) the click and 2) the pref listener.
|
|
if (!this.sorted) {
|
|
try {
|
|
var sortResource = bookmarksSortPrefs.getCharPref("resource");
|
|
var sortDirection = bookmarksSortPrefs.getCharPref("direction");
|
|
|
|
// Walk the columns, when we find a column with a sort resource that matches the supplied
|
|
// data, stop and make sure it's sort active.
|
|
var treecols = document.getAnonymousElementByAttribute(this, "anonid", "treecols");
|
|
var child = treecols.firstChild;
|
|
while (child) {
|
|
if (child.localName != "splitter") {
|
|
if (child.getAttribute("sort") == sortResource) {
|
|
child.setAttribute("sortActive", "true");
|
|
child.setAttribute("sortDirection", sortDirection);
|
|
this.treeBuilder.sort(child, false);
|
|
break;
|
|
}
|
|
}
|
|
child = child.nextSibling;
|
|
}
|
|
}
|
|
catch (e) {
|
|
}
|
|
}
|
|
|
|
this.sorted = false;
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
<property name="columns">
|
|
<getter>
|
|
<![CDATA[
|
|
var cols = [];
|
|
|
|
var treecols = document.getAnonymousElementByAttribute(this, "anonid", "treecols");
|
|
var child = treecols.firstChild;
|
|
while (child) {
|
|
if (child.localName != "splitter") {
|
|
var obj = {
|
|
label: child.getAttribute("label"),
|
|
accesskey: child.getAttribute("accesskey"),
|
|
resource: child.getAttribute("sort"),
|
|
sortActive: child.getAttribute("sortActive") == "true",
|
|
hidden: child.getAttribute("hidden")
|
|
}
|
|
cols.push(obj);
|
|
}
|
|
child = child.nextSibling;
|
|
}
|
|
|
|
return cols;
|
|
]]>
|
|
</getter>
|
|
</property>
|
|
|
|
<method name="toggleColumnVisibility">
|
|
<parameter name="aColumnResource"/>
|
|
<body>
|
|
<![CDATA[
|
|
var elt = document.getAnonymousElementByAttribute(this, "sort", aColumnResource);
|
|
if (elt)
|
|
elt.setAttribute("hidden", elt.getAttribute("hidden") != "true");
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<property name="treeBoxObject">
|
|
<getter><![CDATA[
|
|
return this.tree.boxObject.QueryInterface(Components.interfaces.nsITreeBoxObject);
|
|
]]></getter>
|
|
</property>
|
|
|
|
<property name="treeBuilder">
|
|
<getter><![CDATA[
|
|
return this.tree.builder.QueryInterface(Components.interfaces.nsIXULTreeBuilder);
|
|
]]></getter>
|
|
</property>
|
|
|
|
<property name="tree">
|
|
<getter><![CDATA[
|
|
return document.getAnonymousElementByAttribute(this, "anonid", "bookmarks-tree");
|
|
]]></getter>
|
|
</property>
|
|
|
|
<property name="currentIndex">
|
|
<getter><![CDATA[
|
|
return this.treeBoxObject.selection.currentIndex;
|
|
]]></getter>
|
|
</property>
|
|
|
|
<property name="currentRes">
|
|
<getter><![CDATA[
|
|
return this.treeBuilder.getResourceAtIndex(this.currentIndex);
|
|
]]></getter>
|
|
</property>
|
|
|
|
<property name="parentRes">
|
|
<getter><![CDATA[
|
|
const currIndex = this.currentIndex;
|
|
|
|
if (currIndex == -1)
|
|
return this.rdf.GetResource("NC:BookmarksRoot");
|
|
|
|
var parentIndex = this.treeBoxObject.view.getParentIndex(currIndex);
|
|
if (parentIndex != -1)
|
|
return this.treeBuilder.getResourceAtIndex(parentIndex)
|
|
return this.rdf.GetResource("NC:BookmarksRoot"); // assume its parent is the root
|
|
]]></getter>
|
|
</property>
|
|
|
|
<property name="firstSelectedIndex">
|
|
<getter><![CDATA[
|
|
var first = { };
|
|
this.treeBoxObject.selection.getRangeAt(0, first, { });
|
|
return first.value;
|
|
]]></getter>
|
|
</property>
|
|
|
|
<property name="lastSelectedIndex">
|
|
<getter><![CDATA[
|
|
var bo = this.treeBoxObject;
|
|
var last = { };
|
|
var rangeCount = bo.selection.getRangeCount();
|
|
bo.selection.getRangeAt(rangeCount - 1, { }, last);
|
|
return last.value;
|
|
]]></getter>
|
|
</property>
|
|
|
|
<property name="_browserURL">
|
|
<getter><![CDATA[
|
|
try {
|
|
var prefs = Components.classes["@mozilla.org/preferences;1"];
|
|
if (prefs) {
|
|
prefs = prefs.getService();
|
|
if (prefs)
|
|
prefs = prefs.QueryInterface(Components.interfaces.nsIPref);
|
|
}
|
|
if (prefs) {
|
|
var url = prefs.CopyCharPref("browser.chromeURL");
|
|
if (url)
|
|
return url;
|
|
}
|
|
} catch(e) {
|
|
}
|
|
return "chrome://navigator/content/navigator.xul";
|
|
]]></getter>
|
|
</property>
|
|
|
|
<field name="_type">null</field>
|
|
|
|
<property name="type">
|
|
<getter><![CDATA[
|
|
if (!this._type) {
|
|
var type = this.getAttribute("type");
|
|
if (!type)
|
|
type = "multi-column";
|
|
this._type = type;
|
|
}
|
|
return this._type;
|
|
]]></getter>
|
|
</property>
|
|
|
|
<!-- Returns the row index of the best row at which to perform an operation
|
|
relative to the current selection, e.g. creating a new bookmark
|
|
adjacent to the current selection. -->
|
|
<method name="getNextRowIndex">
|
|
<body><![CDATA[
|
|
var bo = this.treeBoxObject;
|
|
var rangeCount = bo.selection.getRangeCount();
|
|
var currLevel, lastIndex = 0;
|
|
if (!rangeCount)
|
|
currLevel = 0;
|
|
else
|
|
currLevel = bo.view.getLevel(this.firstSelectedIndex);
|
|
|
|
// Walk the selection. If the level for the current item is less than
|
|
// our running minimum, assume it is higher in the hierarchy than any
|
|
// previous. In this case, or in the case with a selected item of same
|
|
// hierarchy, set the lastIndex.
|
|
// XXXben - erk this comment sort of sucks. A diagram might help.
|
|
for (var i = 0; i < rangeCount; ++i) {
|
|
var rangeMin = { };
|
|
var rangeMax = { };
|
|
bo.selection.getRangeAt(i, rangeMin, rangeMax);
|
|
for (var j = rangeMax.value; j >= rangeMin.value; --j) {
|
|
var level = bo.view.getLevel(j);
|
|
if (level <= currLevel) {
|
|
currLevel = level;
|
|
lastIndex = j;
|
|
}
|
|
}
|
|
}
|
|
return lastIndex;
|
|
]]></body>
|
|
</method>
|
|
|
|
<method name="getTypeAtIndex">
|
|
<parameter name="aIndex" />
|
|
<body><![CDATA[
|
|
try {
|
|
return BookmarksUtils.resolveType(this.treeBuilder.getResourceAtIndex(aIndex));
|
|
}
|
|
catch(ex) {
|
|
return null;
|
|
}
|
|
]]></body>
|
|
</method>
|
|
|
|
<!-- observer -->
|
|
<field name="newFolderRDFObserver" readonly="true"><![CDATA[
|
|
({
|
|
_newFolderURI: null,
|
|
onAssert: function (aDS, aSource, aProperty, aValue)
|
|
{
|
|
try {
|
|
var value = aValue.QueryInterface(Components.interfaces.nsIRDFResource);
|
|
if (aDS.URI == "rdf:bookmarks" && aProperty.Value == this.RDF_NS + "type" &&
|
|
value.Value == this.NC_NS + "Folder")
|
|
this._newFolderURI = aSource.Value;
|
|
}
|
|
catch (e) {
|
|
// Failures are OK, the value could be a literal instead of a resource.
|
|
}
|
|
},
|
|
onUnassert: function (aDS, aSource, aProperty, aTarget) { },
|
|
onChange: function (aDS, aSource, aProperty, aOldTarget, aNewTarget) { },
|
|
onMove: function (aDS, aOldSource, aNewSource, aProperty, aTarget) { },
|
|
beginUpdateBatch: function (aDS) { },
|
|
endUpdateBatch: function (aDS) { }
|
|
})
|
|
]]></field>
|
|
|
|
<!-- observer -->
|
|
<field name="DNDObserver" readonly="true"><![CDATA[
|
|
({
|
|
mOuter: this,
|
|
onDragStart: function (aEvent, aXferData, aDragAction)
|
|
{
|
|
if (this.mOuter.tree.getAttribute("sortActive") == "true")
|
|
throw Components.results.NS_OK;
|
|
aXferData.data = new TransferDataSet();
|
|
var rangeCount = this.mOuter.treeBoxObject.selection.getRangeCount();
|
|
for (var i = rangeCount - 1; i >= 0; --i) {
|
|
var rangeMin = { };
|
|
var rangeMax = { };
|
|
this.mOuter.treeBoxObject.selection.getRangeAt(i, rangeMin, rangeMax);
|
|
for (var j = rangeMax.value; j >= rangeMin.value; --j) {
|
|
var currRes = this.mOuter.treeBuilder.getResourceAtIndex(j);
|
|
var parentIndex = this.mOuter.treeBoxObject.view.getParentIndex(j);
|
|
var parentRes;
|
|
if (parentIndex == -1)
|
|
parentRes = this.mOuter.rdf.GetResource("NC:BookmarksRoot");
|
|
else
|
|
parentRes = this.mOuter.treeBuilder.getResourceAtIndex(parentIndex);
|
|
|
|
var type = this.mOuter.db.GetTarget(currRes, this.mOuter.rdf.GetResource(this.mOuter.RDF_NS + "type"), true);
|
|
type = type.QueryInterface(Components.interfaces.nsIRDFResource).Value;
|
|
if (!type || (type != (this.mOuter.NC_NS + "BookmarkSeparator") &&
|
|
type != (this.mOuter.NC_NS + "Bookmark") &&
|
|
type != (this.mOuter.NC_NS + "Folder")))
|
|
throw Components.results.NS_OK;
|
|
var name = this.mOuter.db.GetTarget(currRes, this.mOuter.rdf.GetResource(this.mOuter.NC_NS + "Name"), true);
|
|
var data = new TransferData();
|
|
if (name) {
|
|
name = name.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
|
|
data.addDataForFlavour("text/x-moz-url", currRes.Value + "\n" + name);
|
|
}
|
|
else {
|
|
data.addDataForFlavour("text/x-moz-url", currRes.Value);
|
|
}
|
|
data.addDataForFlavour("moz/rdfitem", currRes.Value + "\n" + parentRes.Value);
|
|
data.addDataForFlavour("text/unicode", currRes.Value);
|
|
|
|
aXferData.data.push(data);
|
|
}
|
|
|
|
if (aEvent.ctrlKey) {
|
|
const kDSIID = Components.interfaces.nsIDragService;
|
|
aDragAction.action = kDSIID.DRAGDROP_ACTION_COPY + kDSIID.DRAGDROP_ACTION_LINK;
|
|
}
|
|
}
|
|
}
|
|
})
|
|
]]></field>
|
|
|
|
<!-- nsIController -->
|
|
<field name="controller" readonly="true"><![CDATA[
|
|
({
|
|
mOuter: this,
|
|
|
|
supportsCommand: function BMOLController_supportsCommand(aCommand)
|
|
{
|
|
switch (aCommand) {
|
|
case "cmd_bm_undo":
|
|
case "cmd_bm_redo":
|
|
return false;
|
|
case "cmd_bm_cut":
|
|
case "cmd_bm_copy":
|
|
case "cmd_bm_paste":
|
|
case "cmd_bm_delete":
|
|
case "cmd_bm_selectAll":
|
|
case "cmd_bm_open":
|
|
case "cmd_bm_openinnewwindow":
|
|
case "cmd_bm_openfolder":
|
|
case "cmd_bm_newbookmark":
|
|
case "cmd_bm_newfolder":
|
|
case "cmd_bm_newseparator":
|
|
case "cmd_bm_find":
|
|
case "cmd_bm_properties":
|
|
case "cmd_bm_rename":
|
|
case "cmd_bm_setnewbookmarkfolder":
|
|
case "cmd_bm_setpersonaltoolbarfolder":
|
|
case "cmd_bm_setnewsearchfolder":
|
|
case "cmd_bm_import":
|
|
case "cmd_bm_export":
|
|
case "cmd_bm_fileBookmark":
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
},
|
|
|
|
isCommandEnabled: function BMOLController_isCommandEnabled(aCommand)
|
|
{
|
|
var bo = this.mOuter.treeBoxObject;
|
|
var type; // The bookmark's RDF:type arc
|
|
|
|
switch (aCommand) {
|
|
case "cmd_bm_undo":
|
|
case "cmd_bm_redo":
|
|
return false;
|
|
case "cmd_bm_openfolder":
|
|
// 'Expand' is only available if one item is selected and that item is a
|
|
// container item.
|
|
return bo.view.rowCount && bo.selection.count == 1 && bo.view.isContainer(this.mOuter.firstSelectedIndex);
|
|
case "cmd_bm_open":
|
|
return this.mOuter.getTypeAtIndex(this.mOuter.firstSelectedIndex) == this.mOuter.NC_NS + "Bookmark";
|
|
case "cmd_bm_openinnewwindow":
|
|
return true;
|
|
case "cmd_bm_rename":
|
|
case "cmd_bm_properties":
|
|
if (bo.selection.count != 1)
|
|
return false;
|
|
type = this.mOuter.getTypeAtIndex(this.mOuter.firstSelectedIndex);
|
|
return type == this.mOuter.NC_NS + "Bookmark" || type == this.mOuter.NC_NS + "Folder";
|
|
case "cmd_bm_cut":
|
|
type = this.mOuter.getTypeAtIndex(this.mOuter.firstSelectedIndex);
|
|
if (type != this.mOuter.NC_NS + "Bookmark" && type != this.mOuter.NC_NS + "BookmarkSeparator" && type != this.mOuter.NC_NS + "Folder")
|
|
return false;
|
|
return bo.selection.count > 0;
|
|
case "cmd_bm_find":
|
|
return true;
|
|
case "cmd_bm_newbookmark":
|
|
case "cmd_bm_newfolder":
|
|
case "cmd_bm_newseparator":
|
|
// This is not really correct because it gives the false impression
|
|
// that it is possible to create an item as a child of some immutable folders
|
|
// like IE Favorites, but it will do for now.
|
|
return true;
|
|
case "cmd_bm_delete":
|
|
// Determining whether or not the selection is mutable is handled by
|
|
// the deletion routine.
|
|
type = this.mOuter.getTypeAtIndex(this.mOuter.firstSelectedIndex);
|
|
if (type != this.mOuter.NC_NS + "Bookmark" && type != this.mOuter.NC_NS + "BookmarkSeparator" &&
|
|
type != this.mOuter.NC_NS + "Folder" && type != this.mOuter.NC_NS + "IEFavoriteFolder")
|
|
return false;
|
|
return bo.selection.count >= 1;
|
|
case "cmd_bm_selectAll":
|
|
// "Select All" is disabled when all visible rows are selected.
|
|
// XXXben this could be cleverer.
|
|
return bo.view.rowCount != bo.selection.count;
|
|
case "cmd_bm_copy":
|
|
return bo.selection.count >= 1;
|
|
case "cmd_bm_paste":
|
|
return this.mOuter.canPaste();
|
|
case "cmd_bm_setnewbookmarkfolder":
|
|
case "cmd_bm_setpersonaltoolbarfolder":
|
|
case "cmd_bm_setnewsearchfolder":
|
|
if (bo.selection.count != 1)
|
|
return false;
|
|
// XXXbar if a folder has more than one of these special attributes,
|
|
// this won't work
|
|
var folderURI;
|
|
if (aCommand == "cmd_bm_setnewbookmarkfolder")
|
|
folderURI = "NC:NewBookmarkFolder";
|
|
else if (aCommand == "cmd_bm_setpersonaltoolbarfolder")
|
|
folderURI = "NC:PersonalToolbarFolder";
|
|
else
|
|
folderURI = "NC:NewSearchFolder";
|
|
return (this.mOuter.getTypeAtIndex(this.mOuter.firstSelectedIndex) == this.mOuter.NC_NS + "Folder")
|
|
&& (this.mOuter.treeBuilder.getResourceAtIndex(this.mOuter.firstSelectedIndex).Value != folderURI);
|
|
case "cmd_bm_import":
|
|
case "cmd_bm_export":
|
|
return true;
|
|
case "cmd_bm_fileBookmark":
|
|
if (bo.selection.count < 1)
|
|
return false;
|
|
type = this.mOuter.getTypeAtIndex(this.mOuter.firstSelectedIndex);
|
|
return type == this.mOuter.NC_NS + "Folder" || type == this.mOuter.NC_NS + "Bookmark";
|
|
default:
|
|
return false;
|
|
}
|
|
},
|
|
|
|
doCommand: function BMOLController_doCommand(aCommand)
|
|
{
|
|
switch (aCommand) {
|
|
case "cmd_bm_cut":
|
|
this.mOuter.copySelection();
|
|
this.mOuter.deleteSelection();
|
|
break;
|
|
case "cmd_bm_copy":
|
|
this.mOuter.copySelection();
|
|
break;
|
|
case "cmd_bm_paste":
|
|
this.mOuter.paste();
|
|
break;
|
|
case "cmd_bm_delete":
|
|
this.mOuter.deleteSelection();
|
|
break;
|
|
case "cmd_bm_selectAll":
|
|
this.mOuter.selectAll();
|
|
break;
|
|
case "cmd_bm_open":
|
|
this.mOuter.openItem(null, false, false);
|
|
break;
|
|
case "cmd_bm_openfolder":
|
|
this.mOuter.treeBoxObject.view.toggleOpenState(this.mOuter.currentIndex);
|
|
break;
|
|
case "cmd_bm_openinnewwindow":
|
|
var type = this.mOuter.getTypeAtIndex(this.mOuter.currentIndex);
|
|
if (type == this.mOuter.NC_NS + "Folder")
|
|
this.mOuter.openFolderInNewWindow();
|
|
else
|
|
this.mOuter.openItem(null, true, false);
|
|
break;
|
|
case "cmd_bm_newbookmark":
|
|
this.mOuter.addBookmark();
|
|
break;
|
|
case "cmd_bm_newfolder":
|
|
this.mOuter.createNewFolder();
|
|
break;
|
|
case "cmd_bm_newseparator":
|
|
this.mOuter.createNewSeparator();
|
|
break;
|
|
case "cmd_bm_find":
|
|
this.mOuter.openFindDialog();
|
|
break;
|
|
case "cmd_bm_properties":
|
|
case "cmd_bm_rename":
|
|
this.mOuter.openPropertiesForItem();
|
|
break;
|
|
case "cmd_bm_setnewbookmarkfolder":
|
|
this.mOuter.setAsNewBookmarkFolder();
|
|
break;
|
|
case "cmd_bm_setpersonaltoolbarfolder":
|
|
this.mOuter.setAsPersonalToolbarFolder();
|
|
break;
|
|
case "cmd_bm_setnewsearchfolder":
|
|
this.mOuter.setAsNewSearchFolder();
|
|
break;
|
|
case "cmd_bm_import":
|
|
this.mOuter.importBookmarks();
|
|
break;
|
|
case "cmd_bm_export":
|
|
this.mOuter.exportBookmarks();
|
|
break;
|
|
case "cmd_bm_fileBookmark":
|
|
this.mOuter.fileBookmark();
|
|
break;
|
|
default:
|
|
}
|
|
}
|
|
})
|
|
]]></field>
|
|
|
|
<method name="onCommandUpdate">
|
|
<body><![CDATA[
|
|
var commands = ["cmd_bm_properties", "cmd_bm_rename", "cmd_bm_copy",
|
|
"cmd_bm_paste", "cmd_bm_cut", "cmd_bm_delete",
|
|
"cmd_bm_setpersonaltoolbarfolder",
|
|
"cmd_bm_setnewbookmarkfolder",
|
|
"cmd_bm_setnewsearchfolder", "cmd_bm_fileBookmark",
|
|
"cmd_bm_openfolder"];
|
|
for (var i = 0; i < commands.length; ++i) {
|
|
var enabled = this.controller.isCommandEnabled(commands[i]);
|
|
var commandNode = document.getElementById(commands[i]);
|
|
if (commandNode) {
|
|
if (enabled)
|
|
commandNode.removeAttribute("disabled");
|
|
else
|
|
commandNode.setAttribute("disabled", "true");
|
|
}
|
|
}
|
|
]]></body>
|
|
</method>
|
|
|
|
<method name="selectionChanged">
|
|
<parameter name="aEvent" />
|
|
<body><![CDATA[
|
|
]]></body>
|
|
</method>
|
|
|
|
<!-- nsIXULTreeBuilderObserver -->
|
|
<field name="builderObserver"><![CDATA[
|
|
({
|
|
mOuter: this,
|
|
canDropOn: function(index)
|
|
{
|
|
return true;
|
|
},
|
|
canDropBeforeAfter: function(index, before)
|
|
{
|
|
return true;
|
|
},
|
|
onDrop: function(row, orientation)
|
|
{
|
|
var dragService = Components.classes["@mozilla.org/widget/dragservice;1"].getService().QueryInterface(Components.interfaces.nsIDragService);
|
|
var dragSession = dragService.getCurrentSession();
|
|
if (!dragSession)
|
|
return;
|
|
const kRDFCContractID = "@mozilla.org/rdf/container;1";
|
|
const kRDFIID = Components.interfaces.nsIRDFContainer;
|
|
var RDFC = Components.classes[kRDFCContractID].getService(kRDFIID);
|
|
var rTarget = this.mOuter.treeBuilder.getResourceAtIndex(row);
|
|
var parentIndex = this.mOuter.treeBoxObject.view.getParentIndex(row);
|
|
var rContainer;
|
|
if (parentIndex == -1)
|
|
rContainer = this.mOuter.rdf.GetResource("NC:BookmarksRoot");
|
|
else
|
|
rContainer = this.mOuter.treeBuilder.getResourceAtIndex(parentIndex);
|
|
var trans = Components.classes["@mozilla.org/widget/transferable;1"].createInstance(Components.interfaces.nsITransferable);
|
|
var rBookmark = this.mOuter.rdf.GetResource(this.mOuter.NC_NS + "Bookmark");
|
|
trans.addDataFlavor("moz/rdfitem");
|
|
trans.addDataFlavor("text/x-moz-url");
|
|
trans.addDataFlavor("text/unicode");
|
|
|
|
var list = Components.classes["@mozilla.org/supports-array;1"].createInstance(Components.interfaces.nsISupportsArray);
|
|
|
|
var sourceUri;
|
|
var sourceResource;
|
|
var dirty = false;
|
|
var additiveFlag = false;
|
|
for (var i = 0; i < dragSession.numDropItems; ++i) {
|
|
dragSession.getData(trans, i);
|
|
var dataObj = {};
|
|
var bestFlavor = {};
|
|
var len = {};
|
|
trans.getAnyTransferData(bestFlavor, dataObj, len);
|
|
if (dataObj)
|
|
dataObj = dataObj.value.QueryInterface(Components.interfaces.nsISupportsString);
|
|
if (!dataObj)
|
|
continue;
|
|
sourceUri = dataObj.data.substring(0, len.value);
|
|
if (!sourceUri)
|
|
continue;
|
|
|
|
var sourceID = [], parentID = [], nameRequired = [], name = [];
|
|
nameRequired[i] = false;
|
|
name[i] = null;
|
|
switch (bestFlavor.value) {
|
|
case "moz/rdfitem":
|
|
var ix = sourceUri.indexOf("\n");
|
|
sourceID[i] = ix >= 0 ? (parentID[i] = sourceUri.substr(ix+1), sourceUri.substr(0, ix)) : sourceUri;
|
|
break;
|
|
case "text/x-moz-url":
|
|
ix = sourceUri.indexOf("\n");
|
|
sourceID[i] = ix >= 0 ? (name[i] = sourceUri.substr(ix+1), sourceUri.substr(0, ix)) : sourceUri;
|
|
break;
|
|
case "text/unicode":
|
|
sourceID[i] = sourceUri;
|
|
nameRequired[i] = true;
|
|
break;
|
|
default:
|
|
continue;
|
|
}
|
|
var rSource = this.mOuter.rdf.GetResource(sourceID[i]);
|
|
var rParent = parentID[i] ? this.mOuter.rdf.GetResource(parentID[i]) : null;
|
|
|
|
const kBMDS = this.mOuter.bookmarksDS;
|
|
var bmType = BookmarksUtils.resolveType(rSource);
|
|
var rType = this.mOuter.rdf.GetResource(this.mOuter.RDF_NS + "type");
|
|
if (!bmType)
|
|
kBMDS.Assert(rSource, rType, rBookmark, true);
|
|
|
|
// prevent dropping folder within itself or one of its subfolders
|
|
if (bmType == this.mOuter.NC_NS + "Folder") {
|
|
var currRow = row;
|
|
do {
|
|
var currURI = this.mOuter.treeBuilder.getResourceAtIndex(currRow).Value;
|
|
currRow = this.mOuter.treeBoxObject.view.getParentIndex(currRow);
|
|
}
|
|
while (currRow != -1 && currURI != "NC:BookmarksRoot" && currURI != rSource.Value);
|
|
if (currURI == rSource.Value)
|
|
return;
|
|
}
|
|
|
|
var dropIndex;
|
|
if (orientation == Components.interfaces.nsITreeView.inDropAfter &&
|
|
this.mOuter.treeBoxObject.view.isContainer(row) &&
|
|
this.mOuter.treeBoxObject.view.isContainerOpen(row) &&
|
|
!this.mOuter.treeBoxObject.view.isContainerEmpty(row)) {
|
|
rContainer = rTarget;
|
|
dropIndex = 1;
|
|
}
|
|
else {
|
|
RDFC.Init(kBMDS, rContainer);
|
|
dropIndex = RDFC.IndexOf(rTarget);
|
|
if (dropIndex == -1)
|
|
break;
|
|
if (orientation == Components.interfaces.nsITreeView.inDropAfter) {
|
|
++dropIndex;
|
|
}
|
|
}
|
|
|
|
const kDSIID = Components.interfaces.nsIDragService;
|
|
const kCopyAction = kDSIID.DRAGDROP_ACTION_COPY + kDSIID.DRAGDROP_ACTION_LINK;
|
|
if (rParent) {
|
|
if (!(dragSession.dragAction & kCopyAction)) {
|
|
RDFC.Init(kBMDS, rParent);
|
|
RDFC.RemoveElement(rSource, false);
|
|
}
|
|
}
|
|
|
|
if (bmType == this.mOuter.NC_NS + "Folder") {
|
|
// If we're going to copy a folder type, we need to clone the folder
|
|
// rather than just asserting the new node as a child of the drop folder.
|
|
if (dragSession.dragAction & kCopyAction)
|
|
rSource = BookmarksUtils.cloneFolder(rSource, rContainer, rTarget);
|
|
}
|
|
if (orientation != Components.interfaces.nsITreeView.inDropOn) {
|
|
RDFC.Init(kBMDS, rContainer);
|
|
RDFC.InsertElementAt(rSource, dropIndex, true);
|
|
}
|
|
else {
|
|
RDFC.Init(kBMDS, rTarget);
|
|
RDFC.AppendElement(rSource);
|
|
}
|
|
|
|
dirty = true;
|
|
|
|
//if (rParent) {
|
|
// gBookmarksShell.selectFolderItem(rContainer.Value, sourceID[i], additiveFlag);
|
|
// if (!additiveFlag) additiveFlag = true;
|
|
//}
|
|
// If a name is supplied, we want to assert this information into the
|
|
// graph. E.g. user drags an internet shortcut to the app, we want to
|
|
// preserve not only the URL but the name of the shortcut. The other case
|
|
// where we need to assert a name is when the node does not already exist
|
|
// in the graph, in this case we'll just use the URL as the name.
|
|
if (name[i] || nameRequired[i]) {
|
|
var currentName = kBMDS.GetTarget(this.mOuter.rdf.GetResource(sourceID[i]), this.mOuter.rdf.GetResource(this.mOuter.NC_NS + "Name"), true);
|
|
if (!currentName) {
|
|
var rDefaultName = this.mOuter.rdf.GetLiteral(name[i] || sourceID[i]);
|
|
if (rDefaultName) {
|
|
var rName = this.mOuter.rdf.GetResource(this.mOuter.NC_NS + "Name");
|
|
kBMDS.Assert(rSource, rName, rDefaultName, true);
|
|
}
|
|
}
|
|
}
|
|
if (dirty)
|
|
this.mOuter.flushBMDatasource();
|
|
}
|
|
},
|
|
onToggleOpenState: function BMOLBuilderObserver_onToggleOpenState(aItemIndex)
|
|
{
|
|
},
|
|
|
|
onCycleHeader: function BMOLBuilderObserver_onCycleHeader(aColumnID, aHeaderElement)
|
|
{
|
|
const kPrefSvcContractID = "@mozilla.org/preferences;1";
|
|
const kPrefSvcIID = Components.interfaces.nsIPrefService;
|
|
var prefSvc = Components.classes[kPrefSvcContractID].getService(kPrefSvcIID);
|
|
var bookmarksSortPrefs = prefSvc.getBranch("browser.bookmarks.sort.");
|
|
|
|
// Sorted! http://www.sorted.org.nz/
|
|
this.mOuter.sorted = true;
|
|
|
|
bookmarksSortPrefs.setCharPref("resource", aHeaderElement.getAttribute("sort"));
|
|
bookmarksSortPrefs.setCharPref("direction", aHeaderElement.getAttribute("sortDirection"));
|
|
},
|
|
|
|
onCycleCell: function BMOLBuilderObserver_onCycleCell(aItemIndex, aColumnID)
|
|
{
|
|
},
|
|
|
|
onSelectionChanged: function BMOLBuilderObserver_onSelectionChanged()
|
|
{
|
|
this.mOuter.onCommandUpdate();
|
|
const kStatusBar = document.getAnonymousElementByAttribute(this.mOuter, "anonid", "statusbar-text");
|
|
if (!kStatusBar)
|
|
return;
|
|
const currentIndex = this.mOuter.currentIndex;
|
|
var displayValue = "";
|
|
if (this.mOuter.treeBoxObject.selection.count == 1) {
|
|
if (this.mOuter.treeBoxObject.view.isContainer(currentIndex)) {
|
|
const kRDFCContractID = "@mozilla.org/rdf/container;1";
|
|
const kRDFCIID = Components.interfaces.nsIRDFContainer;
|
|
const kRDFC = Components.classes[kRDFCContractID].getService(kRDFCIID);
|
|
const krSrc = this.mOuter.treeBuilder.getResourceAtIndex(currentIndex);
|
|
try {
|
|
kRDFC.Init(this.mOuter.db, krSrc);
|
|
var count = kRDFC.GetCount();
|
|
displayValue = this.mOuter._bundle.GetStringFromName("status_foldercount");
|
|
displayValue = displayValue.replace(/%num_items%/, count);
|
|
}
|
|
catch (e) {
|
|
}
|
|
}
|
|
else {
|
|
try {
|
|
displayValue = this.mOuter.db.GetTarget(this.mOuter.treeBuilder.getResourceAtIndex(currentIndex), this.mOuter.rdf.GetResource(this.mOuter.NC_NS + "URL"), true);
|
|
displayValue = displayValue.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
|
|
}
|
|
catch (e) {
|
|
displayValue = "";
|
|
}
|
|
}
|
|
if (displayValue.substring(0, 3) == "NC:")
|
|
displayValue = "";
|
|
}
|
|
kStatusBar.label = displayValue;
|
|
},
|
|
|
|
isEditable: function BMOLBuilderObserver_isEditable(aItemIndex, aColumnID)
|
|
{
|
|
},
|
|
|
|
getImageSource: function BMOLBuilderObserver_getImageSource(aItemIndex, aColumnID)
|
|
{
|
|
},
|
|
|
|
onSetCellText: function BMOLBuilderObserver_onSetCellText(aItemIndex, aColumnID, aValue)
|
|
{
|
|
},
|
|
|
|
onPerformAction: function BMOLBuilderObserver_onPerformAction(aAction)
|
|
{
|
|
},
|
|
|
|
onPerformActionOnRow: function BMOLBuilderObserver_onPerformActionOnRow(aAction, aItemIndex)
|
|
{
|
|
},
|
|
|
|
onPerformActionOnCell: function BMOLBuilderObserver_onPerformActionOnCell(aAction, aItemIndex, aColumnID)
|
|
{
|
|
}
|
|
})
|
|
]]></field>
|
|
|
|
<!-- RDF utility functions required by base binding -->
|
|
<property name="db">
|
|
<getter><![CDATA[
|
|
return this.tree.database;
|
|
]]></getter>
|
|
</property>
|
|
|
|
<method name="doBookmarksCommand">
|
|
<parameter name="aSourceURI"/>
|
|
<parameter name="aCommand"/>
|
|
<parameter name="aArgumentsArray"/>
|
|
<body><![CDATA[
|
|
var rCommand = this.rdf.GetResource(aCommand);
|
|
|
|
var kSuppArrayContractID = "@mozilla.org/supports-array;1";
|
|
var kSuppArrayIID = Components.interfaces.nsISupportsArray;
|
|
var sourcesArray = Components.classes[kSuppArrayContractID].createInstance(kSuppArrayIID);
|
|
if (aSourceURI) {
|
|
var rSource = this.rdf.GetResource(aSourceURI);
|
|
sourcesArray.AppendElement (rSource);
|
|
}
|
|
|
|
var argsArray = Components.classes[kSuppArrayContractID].createInstance(kSuppArrayIID);
|
|
for (var i = 0; i < aArgumentsArray.length; ++i) {
|
|
var rArc = this.rdf.GetResource(aArgumentsArray[i].property);
|
|
argsArray.AppendElement(rArc);
|
|
var rValue = null;
|
|
if ("resource" in aArgumentsArray[i])
|
|
rValue = this.rdf.GetResource(aArgumentsArray[i].resource);
|
|
else
|
|
rValue = this.rdf.GetLiteral(aArgumentsArray[i].literal);
|
|
argsArray.AppendElement(rValue);
|
|
}
|
|
|
|
// Exec the command in the Composite (not Bookmarks) datasource
|
|
// so that command aggregation works
|
|
this.db.DoCommand(sourcesArray, rCommand, argsArray);
|
|
]]></body>
|
|
</method>
|
|
|
|
<method name="selectAll">
|
|
<body><![CDATA[
|
|
this.treeBoxObject.selection.selectAll();
|
|
]]></body>
|
|
</method>
|
|
|
|
<method name="paste">
|
|
<body><![CDATA[
|
|
const kXferableContractID = "@mozilla.org/widget/transferable;1";
|
|
const kXferableIID = Components.interfaces.nsITransferable;
|
|
var xferable = Components.classes[kXferableContractID].createInstance(kXferableIID);
|
|
xferable.addDataFlavor("moz/bookmarkclipboarditem");
|
|
xferable.addDataFlavor("text/x-moz-url");
|
|
xferable.addDataFlavor("text/unicode");
|
|
|
|
const kClipboardContractID = "@mozilla.org/widget/clipboard;1";
|
|
const kClipboardIID = Components.interfaces.nsIClipboard;
|
|
var clipboard = Components.classes[kClipboardContractID].getService(kClipboardIID);
|
|
clipboard.getData(xferable, kClipboardIID.kGlobalClipboard);
|
|
|
|
var flavour = { };
|
|
var data = { };
|
|
var length = { };
|
|
xferable.getAnyTransferData(flavour, data, length);
|
|
var nodes = []; var names = [];
|
|
data = data.value.QueryInterface(Components.interfaces.nsISupportsString).data;
|
|
switch (flavour.value) {
|
|
case "moz/bookmarkclipboarditem":
|
|
nodes = data.split("\n");
|
|
break;
|
|
case "text/x-moz-url":
|
|
var ix = data.indexOf("\n");
|
|
nodes.push(data.substring(0, ix != -1 ? ix : data.length));
|
|
names.push(data.substring(ix));
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
const kRDFContractID = "@mozilla.org/rdf/rdf-service;1";
|
|
const kRDFIID = Components.interfaces.nsIRDFService;
|
|
const ksRDF = Components.classes[kRDFContractID].getService(kRDFIID);
|
|
var parentRes;
|
|
const currentIndex = this.currentIndex;
|
|
if (!this.treeBoxObject.view.isContainer(currentIndex))
|
|
parentRes = this.parentRes;
|
|
else
|
|
parentRes = this.treeBuilder.getResourceAtIndex(currentIndex);
|
|
|
|
const currentRes = this.currentRes;
|
|
const kRDFCContractID = "@mozilla.org/rdf/container;1";
|
|
const kRDFCIID = Components.interfaces.nsIRDFContainer;
|
|
const ksRDFC = Components.classes[kRDFCContractID].getService(kRDFCIID);
|
|
var additiveFlag = false;
|
|
for (var i = 0; i < nodes.length; ++i) {
|
|
if (!nodes[i]) continue;
|
|
var aNode = nodes[i];
|
|
var rType = null;
|
|
|
|
var tabIndex = aNode.indexOf("\t");
|
|
if (tabIndex > 0)
|
|
{
|
|
rType = ksRDF.GetResource(aNode.substring(tabIndex + 1));
|
|
aNode = aNode.substring(0, tabIndex);
|
|
}
|
|
var rCurrent = ksRDF.GetResource(aNode);
|
|
if (!rType && names[i])
|
|
{
|
|
const krName = ksRDF.GetResource(names[i]);
|
|
const krNameProperty = ksRDF.GetResource("http://home.netscape.com/NC-rdf#Name");
|
|
const krBookmark = ksRDF.GetResource("http://home.netscape.com/NC-rdf#Bookmark");
|
|
kBMDS.Assert(rCurrent, krNameProperty, krName, true);
|
|
// note: never need to assert type (it is derived)
|
|
}
|
|
|
|
// If the node is a folder, then we need to create a new anonymous
|
|
// resource and copy all the arcs over.
|
|
if (rType && rType.Value == "http://home.netscape.com/NC-rdf#Folder") {
|
|
// but wait, copying a folder into its child or itself may cause recursive
|
|
// folder, so need a check before the cloning.
|
|
var checkIndex = this.currentIndex;
|
|
var checkRes;
|
|
while (checkIndex != -1) {
|
|
checkRes = this.treeBuilder.getResourceAtIndex(checkIndex);
|
|
if (checkRes.EqualsNode(rCurrent))
|
|
break;
|
|
checkIndex = this.treeBoxObject.view.getParentIndex(checkIndex);
|
|
}
|
|
if (checkIndex == -1)
|
|
rCurrent = BookmarksUtils.cloneFolder(rCurrent, parentRes, currentRes);
|
|
else
|
|
continue;
|
|
}
|
|
// If this item already exists in this container, don't paste, as
|
|
// this will result in the creation of multiple copies in the datasource
|
|
// but will not result in an update of the UI. (In Short: we don't
|
|
// handle multiple bookmarks well)
|
|
ksRDFC.Init(this.bookmarksDS, parentRes);
|
|
ix = ksRDFC.IndexOf(rCurrent);
|
|
if (ix != -1)
|
|
continue;
|
|
|
|
ix = ksRDFC.IndexOf(currentRes);
|
|
if (ix != -1)
|
|
ksRDFC.InsertElementAt(rCurrent, ix+1, true);
|
|
else
|
|
ksRDFC.AppendElement(rCurrent);
|
|
|
|
this.flushBMDatasource();
|
|
}
|
|
]]></body>
|
|
</method>
|
|
|
|
<method name="copySelection">
|
|
<body><![CDATA[
|
|
const kSuppArrayContractID = "@mozilla.org/supports-array;1";
|
|
const kSuppArrayIID = Components.interfaces.nsISupportsArray;
|
|
var itemArray = Components.classes[kSuppArrayContractID].createInstance(kSuppArrayIID);
|
|
const kRDFContractID = "@mozilla.org/rdf/rdf-service;1";
|
|
const kRDFIID = Components.interfaces.nsIRDFService;
|
|
const ksRDF = Components.classes[kRDFContractID].getService(kRDFIID);
|
|
const kSuppWStringContractID = "@mozilla.org/supports-string;1";
|
|
const kSuppWStringIID = Components.interfaces.nsISupportsString;
|
|
var bmstring = Components.classes[kSuppWStringContractID].createInstance(kSuppWStringIID);
|
|
var unicodestring = Components.classes[kSuppWStringContractID].createInstance(kSuppWStringIID);
|
|
var htmlstring = Components.classes[kSuppWStringContractID].createInstance(kSuppWStringIID);
|
|
|
|
var sBookmarkItem = ""; var sTextUnicode = ""; var sTextHTML = "";
|
|
var rangeCount = this.treeBoxObject.selection.getRangeCount();
|
|
for (var i = rangeCount - 1; i >= 0; --i) {
|
|
var rangeMin = {};
|
|
var rangeMax = {};
|
|
this.treeBoxObject.selection.getRangeAt(i, rangeMin, rangeMax);
|
|
for (var j = rangeMax.value; j >= rangeMin.value; --j) {
|
|
var res = this.treeBuilder.getResourceAtIndex(j);
|
|
var urlRes = ksRDF.GetResource("http://home.netscape.com/NC-rdf#URL");
|
|
var nameRes = ksRDF.GetResource("http://home.netscape.com/NC-rdf#Name");
|
|
var typeRes = ksRDF.GetResource("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
|
|
|
|
var url = this.db.GetTarget(res, urlRes, true);
|
|
if (url)
|
|
url = url.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
|
|
var name = this.db.GetTarget(res, nameRes, true);
|
|
name = name.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
|
|
|
|
var bmkType = this.db.GetTarget(res, typeRes, true);
|
|
if (bmkType)
|
|
bmkType = bmkType.Value;
|
|
|
|
// XXXben is "\n" the best delimiter here? I think not.
|
|
sBookmarkItem += res.Value;
|
|
if (bmkType)
|
|
{
|
|
sBookmarkItem += "\t" + bmkType;
|
|
}
|
|
sBookmarkItem += "\n";
|
|
sTextUnicode += url + "\n";
|
|
sTextHTML += "<A HREF=\"" + url + "\">" + name + "</A>";
|
|
}
|
|
}
|
|
|
|
const kXferableContractID = "@mozilla.org/widget/transferable;1";
|
|
const kXferableIID = Components.interfaces.nsITransferable;
|
|
var xferable = Components.classes[kXferableContractID].createInstance(kXferableIID);
|
|
|
|
xferable.addDataFlavor("moz/bookmarkclipboarditem");
|
|
bmstring.data = sBookmarkItem;
|
|
xferable.setTransferData("moz/bookmarkclipboarditem", bmstring, sBookmarkItem.length*2)
|
|
|
|
xferable.addDataFlavor("text/html");
|
|
htmlstring.data = sTextHTML;
|
|
xferable.setTransferData("text/html", htmlstring, sTextHTML.length*2)
|
|
|
|
xferable.addDataFlavor("text/unicode");
|
|
unicodestring.data = sTextUnicode;
|
|
xferable.setTransferData("text/unicode", unicodestring, sTextUnicode.length*2)
|
|
|
|
const kClipboardContractID = "@mozilla.org/widget/clipboard;1";
|
|
const kClipboardIID = Components.interfaces.nsIClipboard;
|
|
var clipboard = Components.classes[kClipboardContractID].getService(kClipboardIID);
|
|
clipboard.setData(xferable, null, kClipboardIID.kGlobalClipboard);
|
|
]]></body>
|
|
</method>
|
|
|
|
<method name="deleteSelection">
|
|
<body><![CDATA[
|
|
const kRDFCContractID = "@mozilla.org/rdf/container;1";
|
|
const kRDFContractID = "@mozilla.org/rdf/rdf-service;1";
|
|
const kRDFIID = Components.interfaces.nsIRDFService;
|
|
const kRDFCIID = Components.interfaces.nsIRDFContainer;
|
|
const ksRDFC = Components.classes[kRDFCContractID].getService(kRDFCIID);
|
|
const ksRDF = Components.classes[kRDFContractID].getService(kRDFIID);
|
|
|
|
var nextIndex = 0; // Used to determine which item to select after the deletion
|
|
// is performed.
|
|
|
|
// Whether or not the selection contains items which cannot be deleted.
|
|
// var selectionContainsImmutableItems = false;
|
|
|
|
var boxObject = this.treeBoxObject;
|
|
var treeBuilder = this.treeBuilder;
|
|
var rangeCount = this.treeBoxObject.selection.getRangeCount();
|
|
|
|
var rangeMax = { };
|
|
var rangeMin = { };
|
|
|
|
// First, walk the selection and see if there's anything we /can't/
|
|
// delete. If so, present a warning dialog listing the items that
|
|
// we can't remove.
|
|
const kIMDSContractID = "@mozilla.org/rdf/datasource;1?name=in-memory-datasource";
|
|
const kIMDSIID = Components.interfaces.nsIRDFDataSource;
|
|
var imDS = Components.classes[kIMDSContractID].getService(kIMDSIID);
|
|
|
|
const kRDFCUContractID = "@mozilla.org/rdf/container-utils;1";
|
|
const kRDFCUIID = Components.interfaces.nsIRDFContainerUtils;
|
|
const kRDFCU = Components.classes[kRDFCUContractID].getService(kRDFCUIID);
|
|
|
|
/*
|
|
var immutableList = this.rdf.GetResource("NC:ImmutableBookmarkList");
|
|
var container = kRDFCU.MakeSeq(imDS, immutableList);
|
|
|
|
for (var i = rangeCount - 1; i >= 0; --i) {
|
|
boxObject.selection.getRangeAt(i, rangeMin, rangeMax);
|
|
for (var j = rangeMax.value; j >= rangeMin.value; --j) {
|
|
var resource = treeBuilder.getResourceAtIndex(j);
|
|
var type = this.getTypeAtIndex(j);
|
|
if (resource.Value == "NC:BookmarksRoot" || type == this.NC_NS + "IEFavoriteFolder")
|
|
continue;
|
|
if (type != this.NC_NS + "Bookmark" && type != this.NC_NS + "BookmarkSeparator" && type != this.NC_NS + "Folder") {
|
|
// This delete operation contains items which cannot be deleted
|
|
// for one reason or another. Make a list of the items which
|
|
// we can't delete, and show a dialog.
|
|
container.AppendElement(resource);
|
|
selectionContainsImmutableItems = true;
|
|
|
|
// Now we need to ensure that this item's parent chain is not
|
|
// part of the current selection so that we don't delete that. We
|
|
// preserve selection on any deletable items in the folder chain
|
|
// however, and these are removed.
|
|
for (var parentIndex = boxObject.view.getParentIndex(j);
|
|
parentIndex != -1;
|
|
parentIndex = boxObject.view.getParentIndex(parentIndex)) {
|
|
// Note that we don't combine this with the check in the
|
|
// |while| above, as this would mean that if you had a folder
|
|
// hierarchy consisting of:
|
|
//
|
|
// Folder -> [ selected ]
|
|
// Folder -> [ not selected ]
|
|
// Immutable item [ selected ]
|
|
//
|
|
// This code would not work and the containing folder would be
|
|
// deleted.
|
|
if (boxObject.selection.isSelected(parentIndex))
|
|
boxObject.selection.toggleSelect(parentIndex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Present a dialog showing any items that we can't delete.
|
|
// if (selectionContainsImmutableItems) {
|
|
// openDialog("chrome://communicator/content/bookmarks/deleteBookmark.xul", "", "modal=yes,resizable=no", imDS);
|
|
|
|
// Now clear the list of immutable items.
|
|
ksRDFC.Init(imDS, immutableList);
|
|
var count = ksRDFC.GetCount();
|
|
for (var i = 0; i < count; ++i)
|
|
ksRDFC.RemoveElementAt(i, false);
|
|
}
|
|
*/
|
|
const kPrefSvcContractID = "@mozilla.org/preferences;1";
|
|
const kPrefSvcIID = Components.interfaces.nsIPrefService;
|
|
var prefSvc = Components.classes[kPrefSvcContractID].getService(kPrefSvcIID);
|
|
var bookmarksPrefs = prefSvc.getBranch("browser.bookmarks.");
|
|
for (i = rangeCount - 1; i >= 0; --i) {
|
|
rangeMax = { };
|
|
rangeMin = { };
|
|
boxObject.selection.getRangeAt(i, rangeMin, rangeMax);
|
|
|
|
for (var j = rangeMax.value; j >= rangeMin.value; --j) {
|
|
var resource = treeBuilder.getResourceAtIndex(j);
|
|
if (resource.Value == "NC:BookmarksRoot")
|
|
continue;
|
|
// If we're removing the static root, make sure we set the pref that
|
|
// tells the bookmark service that it's been added so that after
|
|
// we remove it, the bookmark service doesn't try to add it back
|
|
// on subsequent launches.
|
|
if (resource.Value == "NC:SystemBookmarksStaticRoot")
|
|
bookmarksPrefs.setBoolPref("added_static_root", true);
|
|
|
|
var currType = this.getTypeAtIndex(j);
|
|
if (currType == this.NC_NS + "IEFavoriteFolder")
|
|
bookmarksPrefs.setBoolPref("import_system_favorites", false);
|
|
else if (currType != this.NC_NS + "Bookmark" &&
|
|
currType != this.NC_NS + "BookmarkSeparator" &&
|
|
currType != this.NC_NS + "Folder")
|
|
continue;
|
|
var parentIndex = boxObject.view.getParentIndex(j);
|
|
var parent;
|
|
if (parentIndex != -1)
|
|
parent = treeBuilder.getResourceAtIndex(parentIndex);
|
|
else {
|
|
// assume its parent is the root
|
|
parent = ksRDF.GetResource("NC:BookmarksRoot");
|
|
}
|
|
|
|
/*
|
|
Use RDF datasource command APIs instead of trying to
|
|
directly manipulate the bookmarks datasource graph via:
|
|
|
|
ksRDFC.Init(this.bookmarksDS, parent);
|
|
ksRDFC.RemoveElement(resource, true);
|
|
*/
|
|
|
|
try {
|
|
var args = [{ property: this.NC_NS + "parent",
|
|
resource: parent.Value }];
|
|
this.doBookmarksCommand(resource.Value, this.NC_NS_CMD + "deletebookmark", args);
|
|
}
|
|
catch (e) {
|
|
}
|
|
|
|
|
|
nextIndex = j;
|
|
}
|
|
}
|
|
|
|
// Select the next row
|
|
boxObject.selection.select(nextIndex);
|
|
]]></body>
|
|
</method>
|
|
<method name="openFindDialog">
|
|
<body><![CDATA[
|
|
openDialog("chrome://communicator/content/bookmarks/findBookmark.xul",
|
|
"FindBookmarksWindow",
|
|
"dialog=no,centerscreen,resizable=no,chrome,dependent");
|
|
]]></body>
|
|
</method>
|
|
<method name="canSendLink">
|
|
<body><![CDATA[
|
|
var selectedIndex = this.treeBoxObject.selection.currentIndex;
|
|
return (this.treeBoxObject.selection.count == 1 &&
|
|
!this.treeBoxObject.view.isContainer(selectedIndex) &&
|
|
this.getTypeAtIndex(selectedIndex) != this.NC_NS + "BookmarkSeparator");
|
|
]]></body>
|
|
</method>
|
|
<method name="sendLink">
|
|
<body><![CDATA[
|
|
const currentRes = this.currentRes;
|
|
var urlLiteral = this.db.GetTarget(currentRes, this.rdf.GetResource(this.NC_NS + "URL"), true).QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
|
|
var nameLiteral = this.db.GetTarget(currentRes, this.rdf.GetResource(this.NC_NS + "Name"), true).QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
|
|
sendLink(urlLiteral, nameLiteral);
|
|
]]></body>
|
|
</method>
|
|
<method name="getAllCmds">
|
|
<parameter name="aNodeID"/>
|
|
<body><![CDATA[
|
|
var type = BookmarksUtils.resolveType(aNodeID);
|
|
if (!type) {
|
|
if (aNodeID == "NC:PersonalToolbarFolder" || aNodeID == "NC:BookmarksRoot")
|
|
type = "http://home.netscape.com/NC-rdf#Folder";
|
|
else
|
|
return null;
|
|
}
|
|
var commands = [];
|
|
// menu order:
|
|
//
|
|
// bm_open
|
|
// bm_openfolder
|
|
// bm_openinnewwindow
|
|
// /* bm_openinnewtab not yet supported */
|
|
// ---------------------
|
|
// /* bm_find removed */
|
|
// bm_newfolder
|
|
// ---------------------
|
|
// bm_cut
|
|
// bm_copy
|
|
// bm_paste
|
|
// bm_fileBookmark
|
|
// ---------------------
|
|
// bm_delete
|
|
// bm_rename
|
|
// ---------------------
|
|
// bm_properties
|
|
switch (type) {
|
|
case "http://home.netscape.com/NC-rdf#BookmarkSeparator":
|
|
commands = ["bm_newfolder", "bm_separator",
|
|
"bm_cut", "bm_copy", "bm_paste", "bm_separator",
|
|
"bm_delete"];
|
|
break;
|
|
case "http://home.netscape.com/NC-rdf#Bookmark":
|
|
commands = ["bm_open", "bm_openinnewwindow", /* "bm_openinnewtab", */ "bm_separator",
|
|
"bm_newfolder", "bm_separator",
|
|
"bm_cut", "bm_copy", "bm_paste", "bm_fileBookmark", "bm_separator",
|
|
"bm_delete", "bm_rename", "bm_separator",
|
|
"bm_properties"];
|
|
break;
|
|
case "http://home.netscape.com/NC-rdf#Folder":
|
|
commands = ["bm_openfolder", "bm_openinnewwindow", "bm_separator",
|
|
"bm_newfolder", "bm_separator",
|
|
"bm_cut", "bm_copy", "bm_paste", "bm_fileBookmark", "bm_separator",
|
|
"bm_delete", "bm_rename", "bm_separator",
|
|
"bm_properties"];
|
|
break;
|
|
case "http://home.netscape.com/NC-rdf#IEFavoriteFolder":
|
|
commands = ["bm_openfolder", "bm_separator",
|
|
"bm_delete"];
|
|
break;
|
|
case "http://home.netscape.com/NC-rdf#IEFavorite":
|
|
commands = ["bm_open", "bm_openinnewwindow", /* "bm_openinnewtab", */ "bm_separator",
|
|
"bm_copy"];
|
|
break;
|
|
case "http://home.netscape.com/NC-rdf#FileSystemObject":
|
|
commands = ["bm_open", "bm_openinnewwindow", /* "bm_openinnewtab", */ "bm_separator",
|
|
"bm_copy"];
|
|
break;
|
|
default:
|
|
var source = this.rdf.GetResource(aNodeID);
|
|
return this.db.GetAllCmds(source);
|
|
}
|
|
return new CommandArrayEnumerator(commands);
|
|
]]></body>
|
|
</method>
|
|
|
|
<method name="flattenEnumerator">
|
|
<parameter name="aEnumerator"/>
|
|
<body><![CDATA[
|
|
if ("_index" in aEnumerator)
|
|
return aEnumerator._inner;
|
|
|
|
var temp = [];
|
|
while (aEnumerator.hasMoreElements())
|
|
temp.push(aEnumerator.getNext());
|
|
return temp;
|
|
]]></body>
|
|
</method>
|
|
<method name="findCommonNodes">
|
|
<parameter name="aNewArray"/>
|
|
<parameter name="aOldArray"/>
|
|
<body><![CDATA[
|
|
var common = [];
|
|
for (var i = 0; i < aNewArray.length; ++i) {
|
|
for (var j = 0; j < aOldArray.length; ++j) {
|
|
if (common.length > 0 && common[common.length-1] == aNewArray[i])
|
|
continue;
|
|
if (aNewArray[i] == aOldArray[j])
|
|
common.push(aNewArray[i]);
|
|
}
|
|
}
|
|
return common;
|
|
]]></body>
|
|
</method>
|
|
<method name="createMenuItem">
|
|
<parameter name="aDisplayName"/>
|
|
<parameter name="aCommandName"/>
|
|
<parameter name="aSelectedIndex"/>
|
|
<body><![CDATA[
|
|
const kXULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
|
var xulElement = document.createElementNS(kXULNS, "menuitem");
|
|
xulElement.setAttribute("cmd", aCommandName);
|
|
xulElement.setAttribute("command", "cmd_" + aCommandName.substring(this.NC_NS_CMD.length));
|
|
switch (aCommandName) {
|
|
case this.NC_NS_CMD + "bm_open":
|
|
xulElement.setAttribute("label", aDisplayName);
|
|
xulElement.setAttribute("default", "true");
|
|
break;
|
|
case this.NC_NS_CMD + "bm_openfolder":
|
|
aDisplayName = this.treeBoxObject.view.isContainerOpen(aSelectedIndex) ? this._bundle.GetStringFromName("cmd_bm_openfolder2") : aDisplayName;
|
|
xulElement.setAttribute("label", aDisplayName);
|
|
xulElement.setAttribute("default", "true");
|
|
break;
|
|
case this.NC_NS_CMD + "bm_renamebookmark":
|
|
if (!document.popupNode.hasAttribute("type")) {
|
|
xulElement.setAttribute("label", this._bundle.GetStringFromName("cmd_bm_renamebookmark2"));
|
|
xulElement.setAttribute("cmd", (this.NC_NS_CMD + "bm_editurl"));
|
|
}
|
|
else
|
|
xulElement.setAttribute("label", aDisplayName);
|
|
break;
|
|
default:
|
|
xulElement.setAttribute("label", aDisplayName);
|
|
break;
|
|
}
|
|
return xulElement;
|
|
]]></body>
|
|
</method>
|
|
<method name="getCommandName">
|
|
<parameter name="aCommand"/>
|
|
<body><![CDATA[
|
|
var cmdName = aCommand.substring(this.NC_NS_CMD.length);
|
|
try {
|
|
// Note: this will succeed only if there's a string in the bookmarks
|
|
// string bundle for this command name. Otherwise, <xul:stringbundle/>
|
|
// will throw, we'll catch & stifle the error, and look up the command
|
|
// name in the datasource.
|
|
return BookmarksUtils.getLocaleString("cmd_" + cmdName);
|
|
}
|
|
catch (e) {
|
|
// XXX - WORK TO DO HERE! (rjc will cry if we don't fix this)
|
|
// need to ask the ds for the commands for this node, however we don't
|
|
// have the right params. This is kind of a problem.
|
|
dump("*** BAD! EVIL! WICKED! NO! ACK! ARGH! ORGH!\n");
|
|
const rName = this.rdf.GetResource(this.NC_NS + "Name");
|
|
const rSource = this.rdf.GetResource(aCommand);
|
|
return this.db.GetTarget(rSource, rName, true).Value;
|
|
}
|
|
]]></body>
|
|
</method>
|
|
<method name="createContextMenu">
|
|
<parameter name="aEvent"/>
|
|
<body><![CDATA[
|
|
var popup = aEvent.target;
|
|
// clear out the old context menu contents (if any)
|
|
while (popup.hasChildNodes())
|
|
popup.removeChild(popup.firstChild);
|
|
|
|
var popupNode = document.popupNode;
|
|
var commonCommands = [];
|
|
var rangeCount = this.treeBoxObject.selection.getRangeCount();
|
|
for (var i = rangeCount - 1; i >= 0; --i) {
|
|
var minRange = {};
|
|
var maxRange = {};
|
|
this.treeBoxObject.selection.getRangeAt(i, minRange, maxRange);
|
|
for (var j = maxRange.value; j >= minRange.value; --j) {
|
|
var nodeURI = this.treeBuilder.getResourceAtIndex(j).Value;
|
|
var commands = this.getAllCmds(nodeURI);
|
|
if (!commands) {
|
|
aEvent.preventDefault();
|
|
return;
|
|
}
|
|
commands = this.flattenEnumerator(commands);
|
|
if (!commonCommands.length) commonCommands = commands;
|
|
commonCommands = this.findCommonNodes(commands, commonCommands);
|
|
}
|
|
}
|
|
if (!commonCommands.length) {
|
|
aEvent.preventDefault();
|
|
return;
|
|
}
|
|
|
|
// Now that we should have generated a list of commands that is valid
|
|
// for the entire selection, build a context menu.
|
|
for (i = 0; i < commonCommands.length; ++i) {
|
|
const kXULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
|
var currCommand = commonCommands[i].QueryInterface(Components.interfaces.nsIRDFResource).Value;
|
|
var element = null;
|
|
if (currCommand != this.NC_NS_CMD + "bm_separator") {
|
|
var commandName = this.getCommandName(currCommand);
|
|
var selectedIndex = this.treeBoxObject.selection.currentIndex;
|
|
element = this.createMenuItem(commandName, currCommand, selectedIndex);
|
|
}
|
|
else if (i != 0 && i < commonCommands.length-1) {
|
|
// Never append a separator as the first or last element in a context
|
|
// menu.
|
|
element = document.createElementNS(kXULNS, "menuseparator");
|
|
}
|
|
|
|
if (element)
|
|
popup.appendChild(element);
|
|
}
|
|
]]></body>
|
|
</method>
|
|
<method name="openPropertiesForItem">
|
|
<body><![CDATA[
|
|
// XXX if not bookmarks separator
|
|
var itemURI = this.treeBuilder.getResourceAtIndex(this.treeBoxObject.selection.currentIndex).Value;
|
|
openDialog("chrome://communicator/content/bookmarks/bm-props.xul",
|
|
"", "centerscreen,chrome,dialog=no,resizable=no,dependent",
|
|
itemURI);
|
|
]]></body>
|
|
</method>
|
|
<method name="setAsPersonalToolbarFolder">
|
|
<body><![CDATA[
|
|
var selectedURI = this.treeBuilder.getResourceAtIndex(this.treeBoxObject.selection.currentIndex).Value;
|
|
var args = [];
|
|
this.doBookmarksCommand(selectedURI, this.NC_NS_CMD + "setpersonaltoolbarfolder", args);
|
|
|
|
]]></body>
|
|
</method>
|
|
<method name="setAsNewSearchFolder">
|
|
<body><![CDATA[
|
|
var selectedURI = this.treeBuilder.getResourceAtIndex(this.treeBoxObject.selection.currentIndex).Value;
|
|
var args = [];
|
|
this.doBookmarksCommand(selectedURI, this.NC_NS_CMD + "setnewsearchfolder", args);
|
|
]]></body>
|
|
</method>
|
|
<method name="setAsNewBookmarkFolder">
|
|
<body><![CDATA[
|
|
var selectedURI = this.treeBuilder.getResourceAtIndex(this.treeBoxObject.selection.currentIndex).Value;
|
|
var args = [];
|
|
this.doBookmarksCommand(selectedURI, this.NC_NS_CMD + "setnewbookmarkfolder", args);
|
|
]]></body>
|
|
</method>
|
|
<method name="addBookmark">
|
|
<body><![CDATA[
|
|
const currentIndex = this.currentIndex;
|
|
|
|
var parentIndex;
|
|
if (this.treeBoxObject.view.rowCount) {
|
|
if (this.treeBoxObject.view.isContainerOpen(currentIndex))
|
|
parentIndex = currentIndex;
|
|
else
|
|
parentIndex = this.treeBoxObject.view.getParentIndex(currentIndex);
|
|
}
|
|
else
|
|
parentIndex = -1;
|
|
var parentURI;
|
|
if (parentIndex == -1)
|
|
parentURI = this.rdf.GetResource("NC:BookmarksRoot").Value;
|
|
else
|
|
parentURI = this.treeBuilder.getResourceAtIndex(parentIndex).Value;
|
|
|
|
var rv = { newBookmark: null };
|
|
openDialog("chrome://communicator/content/bookmarks/addBookmark.xul", "",
|
|
"centerscreen,chrome,modal=yes,dialog=yes,resizable=no", null, null, parentURI, null, "newBookmark", rv);
|
|
if (rv.newBookmark) {
|
|
var ind = this.treeBuilder.getIndexOfResource(rv.newBookmark);
|
|
this.treeBoxObject.selection.select(ind);
|
|
}
|
|
]]></body>
|
|
</method>
|
|
<method name="fileBookmark">
|
|
<body><![CDATA[
|
|
// XXX folder arg
|
|
var rv = { selectedFolder: null };
|
|
openDialog("chrome://communicator/content/bookmarks/addBookmark.xul", "",
|
|
"centerscreen,chrome,modal=yes,dialog=yes,resizable=yes", null, null, null, null, "selectFolder", rv);
|
|
if (rv.selectedFolder) {
|
|
var rangeCount = this.treeBoxObject.selection.getRangeCount();
|
|
for (var k = rangeCount - 1; k >= 0; --k) {
|
|
var rangeMin = {};
|
|
var rangeMax = {};
|
|
this.treeBoxObject.selection.getRangeAt(k, rangeMin, rangeMax);
|
|
for (var i = rangeMax.value; i >= rangeMin.value; --i) {
|
|
var selected = this.treeBuilder.getResourceAtIndex(i);
|
|
if (selected.Value == rv.selectedFolder)
|
|
return; // Selection contains the target folder. Just fail silently.
|
|
var additiveFlag = false;
|
|
var parentIndex = this.treeBoxObject.view.getParentIndex(i);
|
|
var parentURI;
|
|
if (parentIndex == -1)
|
|
parentURI = this.rdf.GetResource("NC:BookmarksRoot").Value;
|
|
else
|
|
parentURI = this.treeBuilder.getResourceAtIndex(parentIndex).Value;
|
|
this.moveBookmark(selected.Value, parentURI, rv.selectedFolder);
|
|
// gBookmarksShell.selectFolderItem(rv.selectedFolder, selected.Value, additiveFlag);
|
|
if (!additiveFlag) additiveFlag = true;
|
|
}
|
|
}
|
|
this.flushBMDatasource();
|
|
}
|
|
]]></body>
|
|
</method>
|
|
<method name="moveBookmark">
|
|
<parameter name="aBookmarkURI"/>
|
|
<parameter name="aFromFolderURI"/>
|
|
<parameter name="aToFolderURI"/>
|
|
<body><![CDATA[
|
|
const kRDFCContractID = "@mozilla.org/rdf/container;1";
|
|
const kRDFCIID = Components.interfaces.nsIRDFContainer;
|
|
const kRDFC = Components.classes[kRDFCContractID].getService(kRDFCIID);
|
|
const krSrc = this.rdf.GetResource(aBookmarkURI);
|
|
const krOldParent = this.rdf.GetResource(aFromFolderURI);
|
|
const krNewParent = this.rdf.GetResource(aToFolderURI);
|
|
kRDFC.Init(this.bookmarksDS, krNewParent);
|
|
kRDFC.AppendElement(krSrc);
|
|
kRDFC.Init(this.bookmarksDS, krOldParent);
|
|
kRDFC.RemoveElement(krSrc, true);
|
|
]]></body>
|
|
</method>
|
|
<method name="importBookmarks">
|
|
<body><![CDATA[
|
|
try {
|
|
const kFilePickerContractID = "@mozilla.org/filepicker;1";
|
|
const kFilePickerIID = Components.interfaces.nsIFilePicker;
|
|
const kFilePicker = Components.classes[kFilePickerContractID].createInstance(kFilePickerIID);
|
|
|
|
const kTitle = this._bundle.GetStringFromName("SelectImport");
|
|
kFilePicker.init(window, kTitle, kFilePickerIID["modeOpen"]);
|
|
kFilePicker.appendFilters(kFilePickerIID.filterHTML | kFilePickerIID.filterAll);
|
|
var fileName;
|
|
if (kFilePicker.show() != kFilePickerIID.returnCancel) {
|
|
fileName = kFilePicker.fileURL.spec;
|
|
if (!fileName) return;
|
|
}
|
|
else return;
|
|
}
|
|
catch (e) {
|
|
return;
|
|
}
|
|
var seln = null;
|
|
try {
|
|
seln = this.treeBuilder.getResourceAtIndex(this.treeBoxObject.selection.currentIndex).Value;
|
|
}
|
|
catch(ex) {
|
|
seln = this.rdf.GetResource("NC:BookmarksRoot").Value;
|
|
}
|
|
var args = [{ property: this.NC_NS + "URL", literal: fileName}];
|
|
this.doBookmarksCommand(seln, this.NC_NS_CMD + "import", args);
|
|
]]></body>
|
|
</method>
|
|
<method name="exportBookmarks">
|
|
<body><![CDATA[
|
|
try {
|
|
const kFilePickerContractID = "@mozilla.org/filepicker;1";
|
|
const kFilePickerIID = Components.interfaces.nsIFilePicker;
|
|
const kFilePicker = Components.classes[kFilePickerContractID].createInstance(kFilePickerIID);
|
|
|
|
const kTitle = this._bundle.GetStringFromName("EnterExport");
|
|
const kRDFExportIndex = 2;
|
|
kFilePicker.init(window, kTitle, kFilePickerIID["modeSave"]);
|
|
kFilePicker.appendFilters(kFilePickerIID.filterHTML | kFilePickerIID.filterAll);
|
|
kFilePicker.appendFilter("RDF", "*.rdf"); // index 2: kRDFExportIndex
|
|
kFilePicker.defaultString = "bookmarks.html";
|
|
var fileName;
|
|
if (kFilePicker.show() != kFilePickerIID.returnCancel) {
|
|
fileName = kFilePicker.fileURL.spec;
|
|
if (!fileName) return;
|
|
}
|
|
else return;
|
|
}
|
|
catch (e) {
|
|
return;
|
|
}
|
|
var seln = null;
|
|
try {
|
|
seln = this.treeBuilder.getResourceAtIndex(this.treeBoxObject.selection.currentIndex).Value;
|
|
}
|
|
catch(ex) {
|
|
seln = this.rdf.GetResource("NC:BookmarksRoot").Value;
|
|
}
|
|
var args = [{ property: this.NC_NS + "URL", literal: fileName},
|
|
{ property: this.RDF_NS + "type",
|
|
literal: (kFilePicker.filterIndex == kRDFExportIndex) ? "RDF" : "HTML"}];
|
|
this.doBookmarksCommand(seln, this.NC_NS_CMD + "export", args);
|
|
]]></body>
|
|
</method>
|
|
<method name="openFolderInNewWindow">
|
|
<body><![CDATA[
|
|
var selectedIndex = this.treeBoxObject.selection.currentIndex;
|
|
var selectedURI = this.treeBuilder.getResourceAtIndex(selectedIndex).Value;
|
|
openDialog("chrome://communicator/content/bookmarks/bookmarks.xul",
|
|
"", "chrome,all,dialog=no", selectedURI);
|
|
]]>
|
|
</body>
|
|
</method>
|
|
<method name="createNewSeparator">
|
|
<body><![CDATA[
|
|
var currIndex = this.treeBoxObject.selection.currentIndex;
|
|
if (currIndex == -1)
|
|
currIndex = this.treeBoxObject.view.rowCount - 1;
|
|
var parentIndex = this.treeBoxObject.view.getParentIndex(currIndex);
|
|
var parentValue;
|
|
if (parentIndex == -1)
|
|
parentValue = this.rdf.GetResource("NC:BookmarksRoot").Value;
|
|
else
|
|
parentValue = this.treeBuilder.getResourceAtIndex(parentIndex).Value;
|
|
args = [{ property: this.NC_NS + "parent",
|
|
resource: parentValue }];
|
|
this.doBookmarksCommand(this.treeBuilder.getResourceAtIndex(currIndex).Value,
|
|
this.NC_NS_CMD + "newseparator", args);
|
|
]]></body>
|
|
</method>
|
|
<method name="createNewFolder">
|
|
<body><![CDATA[
|
|
const kPromptSvcContractID = "@mozilla.org/embedcomp/prompt-service;1";
|
|
const kPromptSvcIID = Components.interfaces.nsIPromptService;
|
|
const kPromptSvc = Components.classes[kPromptSvcContractID].getService(kPromptSvcIID);
|
|
var defaultValue = this._bundle.GetStringFromName("ile_newfolder");
|
|
var dialogTitle = this._bundle.GetStringFromName("newfolder_dialog_title");
|
|
var dialogMsg = this._bundle.GetStringFromName("newfolder_dialog_msg");
|
|
var stringValue = { value: defaultValue };
|
|
var relativeIndex = this.currentIndex;
|
|
const currentIndex = this.currentIndex;
|
|
var parentRes;
|
|
var isParent = false;
|
|
if (kPromptSvc.prompt(window, dialogTitle, dialogMsg, stringValue, null, { value: 0 })) {
|
|
if (currentIndex != -1 && currentIndex < this.treeBoxObject.view.rowCount) {
|
|
// If it's an open container, the relative index should be that of the last child.
|
|
if (this.treeBoxObject.view.isContainerOpen(currentIndex)) {
|
|
isParent = true;
|
|
var index = currentIndex + 1;
|
|
while (index < this.treeBoxObject.view.rowCount
|
|
&& this.treeBoxObject.view.getParentIndex(index) == currentIndex)
|
|
++index;
|
|
relativeIndex = index - 1;
|
|
}
|
|
if (isParent) {
|
|
parentRes = this.treeBuilder.getResourceAtIndex(currentIndex);
|
|
} else {
|
|
parentRes = this.parentRes;
|
|
}
|
|
}
|
|
else {
|
|
parentRes = this.rdf.GetResource("NC:BookmarksRoot");
|
|
relativeIndex = -1;
|
|
}
|
|
var args = [{ property: this.NC_NS + "parent",
|
|
resource: parentRes.Value },
|
|
{ property: this.NC_NS + "Name",
|
|
literal: stringValue.value }];
|
|
this.bookmarksDS.AddObserver(this.newFolderRDFObserver);
|
|
var relativeRes;
|
|
if (relativeIndex != -1)
|
|
relativeRes = this.treeBuilder.getResourceAtIndex(relativeIndex).Value;
|
|
else
|
|
relativeRes = this.rdf.GetResource("NC:BookmarksRoot").Value;
|
|
|
|
this.doBookmarksCommand(relativeRes, this.NC_NS_CMD + "newfolder", args);
|
|
this.bookmarksDS.RemoveObserver(this.newFolderRDFObserver);
|
|
}
|
|
]]></body>
|
|
</method>
|
|
|
|
<method name="validOpenClickConditions">
|
|
<parameter name="aEvent"/>
|
|
<body><![CDATA[
|
|
if (aEvent.button != 0 || aEvent.originalTarget.localName != "treechildren")
|
|
return false;
|
|
var row = {};
|
|
var col = {};
|
|
var obj = {};
|
|
this.treeBoxObject.getCellAt(aEvent.clientX, aEvent.clientY, row, col, obj);
|
|
if (row.value == -1 || obj.value == "twisty")
|
|
return false;
|
|
return true;
|
|
]]></body>
|
|
</method>
|
|
|
|
// requires utilityOverlay.js if opening in new window for opentopwin()
|
|
<method name="openItem">
|
|
<parameter name="aEvent"/>
|
|
<parameter name="aInNewWindow"/>
|
|
<parameter name="aOpenGroups"/>
|
|
<body><![CDATA[
|
|
var groupRes = this.rdf.GetResource(this.NC_NS + "FolderGroup");
|
|
var groupTarget = this.db.GetTarget(this.treeBuilder.getResourceAtIndex(this.treeBoxObject.selection.currentIndex),
|
|
groupRes, true);
|
|
|
|
if (groupTarget && (!aOpenGroups || aEvent.detail > 1))
|
|
return;
|
|
|
|
if (!groupTarget && this.treeBoxObject.view.isContainer(this.treeBoxObject.selection.currentIndex)) {
|
|
if (this.clickCount == 1) {
|
|
var row = { };
|
|
var col = { };
|
|
var elt = { };
|
|
this.treeBoxObject.getCellAt(aEvent.clientX, aEvent.clientY, row, col, elt);
|
|
if (row.value >= 0)
|
|
this.treeBoxObject.view.toggleOpenState(row.value);
|
|
}
|
|
return;
|
|
}
|
|
|
|
var urlRes, urlValue, w;
|
|
if (aEvent && aEvent.altKey)
|
|
this.openPropertiesForItem();
|
|
else if (aInNewWindow) {
|
|
var seln = this.treeBoxObject.selection;
|
|
var rangeCount = seln.getRangeCount();
|
|
for (var i = rangeCount - 1; i >= 0; --i) {
|
|
var rangeMin = { };
|
|
var rangeMax = { };
|
|
seln.getRangeAt(i, rangeMin, rangeMax);
|
|
for (var k = rangeMax.value; k >= rangeMin.value; --k) {
|
|
groupTarget = this.db.GetTarget(this.treeBuilder.getResourceAtIndex(k),
|
|
groupRes, true);
|
|
|
|
if (!groupTarget) {
|
|
urlRes = this.rdf.GetResource(this.NC_NS + "URL");
|
|
urlValue = this.db.GetTarget(this.treeBuilder.getResourceAtIndex(k), urlRes, true).QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
|
|
// Ignore "NC:" and empty urls
|
|
if (!urlValue || urlValue.substring(0,3) == "NC:") return;
|
|
}
|
|
else
|
|
urlValue = "about:blank";
|
|
|
|
w = openDialog(this._browserURL, "_blank", "chrome,all,dialog=no", urlValue);
|
|
if (groupTarget)
|
|
w.OpenBookmarkGroupFromResource(this.treeBuilder.getResourceAtIndex(k),
|
|
this.db, this.rdf);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
groupTarget = this.db.GetTarget(this.currentRes, groupRes, true);
|
|
if (!groupTarget) {
|
|
urlRes = this.rdf.GetResource(this.NC_NS + "URL");
|
|
urlValue = this.db.GetTarget(this.currentRes, urlRes, true).QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
|
|
// Ignore "NC:" and empty urls
|
|
if (!urlValue || urlValue.substring(0,3) == "NC:") return;
|
|
}
|
|
else
|
|
urlValue = "about:blank";
|
|
|
|
if (groupTarget) {
|
|
w = getTopWin();
|
|
w.focus();
|
|
w.OpenBookmarkGroupFromResource(this.currentRes, this.db, this.rdf);
|
|
}
|
|
else {
|
|
openTopWin(urlValue);
|
|
}
|
|
}
|
|
if (aEvent)
|
|
aEvent.preventBubble();
|
|
]]></body>
|
|
</method>
|
|
<method name="canPaste">
|
|
<body><![CDATA[
|
|
// XXXben
|
|
return true;
|
|
]]></body>
|
|
</method>
|
|
<method name="searchBookmarks">
|
|
<parameter name="aInput"/>
|
|
<body><![CDATA[
|
|
if (!aInput)
|
|
this.tree.setAttribute("ref", "NC:BookmarksRoot");
|
|
else {
|
|
const ref = "find:datasource=rdf:bookmarks&match=http://home.netscape.com/NC-rdf#Name&method=contains&text=";
|
|
this.tree.setAttribute("ref", ref + escape(aInput));
|
|
}
|
|
]]></body>
|
|
</method>
|
|
</implementation>
|
|
</binding>
|
|
<!-- Full Bookmarks Tree, multi-columned -->
|
|
<!-- Localize column labels! -->
|
|
<binding id="bookmarks-tree-full" extends="chrome://communicator/content/bookmarks/bookmarks.xml#bookmarks-tree">
|
|
<xbl:content xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:xbl="http://www.mozilla.org/xbl"
|
|
contextmenu="_child">
|
|
<!-- XXXben need focus event handler for cmd update -->
|
|
<menupopup id="bmContext"
|
|
onpopupshowing="this.parentNode.createContextMenu(event);"/>
|
|
<vbox flex="1">
|
|
<tree anonid="bookmarks-tree" flex="1" class="plain" enableColumnDrag="true"
|
|
datasources="rdf:bookmarks rdf:internetsearch rdf:files rdf:localsearch" ref="NC:BookmarksRoot" flags="dont-build-content"
|
|
onkeypress="if (event.keyCode == 13) this.parentNode.parentNode.openItem(event, false, false);"
|
|
ondblclick="if (this.parentNode.parentNode.validOpenClickConditions(event)) this.parentNode.parentNode.openItem(event, false, false);"
|
|
ondraggesture="if (event.originalTarget.localName == 'treechildren') nsDragAndDrop.startDrag(event, this.parentNode.parentNode.DNDObserver);"
|
|
onselect="this.treeBoxObject.view.selectionChanged();">
|
|
<template xmlns:nc="http://home.netscape.com/NC-rdf#">
|
|
<rule rdf:type="http://home.netscape.com/NC-rdf#BookmarkSeparator">
|
|
<treechildren>
|
|
<treeitem uri="rdf:*">
|
|
<treerow properties="rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#type separator"/>
|
|
</treeitem>
|
|
</treechildren>
|
|
</rule>
|
|
<rule nc:FolderGroup="true">
|
|
<treechildren>
|
|
<treeitem uri="rdf:*">
|
|
<treerow properties="rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#type rdf:http://home.netscape.com/NC-rdf#loading rdf:http://home.netscape.com/WEB-rdf#status">
|
|
<treecell properties="group" label="rdf:http://home.netscape.com/NC-rdf#Name" />
|
|
<treecell label="rdf:http://home.netscape.com/NC-rdf#URL" />
|
|
<treecell label="rdf:http://home.netscape.com/NC-rdf#ShortcutURL" />
|
|
<treecell label="rdf:http://home.netscape.com/NC-rdf#Description" />
|
|
<treecell label="rdf:http://home.netscape.com/WEB-rdf#LastVisitDate"/>
|
|
<treecell label="rdf:http://home.netscape.com/NC-rdf#BookmarkAddDate" />
|
|
<treecell label="rdf:http://home.netscape.com/NC-rdf#LastModifiedDate" />
|
|
</treerow>
|
|
</treeitem>
|
|
</treechildren>
|
|
</rule>
|
|
<rule>
|
|
<treechildren>
|
|
<treeitem uri="rdf:*">
|
|
<treerow properties="rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#type rdf:http://home.netscape.com/NC-rdf#loading rdf:http://home.netscape.com/WEB-rdf#status">
|
|
<treecell label="rdf:http://home.netscape.com/NC-rdf#Name" />
|
|
<treecell label="rdf:http://home.netscape.com/NC-rdf#URL" />
|
|
<treecell label="rdf:http://home.netscape.com/NC-rdf#ShortcutURL" />
|
|
<treecell label="rdf:http://home.netscape.com/NC-rdf#Description" />
|
|
<treecell label="rdf:http://home.netscape.com/WEB-rdf#LastVisitDate"/>
|
|
<treecell label="rdf:http://home.netscape.com/NC-rdf#BookmarkAddDate" />
|
|
<treecell label="rdf:http://home.netscape.com/NC-rdf#LastModifiedDate" />
|
|
</treerow>
|
|
</treeitem>
|
|
</treechildren>
|
|
</rule>
|
|
</template>
|
|
<treecols anonid="treecols">
|
|
<treecol id="Name" label="&treecol.name.label;" flex="1" primary="true"
|
|
class="sortDirectionIndicator"
|
|
persist="width hidden sortActive sortDirection ordinal"
|
|
sort="rdf:http://home.netscape.com/NC-rdf#Name"
|
|
sortActive="true" sortDirection="none"/>
|
|
<splitter class="tree-splitter" />
|
|
<treecol id="URL" label="&treecol.url.label;"
|
|
flex="1" class="sortDirectionIndicator"
|
|
sort="rdf:http://home.netscape.com/NC-rdf#URL"
|
|
persist="width hidden sortActive sortDirection ordinal" />
|
|
<splitter class="tree-splitter" />
|
|
<treecol id="ShortcutURL" label="&treecol.shortcut.label;"
|
|
hidden="true" flex="1" class="sortDirectionIndicator"
|
|
persist="hidden width sortActive sortDirection ordinal"
|
|
sort="rdf:http://home.netscape.com/NC-rdf#ShortcutURL"/>
|
|
<splitter class="tree-splitter"/>
|
|
<treecol id="Description" label="&treecol.description.label;"
|
|
hidden="true" flex="1" class="sortDirectionIndicator"
|
|
persist="hidden width sortActive sortDirection ordinal"
|
|
sort="rdf:http://home.netscape.com/NC-rdf#Description"/>
|
|
<splitter class="tree-splitter"/>
|
|
<treecol id="AddDate" label="&treecol.addedon.label;"
|
|
hidden="true" flex="1" class="sortDirectionIndicator"
|
|
sort="rdf:http://home.netscape.com/NC-rdf#BookmarkAddDate"
|
|
persist="width hidden sortActive sortDirection ordinal" />
|
|
<splitter class="tree-splitter" />
|
|
<treecol id="LastModDate" label="&treecol.lastmod.label;"
|
|
hidden="true" flex="1" class="sortDirectionIndicator"
|
|
sort="rdf:http://home.netscape.com/NC-rdf#LastModifiedDate"
|
|
persist="width hidden sortActive sortDirection ordinal" />
|
|
<splitter class="tree-splitter" />
|
|
<treecol id="LastVisitDate" label="&treecol.lastvisit.label;"
|
|
hidden="true" flex="1" class="sortDirectionIndicator"
|
|
sort="rdf:http://home.netscape.com/NC-rdf#LastVisitDate"
|
|
persist="width hidden sortActive sortDirection ordinal" />
|
|
</treecols>
|
|
</tree>
|
|
<statusbar class="chromeclass-status" xbl:inherits="hidden=hidestatusbar" hidden="false">
|
|
<statusbarpanel anonid="statusbar-text" flex="1"/>
|
|
</statusbar>
|
|
</vbox>
|
|
</xbl:content>
|
|
<implementation>
|
|
<field name="clickCount">2</field>
|
|
</implementation>
|
|
</binding>
|
|
<!-- Single column tree -->
|
|
<binding id="bookmarks-tree-name" extends="chrome://communicator/content/bookmarks/bookmarks.xml#bookmarks-tree">
|
|
<xbl:content xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
|
xmlns:xbl="http://www.mozilla.org/xbl" contextmenu="_child">
|
|
<menupopup id="bmContext"
|
|
onpopupshowing="this.parentNode.createContextMenu(event);"/>
|
|
<tree anonid="bookmarks-tree" flex="1" hidecolumnpicker="true" class="plain"
|
|
datasources="rdf:bookmarks rdf:internetsearch rdf:files rdf:localsearch" ref="NC:BookmarksRoot" flags="dont-build-content"
|
|
onkeypress="if (event.keyCode == 13) this.parentNode.openItem(event, false, true);"
|
|
ondraggesture="if (event.originalTarget.localName == 'treechildren') nsDragAndDrop.startDrag(event, this.parentNode.DNDObserver);"
|
|
onclick="if (this.parentNode.validOpenClickConditions(event)) this.parentNode.openItem(event, false, true);"
|
|
onselect="this.parentNode.treeBoxObject.view.selectionChanged();">
|
|
<template xmlns:nc="http://home.netscape.com/NC-rdf#">
|
|
<rule rdf:type="http://home.netscape.com/NC-rdf#BookmarkSeparator">
|
|
<treechildren>
|
|
<treeitem uri="rdf:*">
|
|
<treerow properties="rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#type separator" />
|
|
</treeitem>
|
|
</treechildren>
|
|
</rule>
|
|
<rule nc:FolderGroup="true">
|
|
<treechildren>
|
|
<treeitem uri="rdf:*">
|
|
<treerow properties="rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#type rdf:http://home.netscape.com/NC-rdf#loading rdf:http://home.netscape.com/WEB-rdf#status">
|
|
<treecell properties="group hidetwisty" label="rdf:http://home.netscape.com/NC-rdf#Name" />
|
|
<treecell label="rdf:http://home.netscape.com/NC-rdf#URL" />
|
|
<treecell label="rdf:http://home.netscape.com/NC-rdf#ShortcutURL" />
|
|
<treecell label="rdf:http://home.netscape.com/NC-rdf#Description" />
|
|
<treecell label="rdf:http://home.netscape.com/WEB-rdf#LastVisitDate"/>
|
|
<treecell label="rdf:http://home.netscape.com/NC-rdf#BookmarkAddDate" />
|
|
<treecell label="rdf:http://home.netscape.com/NC-rdf#LastModifiedDate" />
|
|
</treerow>
|
|
</treeitem>
|
|
</treechildren>
|
|
</rule>
|
|
<rule>
|
|
<treechildren>
|
|
<treeitem uri="rdf:*">
|
|
<treerow properties="rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#type rdf:http://home.netscape.com/NC-rdf#loading rdf:http://home.netscape.com/WEB-rdf#status">
|
|
<treecell label="rdf:http://home.netscape.com/NC-rdf#Name" />
|
|
<treecell label="rdf:http://home.netscape.com/NC-rdf#URL" />
|
|
<treecell label="rdf:http://home.netscape.com/NC-rdf#ShortcutURL" />
|
|
<treecell label="rdf:http://home.netscape.com/NC-rdf#Description" />
|
|
<treecell label="rdf:http://home.netscape.com/WEB-rdf#LastVisitDate"/>
|
|
<treecell label="rdf:http://home.netscape.com/NC-rdf#BookmarkAddDate" />
|
|
<treecell label="rdf:http://home.netscape.com/NC-rdf#LastModifiedDate" />
|
|
</treerow>
|
|
</treeitem>
|
|
</treechildren>
|
|
</rule>
|
|
</template>
|
|
<treecols anonid="treecols">
|
|
<treecol id="Name" label="&treecol.name.label;" flex="1" primary="true"
|
|
class="sortDirectionIndicator"
|
|
persist="width hidden sortActive sortDirection ordinal"
|
|
sort="rdf:http://home.netscape.com/NC-rdf#Name"
|
|
sortActive="true" sortDirection="none"/>
|
|
<splitter class="tree-splitter" />
|
|
<treecol id="URL" label="&treecol.url.label;"
|
|
flex="1" class="sortDirectionIndicator"
|
|
sort="rdf:http://home.netscape.com/NC-rdf#URL"
|
|
hidden="true"/>
|
|
<splitter class="tree-splitter" />
|
|
<treecol id="ShortcutURL" label="&treecol.shortcut.label;"
|
|
hidden="true" flex="1" class="sortDirectionIndicator"
|
|
sort="rdf:http://home.netscape.com/NC-rdf#ShortcutURL"/>
|
|
<splitter class="tree-splitter" />
|
|
<treecol id="Description" label="&treecol.description.label;"
|
|
hidden="true" flex="1" class="sortDirectionIndicator"
|
|
sort="rdf:http://home.netscape.com/NC-rdf#Description"/>
|
|
<splitter class="tree-splitter" />
|
|
<treecol id="AddDate" label="&treecol.addedon.label;"
|
|
hidden="true" flex="1" class="sortDirectionIndicator"
|
|
sort="rdf:http://home.netscape.com/NC-rdf#BookmarkAddDate" />
|
|
<splitter class="tree-splitter" />
|
|
<treecol id="LastModDate" label="&treecol.lastmod.label;"
|
|
hidden="true" flex="1" class="sortDirectionIndicator"
|
|
sort="rdf:http://home.netscape.com/NC-rdf#LastModifiedDate" />
|
|
<splitter class="tree-splitter" />
|
|
<treecol id="LastVisitDate" label="&treecol.lastvisit.label;"
|
|
hidden="true" flex="1" class="sortDirectionIndicator"
|
|
sort="rdf:http://home.netscape.com/NC-rdf#LastVisitDate" />
|
|
</treecols>
|
|
</tree>
|
|
</xbl:content>
|
|
<implementation>
|
|
<field name="clickCount">1</field>
|
|
</implementation>
|
|
</binding>
|
|
<!-- Tree with folders only -->
|
|
<binding id="bookmarks-tree-folders" extends="chrome://communicator/content/bookmarks/bookmarks.xml#bookmarks-tree">
|
|
<xbl:content xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:xbl="http://www.mozilla.org/xbl">
|
|
<tree anonid="bookmarks-tree" flex="1" hidecolumnpicker="true"
|
|
datasources="rdf:bookmarks rdf:internetsearch rdf:files rdf:localsearch" ref="NC:BookmarksRoot" flags="dont-build-content"
|
|
onselect="this.parentNode.treeBoxObject.view.selectionChanged();">
|
|
<template>
|
|
<rule iscontainer="true">
|
|
<treechildren>
|
|
<treeitem uri="rdf:*">
|
|
<treerow properties="rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#type rdf:http://home.netscape.com/NC-rdf#loading rdf:http://home.netscape.com/WEB-rdf#status">
|
|
<treecell label="rdf:http://home.netscape.com/NC-rdf#Name" />
|
|
</treerow>
|
|
</treeitem>
|
|
</treechildren>
|
|
</rule>
|
|
</template>
|
|
<treecols anonid="treecols">
|
|
<treecol id="Name" label="&treecol.name.label;" flex="1" primary="true"
|
|
class="sortDirectionIndicator" persist="width hidden sortActive sortDirection"
|
|
sort="rdf:http://home.netscape.com/NC-rdf#Name"
|
|
sortActive="true" sortDirection="none"/>
|
|
</treecols>
|
|
</tree>
|
|
</xbl:content>
|
|
<implementation>
|
|
<field name="clickCount">1</field>
|
|
</implementation>
|
|
</binding>
|
|
</bindings>
|
|
<!--
|
|
|
|
API:
|
|
- root ref
|
|
- datasources
|
|
- columns
|
|
- click count
|
|
- sort
|
|
- selection
|
|
- default action oncommand
|
|
- context menu
|
|
- insert, remove bookmarks
|
|
-
|
|
|
|
//-->
|
|
<!--
|
|
ILE:
|
|
- impl ILE on tree.xml
|
|
//-->
|
|
<!--
|
|
Command handling:
|
|
- impl |nsIController|
|
|
- actual controller implemented by client which intercepts commands and provides
|
|
special handling for things like open in new browser etc.
|
|
- client can alternatively use the built in controller for default functionality.
|
|
- decisions:
|
|
Implementation pattern:
|
|
client:
|
|
(A) bookmarksUIElement.prototype.doCommand = function () { .. }
|
|
OR
|
|
(B) var ctrlr = { doCommand: function () { bookmarksUIElement.doCommand(); }
|
|
Tend to prefer (B) as it supports delegation
|
|
//-->
|