зеркало из https://github.com/mozilla/pjs.git
New bookmarks window stuff, not yet part of build.
This commit is contained in:
Родитель
95defc7d0e
Коммит
530f85f222
|
@ -0,0 +1,140 @@
|
|||
/* -*- Mode: C; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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>
|
||||
* Josh Soref <timeless@mac.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Style rules for bookmarks tree items. Ideally this would be usage agnostic, but
|
||||
* there's window/panel specific cruft in here too.
|
||||
**/
|
||||
.treecell-bookmark
|
||||
{
|
||||
list-style-image : inherit;
|
||||
}
|
||||
|
||||
.treeitem-bookmark
|
||||
{
|
||||
list-style-image : url("chrome://communicator/skin/bookmarks/location.gif");
|
||||
}
|
||||
|
||||
.treeitem-bookmark[container="true"][open="true"][loading="true"]
|
||||
{
|
||||
list-style-image : url("chrome://global/skin/loading.gif") ! important ;
|
||||
}
|
||||
|
||||
.treeitem-bookmark[status="new"]
|
||||
{
|
||||
list-style-image : url("chrome://communicator/skin/bookmarks/bookmark-item-updated.gif") ! important ;
|
||||
}
|
||||
|
||||
.treeitem-bookmark[type="http://home.netscape.com/NC-rdf#Folder"],
|
||||
.treeitem-bookmark[container="true"]
|
||||
{
|
||||
list-style-image : url("chrome://communicator/skin/bookmarks/bookmark-folder-closed.gif");
|
||||
}
|
||||
|
||||
.treeitem-bookmark[type="http://home.netscape.com/NC-rdf#Folder"][open="true"]
|
||||
{
|
||||
list-style-image : url("chrome://communicator/skin/bookmarks/bookmark-folder-open.gif");
|
||||
}
|
||||
|
||||
.treeitem-bookmark[container="true"][open="true"]
|
||||
{
|
||||
list-style-image : url("chrome://communicator/skin/bookmarks/bookmark-folder-open.gif");
|
||||
}
|
||||
|
||||
.treeitem-bookmark[type="http://home.netscape.com/NC-rdf#Folder"][id="NC:PersonalToolbarFolder"]
|
||||
{
|
||||
list-style-image : url("chrome://communicator/skin/bookmarks/personal-folder-closed.gif") !important;
|
||||
}
|
||||
|
||||
.treeitem-bookmark[type="http://home.netscape.com/NC-rdf#Folder"][id="NC:PersonalToolbarFolder"][open="true"]
|
||||
{
|
||||
list-style-image : url("chrome://communicator/skin/bookmarks/personal-folder-open.gif") !important;
|
||||
}
|
||||
|
||||
.treeitem-bookmark[type="http://home.netscape.com/NC-rdf#BookmarkSeparator"]
|
||||
{
|
||||
list-style-image : url("chrome://communicator/skin/bookmarks/location.gif");
|
||||
}
|
||||
|
||||
.treeitem-bookmark[type="http://home.netscape.com/NC-rdf#Bookmark"]
|
||||
{
|
||||
list-style-image : url("chrome://communicator/skin/bookmarks/location.gif");
|
||||
}
|
||||
|
||||
/**
|
||||
* XXX - need to create some different icons for file system objects
|
||||
**/
|
||||
.treeitem-bookmark[type="http://home.netscape.com/NC-rdf#FileSystemObject"][container="true"][open="true"]
|
||||
{
|
||||
list-style-image : url("chrome://communicator/skin/directory/file-folder-open.gif");
|
||||
}
|
||||
|
||||
.treeitem-bookmark[type="http://home.netscape.com/NC-rdf#FileSystemObject"][container="true"]
|
||||
{
|
||||
list-style-image : url("chrome://communicator/skin/directory/file-folder-closed.gif");
|
||||
}
|
||||
|
||||
.treeitem-bookmark[type="http://home.netscape.com/NC-rdf#FileSystemObject"]
|
||||
{
|
||||
list-style-image : url("chrome://communicator/skin/directory/file-icon.gif");
|
||||
}
|
||||
|
||||
/**
|
||||
* Bookmarks tree
|
||||
**/
|
||||
.bookmarks-panel-tree, .bookmarks-panel-tree > .tree-container-treerows
|
||||
{
|
||||
border : none;
|
||||
}
|
||||
|
||||
#bookmarksTree
|
||||
{
|
||||
border-top : none;
|
||||
border-bottom : none;
|
||||
}
|
||||
|
||||
/**
|
||||
* XXX - disable print plus. This needs to go into ns/!!!
|
||||
*/
|
||||
#navprintplus
|
||||
{
|
||||
display : none !important;
|
||||
}
|
||||
|
||||
#status-bar
|
||||
{
|
||||
height : 1em;
|
||||
}
|
||||
|
||||
#notification-icon
|
||||
{
|
||||
list-style-image : url("chrome://communicator/skin/bookmarks/notification.gif");
|
||||
}
|
||||
|
||||
#schedule-icon
|
||||
{
|
||||
list-style-image : url("chrome://communicator/skin/bookmarks/schedule.gif");
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
/* -*- Mode: C; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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>
|
||||
* Josh Soref <timeless@mac.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Style rules for bookmark items in Navigator.
|
||||
**/
|
||||
|
||||
|
||||
#home-button
|
||||
{
|
||||
list-style-image : url("chrome://communicator/skin/bookmarks/home.gif");
|
||||
}
|
||||
|
||||
#home-button:hover
|
||||
{
|
||||
list-style-image : url("chrome://communicator/skin/bookmarks/home-hover.gif");
|
||||
}
|
||||
|
||||
#home-button:hover:active
|
||||
{
|
||||
list-style-image : url("chrome://communicator/skin/bookmarks/home-active.gif");
|
||||
}
|
||||
|
||||
/**
|
||||
* Personal toolbar items
|
||||
**/
|
||||
.bookmarkitem
|
||||
{
|
||||
list-style-image : url("chrome://communicator/skin/bookmarks/location.gif");
|
||||
cursor : pointer;
|
||||
}
|
||||
|
||||
.bookmarkfolder
|
||||
{
|
||||
list-style-image : url("chrome://communicator/skin/bookmarks/bookmark-folder-closed.gif");
|
||||
}
|
||||
|
||||
.bookmarkfolder > .menubutton-toolbar-single-internal-box > .menubutton-toolbar-single-dropmarker
|
||||
{
|
||||
display : none;
|
||||
}
|
||||
|
||||
.bookmarkfolder[open="true"]
|
||||
{
|
||||
list-style-image : url("chrome://communicator/skin/bookmarks/bookmark-folder-open.gif");
|
||||
}
|
||||
|
||||
/* Bookmark item/folder buttons on the personal toolbar */
|
||||
|
||||
/* need to override default border on button-toolbar buttons/menubuttons */
|
||||
.button-toolbar.bookmarkitem
|
||||
{
|
||||
-moz-binding : url("chrome://global/skin/classicBindings.xml#toolbarbutton-left");
|
||||
border : none;
|
||||
vertical-align : middle;
|
||||
}
|
||||
|
||||
.button-toolbar.bookmarkitem,
|
||||
.button-toolbar.bookmarkfolder
|
||||
{
|
||||
max-width : 10em;
|
||||
}
|
||||
|
||||
.button-toolbar.bookmarkfolder > box > text
|
||||
{
|
||||
max-width: 8em !important;
|
||||
}
|
||||
|
||||
.toolbarbutton-top-icon
|
||||
{
|
||||
max-width : 2em;
|
||||
}
|
||||
|
||||
.toolbarbutton-left-text
|
||||
{
|
||||
max-width : 8em;
|
||||
}
|
||||
|
||||
.button-toolbar.bookmarkfolder, .button-toolbar.bookmarkfolder:hover
|
||||
{
|
||||
border : none;
|
||||
}
|
||||
|
||||
.button-toolbar.bookmarkitem > .toolbarbutton-left-icon
|
||||
{
|
||||
margin-right : 4px;
|
||||
}
|
||||
|
||||
.bookmarkfolder.button-toolbar:hover
|
||||
{
|
||||
color : #0000FF;
|
||||
cursor : pointer;
|
||||
border : none;
|
||||
}
|
||||
|
||||
.bookmarkfolder.button-toolbar:hover:active
|
||||
{
|
||||
color : #FF0000;
|
||||
border : none;
|
||||
}
|
||||
.bookmarkitem.button-toolbar:hover
|
||||
{
|
||||
color : #0000FF;
|
||||
text-decoration : underline;
|
||||
cursor : pointer;
|
||||
border : none;
|
||||
}
|
||||
|
||||
.bookmarkitem.button-toolbar:hover:active
|
||||
{
|
||||
color : #FF0000;
|
||||
text-decoration : underline;
|
||||
border : none;
|
||||
}
|
||||
|
||||
/* drag and drop feedback */
|
||||
.bookmarkitem.button-toolbar[dragover-left="true"]
|
||||
{
|
||||
margin-left : 0px;
|
||||
border-left : 2px solid threeddarkshadow;
|
||||
}
|
||||
|
||||
.bookmarkitem.button-toolbar[dragover-right="true"]
|
||||
{
|
||||
margin-right : 0px;
|
||||
border-right : 2px solid threeddarkshadow;
|
||||
}
|
||||
|
||||
.menubutton-toolbar-single-text[dragover-top="true"]
|
||||
{
|
||||
background-color : threeddarkshadow;
|
||||
color : threedhighlight;
|
||||
}
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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)
|
||||
*/
|
||||
|
||||
var gFld_Name = null;
|
||||
var gFld_URL = null;
|
||||
var gFolderTree = null;
|
||||
|
||||
const kRDFSContractID = "@mozilla.org/rdf/rdf-service;1";
|
||||
const kRDFSIID = Components.interfaces.nsIRDFService;
|
||||
const kRDF = Components.classes[kRDFSContractID].getService(kRDFSIID);
|
||||
|
||||
var gSelectItemObserver = null;
|
||||
|
||||
var gCreateInFolder = "NC:NewBookmarkFolder";
|
||||
|
||||
function Startup()
|
||||
{
|
||||
doSetOKCancel(onOK);
|
||||
gFld_Name = document.getElementById("name");
|
||||
gFld_URL = document.getElementById("url");
|
||||
gFolderTree = document.getElementById("folders");
|
||||
|
||||
if ("arguments" in window) {
|
||||
gFld_Name.value = window.arguments[0] || "";
|
||||
gFld_URL.value = window.arguments[1] || "";
|
||||
if (window.arguments[2]) {
|
||||
gCreateInFolder = window.arguments[2];
|
||||
//document.getElementById("createin").setAttribute("hidden", "true");
|
||||
//document.getElementById("folderbox").setAttribute("hidden", "true");
|
||||
}
|
||||
}
|
||||
|
||||
onLocationInput();
|
||||
gFld_Name.focus();
|
||||
}
|
||||
|
||||
function toggleCreateIn()
|
||||
{
|
||||
var folderbox = document.getElementById("folderbox");
|
||||
var createInButton = document.getElementById("createin");
|
||||
var dontaskagain = document.getElementById("dontaskagain");
|
||||
var oldID, newID;
|
||||
if (folderbox.getAttribute("hidden") == "true") {
|
||||
createInButton.value = createInButton.getAttribute("value2");
|
||||
folderbox.removeAttribute("hidden");
|
||||
dontaskagain.removeAttribute("hidden");
|
||||
oldID = "buttonsparent";
|
||||
newID = "openParent";
|
||||
}
|
||||
else {
|
||||
createInButton.value = createInButton.getAttribute("value1");
|
||||
folderbox.setAttribute("hidden", "true");
|
||||
dontaskagain.setAttribute("hidden", "true");
|
||||
oldID = "openParent";
|
||||
newID = "buttonsparent";
|
||||
}
|
||||
var oldParent = document.getElementById(oldID);
|
||||
var newParent = document.getElementById(newID);
|
||||
var buttons = oldParent.firstChild.cloneNode(true);
|
||||
oldParent.removeChild(oldParent.firstChild);
|
||||
newParent.appendChild(buttons);
|
||||
sizeToContent();
|
||||
}
|
||||
|
||||
function onLocationInput ()
|
||||
{
|
||||
var ok = document.getElementById("ok");
|
||||
if (!gFld_URL.value)
|
||||
ok.setAttribute("disabled", "true");
|
||||
else
|
||||
ok.removeAttribute("disabled");
|
||||
}
|
||||
|
||||
function onOK()
|
||||
{
|
||||
const kBMDS = kRDF.GetDataSource("rdf:bookmarks");
|
||||
const kBMSContractID = "@mozilla.org/browser/bookmarks-service;1";
|
||||
const kBMSIID = Components.interfaces.nsIBookmarksService;
|
||||
const kBMS = Components.classes[kBMSContractID].getService(kBMSIID);
|
||||
var rFolder = kRDF.GetResource(gCreateInFolder, true);
|
||||
const kRDFCContractID = "@mozilla.org/rdf/container;1";
|
||||
const kRDFIID = Components.interfaces.nsIRDFContainer;
|
||||
const kRDFC = Components.classes[kRDFCContractID].getService(kRDFIID);
|
||||
try {
|
||||
kRDFC.Init(kBMDS, rFolder);
|
||||
}
|
||||
catch (e) {
|
||||
// No "NC:NewBookmarkFolder" exists, just append to the root.
|
||||
rFolder = kRDF.GetResource("NC:BookmarksRoot", true);
|
||||
}
|
||||
if (!gFld_URL.value) return;
|
||||
kBMS.AddBookmarkToFolder(gFld_URL.value, rFolder, gFld_Name.value, null);
|
||||
close();
|
||||
}
|
||||
|
||||
function onTreeSelect ()
|
||||
{
|
||||
if (gFolderTree.selectedItems.length < 1)
|
||||
gCreateInFolder = "NC:NewBookmarkFolder";
|
||||
var selectedItem = gFolderTree.selectedItems[0];
|
||||
gCreateInFolder = selectedItem.id;
|
||||
}
|
||||
|
||||
var gBookmarksShell = null;
|
||||
function createNewFolder ()
|
||||
{
|
||||
// ick.
|
||||
gBookmarksShell = new BookmarksTree("folders");
|
||||
var item = null;
|
||||
var folderKids = document.getElementById("folderKids");
|
||||
if (gFolderTree.selectedItems.length < 1)
|
||||
item = folderKids.firstChild;
|
||||
item = gFolderTree.selectedItems.length < 1 ? folderKids.firstChild : gFolderTree.selectedItems[0];
|
||||
gBookmarksShell.commands.createBookmarkItem("folder", item);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
<?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)
|
||||
|
||||
-->
|
||||
|
||||
<?xml-stylesheet href="chrome://communicator/skin/"?>
|
||||
<?xml-stylesheet href="chrome://communicator/skin/bookmarks/bookmarks-tree.css"?>
|
||||
|
||||
<?xul-overlay href="chrome://global/content/dialogOverlay.xul"?>
|
||||
<?xul-overlay href="chrome://global/content/globalOverlay.xul"?>
|
||||
|
||||
<!DOCTYPE window [
|
||||
<!ENTITY % brandDTD SYSTEM "chrome://global/locale/brand.dtd" >
|
||||
%brandDTD;
|
||||
<!ENTITY % addBookmarkDTD SYSTEM "chrome://communicator/locale/bookmarks/addBookmark.dtd">
|
||||
%addBookmarkDTD;
|
||||
]>
|
||||
|
||||
<window id="newBookmarkWindow" style="width: 36em;"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="&newBookmark.title;" orient="vertical" class="dialog"
|
||||
onload="Startup();">
|
||||
|
||||
<script type="text/javascript" src="chrome://communicator/content/bookmarks/bookmarksOverlay.js"></script>
|
||||
<script type="text/javascript" src="chrome://communicator/content/bookmarks/bookmarksTree.js"></script>
|
||||
<script type="text/javascript" src="chrome://communicator/content/bookmarks/addBookmark.js"></script>
|
||||
|
||||
<stringbundle id="bookmarksbundle"
|
||||
src="chrome://communicator/locale/bookmarks/bookmark.properties"/>
|
||||
|
||||
|
||||
<keyset id="keyset"/>
|
||||
|
||||
<popupset id="aTooltipSet"/>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<grid id="bookmarknamegrid">
|
||||
<columns>
|
||||
<column/>
|
||||
<column flex="5"/>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row autostretch="never">
|
||||
<text class="label" value="&name.label;" accesskey="&name.accesskey;" for="name"/>
|
||||
<textfield id="name"/>
|
||||
</row>
|
||||
<row>
|
||||
<separator class="thin"/>
|
||||
<separator class="thin"/>
|
||||
</row>
|
||||
<row autostretch="never">
|
||||
<text class="label" value="&url.label;" accesskey="&url.accesskey;" for="url"/>
|
||||
<textfield id="url" oninput="onLocationInput();"/>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
|
||||
<separator/>
|
||||
|
||||
<box id="createinbuttonbox">
|
||||
<button id="createin" class="disclosure-triangle" value="&button.createin.label;"
|
||||
accesskey="&button.createin.accesskey;"
|
||||
value1="&button.createin.label;"
|
||||
value2="&button.createin2.label;"
|
||||
oncommand="toggleCreateIn();"/>
|
||||
<spring flex="1"/>
|
||||
<box id="buttonsparent">
|
||||
<box id="okCancelButtonsRight"/>
|
||||
</box>
|
||||
</box>
|
||||
|
||||
<box id="folderbox" orient="vertical" hidden="true">
|
||||
<separator/>
|
||||
<grid>
|
||||
<columns>
|
||||
<column/>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row autostretch="never" valign="top">
|
||||
<text class="label" value="&createin.label;"/>
|
||||
<box autostretch="never" valign="top">
|
||||
<tree id="folders" flex="1" style="height: 12em; width: 0px"
|
||||
class="inset" ref="NC:BookmarksRoot" datasources="rdf:bookmarks"
|
||||
template="file-bookmarks-template">
|
||||
<treecols>
|
||||
<treecol flex="1"/>
|
||||
</treecols>
|
||||
|
||||
<template id="file-bookmarks-template">
|
||||
<rule iscontainer="true">
|
||||
<treechildren>
|
||||
<treeitem uri="rdf:*" persist="open" class="treeitem-bookmark"
|
||||
rdf:type="rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#type">
|
||||
<treerow>
|
||||
<treecell value="rdf:http://home.netscape.com/NC-rdf#Name"
|
||||
class="treecell-indent-editable" editable="true"
|
||||
src="rdf:http://home.netscape.com/NC-rdf#Icon"
|
||||
rdf:type="rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
|
||||
loading="rdf:http://home.netscape.com/NC-rdf#loading"/>
|
||||
</treerow>
|
||||
</treeitem>
|
||||
</treechildren>
|
||||
</rule>
|
||||
</template>
|
||||
<treechildren id="folderKids" flex="1"/>
|
||||
</tree>
|
||||
<button value="&button.newfolder.label;" accesskey="&button.newfolder.accesskey;"
|
||||
oncommand="createNewFolder();"/>
|
||||
</box>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
<separator/>
|
||||
</box>
|
||||
|
||||
<box valign="bottom">
|
||||
<box autostretch="never">
|
||||
<checkbox id="dontaskagain" hidden="true"
|
||||
tooltip="aTooltip" tooltiptext="&dontshowmessage.tooltip;"
|
||||
value="&alwayscreateinfolder.label;"
|
||||
accesskey="&alwayscreateinfolder.accesskey;"/>
|
||||
</box>
|
||||
<spring flex="1"/>
|
||||
<box id="openParent" orient="vertical"/>
|
||||
</box>
|
||||
|
||||
</window>
|
|
@ -0,0 +1,596 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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)
|
||||
*/
|
||||
|
||||
var NC_NS = "http://home.netscape.com/NC-rdf#";
|
||||
var RDF_NS = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
|
||||
const NC_NS_CMD = NC_NS + "command?cmd=";
|
||||
|
||||
function NODE_ID (aElement)
|
||||
{
|
||||
return aElement.getAttribute("ref") || aElement.id;
|
||||
}
|
||||
|
||||
function LITERAL (aDB, aElement, aPropertyID)
|
||||
{
|
||||
var RDF = BookmarksUIElement.prototype.RDF;
|
||||
var rSource = RDF.GetResource(NODE_ID(aElement));
|
||||
var rProperty = RDF.GetResource(aPropertyID);
|
||||
var node = aDB.GetTarget(rSource, rProperty, true);
|
||||
return node ? node.QueryInterface(Components.interfaces.nsIRDFLiteral).Value : "";
|
||||
}
|
||||
|
||||
function BookmarksUIElement () { }
|
||||
BookmarksUIElement.prototype = {
|
||||
_rdf: null,
|
||||
get RDF ()
|
||||
{
|
||||
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;
|
||||
},
|
||||
|
||||
propertySet: function (sourceID, propertyID, newValue)
|
||||
{
|
||||
if (!newValue) return;
|
||||
const kRDFContractID = "@mozilla.org/rdf/rdf-service;1";
|
||||
const kRDFIID = Components.interfaces.nsIRDFService;
|
||||
const kRDF = Components.classes[kRDFContractID].getService(kRDFIID);
|
||||
// need to shuffle this into an API.
|
||||
const kBMDS = kRDF.GetDataSource("rdf:bookmarks");
|
||||
const krProperty = kRDF.GetResource(propertyID);
|
||||
const krItem = kRDF.GetResource(sourceID);
|
||||
var rCurrValue = kBMDS.GetTarget(krItem, krProperty, true);
|
||||
const krNewValue = kRDF.GetLiteral(newValue);
|
||||
if (!rCurrValue)
|
||||
kBMDS.Assert(krItem, krProperty, krNewValue, true);
|
||||
else {
|
||||
rCurrValue = rCurrValue.QueryInterface(Components.interfaces.nsIRDFLiteral);
|
||||
if (rCurrValue.Value != newValue)
|
||||
kBMDS.Change(krItem, krProperty, rCurrValue, krNewValue);
|
||||
}
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Fill a context menu popup with menuitems that are appropriate for the current
|
||||
// selection.
|
||||
createContextMenu: function (aEvent)
|
||||
{
|
||||
var popup = aEvent.target;
|
||||
|
||||
// clear out the old context menu contents (if any)
|
||||
while (popup.hasChildNodes())
|
||||
popup.removeChild(popup.firstChild);
|
||||
|
||||
var popupNode = document.popupNode;
|
||||
|
||||
if (!("findRDFNode" in this))
|
||||
throw "Clients must implement findRDFNode!";
|
||||
var itemNode = this.findRDFNode(popupNode, true);
|
||||
if (!itemNode) return;
|
||||
|
||||
if (!("getContextSelection" in this))
|
||||
throw "Clients must implement getContextSelection!";
|
||||
var selection = this.getContextSelection (itemNode);
|
||||
var commonCommands = [];
|
||||
for (var i = 0; i < selection.length; ++i) {
|
||||
var nodeURI = NODE_ID(selection[i]);
|
||||
var commands = this.getAllCmds(nodeURI);
|
||||
commands = this.flattenEnumerator(commands);
|
||||
if (!commonCommands.length) commonCommands = commands;
|
||||
commonCommands = this.findCommonNodes(commands, commonCommands);
|
||||
}
|
||||
|
||||
// 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 != NC_NS_CMD + "separator") {
|
||||
var commandName = this.getCommandName(currCommand);
|
||||
element = this.createMenuItem(commandName, currCommand, itemNode);
|
||||
}
|
||||
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);
|
||||
}
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Given two unique arrays, return an array that contains only the elements
|
||||
// common to both.
|
||||
findCommonNodes: function (aNewArray, aOldArray)
|
||||
{
|
||||
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;
|
||||
},
|
||||
|
||||
flattenEnumerator: function (aEnumerator)
|
||||
{
|
||||
if ("_index" in aEnumerator)
|
||||
return aEnumerator._inner;
|
||||
|
||||
var temp = [];
|
||||
while (aEnumerator.hasMoreElements())
|
||||
temp.push(aEnumerator.getNext());
|
||||
return temp;
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// For a given URI (a unique identifier of a resource in the graph) return
|
||||
// an enumeration of applicable commands for that URI.
|
||||
getAllCmds: function (aNodeID)
|
||||
{
|
||||
var type = this.resolveType(aNodeID);
|
||||
var commands = [];
|
||||
switch (type) {
|
||||
case "http://home.netscape.com/NC-rdf#BookmarkSeparator":
|
||||
commands = ["find", "separator", "cut", "copy", "paste",
|
||||
"delete"];
|
||||
break;
|
||||
case "http://home.netscape.com/NC-rdf#Bookmark":
|
||||
commands = ["open", "find", "separator", "cut", "copy", "paste",
|
||||
"delete", "separator", "rename", "separator",
|
||||
"properties"];
|
||||
break;
|
||||
case "http://home.netscape.com/NC-rdf#Folder":
|
||||
commands = ["openfolder", "openfolderinnewwindow", "find", "separator",
|
||||
"cut", "copy", "paste", "delete", "separator", "rename",
|
||||
"separator", "newfolder", "separator", "properties"];
|
||||
break;
|
||||
default:
|
||||
var source = this.RDF.GetResource(aNodeID);
|
||||
return this.db.GetAllCmds(source);
|
||||
}
|
||||
return new CommandArrayEnumerator(commands);
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Retrieve the human-readable name for a particular command. Used when
|
||||
// manufacturing a UI to invoke commands.
|
||||
getCommandName: function (aCommand)
|
||||
{
|
||||
var cmdName = aCommand.substring(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 this.getLocaleString ("cmd_" + cmdName);
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
const rName = this.RDF.GetResource(NC_NS + "Name");
|
||||
const rSource = this.RDF.GetResource(aNodeID);
|
||||
return this.db.GetTarget(rSource, rName, true).Value;
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Perform a command based on a UI event. XXX - work to do here.
|
||||
preExecCommand: function (aEvent)
|
||||
{
|
||||
var commandID = aEvent.target.getAttribute("command");
|
||||
if (!commandID) return;
|
||||
goDoCommand("cmd_" + commandID.substring(NC_NS_CMD.length));
|
||||
},
|
||||
|
||||
execCommand: function (commandID)
|
||||
{
|
||||
var selection = this.getSelection ();
|
||||
if (selection.length == 1 && commandID != "cut" && commandID != "copy" &&
|
||||
commandID != "paste" && commandID != "delete") {
|
||||
// Commands that can only be performed on a single selection
|
||||
var selectedItem = selection[0];
|
||||
switch (commandID) {
|
||||
case "open":
|
||||
this.openRDFNode(selectedItem);
|
||||
break;
|
||||
case "openfolder":
|
||||
this.commands.openFolder(selectedItem);
|
||||
break;
|
||||
case "openfolderinnewwindow":
|
||||
this.openFolderInNewWindow(selectedItem);
|
||||
break;
|
||||
case "rename":
|
||||
// XXX - this is SO going to break if we ever do column re-ordering.
|
||||
this.commands.editCell(selectedItem, 0);
|
||||
break;
|
||||
case "editurl":
|
||||
this.commands.editCell(selectedItem, 1);
|
||||
break;
|
||||
case "setnewbookmarkfolder":
|
||||
case "setpersonaltoolbarfolder":
|
||||
case "setnewsearchfolder":
|
||||
rCommand = this.RDF.GetResource(NC_NS_CMD + commandID);
|
||||
rSource = this.RDF.GetResource(NODE_ID(selectedItem));
|
||||
|
||||
kSuppArrayContractID = "@mozilla.org/supports-array;1";
|
||||
kSuppArrayIID = Components.interfaces.nsISupportsArray;
|
||||
var sourcesArray = Components.classes[kSuppArrayContractID].createInstance(kSuppArrayIID);
|
||||
sourcesArray.AppendElement (krSource);
|
||||
var argsArray = Components.classes[kSuppArrayContractID].createInstance(kSuppArrayIID);
|
||||
this.db.DoCommand(sourcesArray, krCommand, argsArray);
|
||||
break;
|
||||
case "properties":
|
||||
this.showPropertiesForNode(selectedItem);
|
||||
break;
|
||||
case "find":
|
||||
this.findInBookmarks();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Commands that can be performed on a selection of 1 or more items.
|
||||
switch (commandID) {
|
||||
case "cut":
|
||||
this.copySelection (selection);
|
||||
this.deleteSelection (selection);
|
||||
break;
|
||||
case "copy":
|
||||
this.copySelection (selection);
|
||||
break;
|
||||
case "paste":
|
||||
this.paste (selection);
|
||||
break;
|
||||
case "delete":
|
||||
this.deleteSelection (selection);
|
||||
break;
|
||||
case "find":
|
||||
this.findInBookmarks();
|
||||
break;
|
||||
case "newfolder":
|
||||
var nfseln = this.getBestItem ();
|
||||
this.commands.createBookmarkItem("folder", nfseln);
|
||||
break;
|
||||
case "newbookmark":
|
||||
var folder = this.getSelectedFolder();
|
||||
openDialog("chrome://communicator/content/bookmarks/addBookmark.xul", "",
|
||||
"centerscreen,chrome,dialog=no,resizable=no", null, null, folder);
|
||||
break;
|
||||
case "newseparator":
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Execute a command with the given source and arguments
|
||||
doBookmarksCommand: function (aSourceURI, aCommand, aArgumentsArray)
|
||||
{
|
||||
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 Bookmarks datasource.
|
||||
const kBMDS = this.RDF.GetDataSource("rdf:bookmarks");
|
||||
kBMDS.DoCommand(sourcesArray, rCommand, argsArray);
|
||||
},
|
||||
|
||||
openFolderInNewWindow: function (aSelectedItem)
|
||||
{
|
||||
openDialog("chrome://communicator/content/bookmarks/bookmarks.xul",
|
||||
"", "chrome,all,dialog=no", NODE_ID(aSelectedItem));
|
||||
},
|
||||
|
||||
copySelection: function (aSelection)
|
||||
{
|
||||
const kSuppArrayContractID = "@mozilla.org/supports-array;1";
|
||||
const kSuppArrayIID = Components.interfaces.nsISupportsArray;
|
||||
var itemArray = Components.classes[kSuppArrayContractID].createInstance(kSuppArrayIID);
|
||||
|
||||
const kSuppWStringContractID = "@mozilla.org/supports-wstring;1";
|
||||
const kSuppWStringIID = Components.interfaces.nsISupportsWString;
|
||||
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 = "";
|
||||
for (var i = 0; i < aSelection.length; ++i) {
|
||||
var url = LITERAL(this.db, aSelection[i], NC_NS + "URL");
|
||||
var name = LITERAL(this.db, aSelection[i], NC_NS + "Name");
|
||||
sBookmarkItem += NODE_ID(aSelection[i]) + "\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 = sTextHTML;
|
||||
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);
|
||||
},
|
||||
|
||||
paste: function (aSelection)
|
||||
{
|
||||
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.nsISupportsWString).data;
|
||||
switch (flavour.value) {
|
||||
case "moz/bookmarkclipboarditem":
|
||||
nodes = data.split("\n");
|
||||
break;
|
||||
case "text/x-moz-url":
|
||||
var ix = data.value.indexOf("\n");
|
||||
nodes.push(data.substring(0, ix != -1 ? ix : data.length));
|
||||
names.push(data.substring(ix));
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
const lastSelected = aSelection[aSelection.length-1];
|
||||
const kParentNode = this.resolvePasteFolder(aSelection);
|
||||
const krParent = this.RDF.GetResource(NODE_ID(kParentNode));
|
||||
const krSource = this.RDF.GetResource(NODE_ID(lastSelected));
|
||||
|
||||
const kRDFCContractID = "@mozilla.org/rdf/container;1";
|
||||
const kRDFCIID = Components.interfaces.nsIRDFContainer;
|
||||
const ksRDFC = Components.classes[kRDFCContractID].getService(kRDFCIID);
|
||||
const kBMDS = this.RDF.GetDataSource("rdf:bookmarks");
|
||||
ksRDFC.Init(kBMDS, krParent);
|
||||
|
||||
for (var i = 0; i < nodes.length; ++i) {
|
||||
if (!nodes[i]) continue;
|
||||
const krCurrent = this.RDF.GetResource(nodes[i]);
|
||||
if (names.length) {
|
||||
// If we are given names, this implies that the nodes do not already
|
||||
// exist in the graph, and we need to create some additional information
|
||||
// for them.
|
||||
const krName = this.RDF.GetResource(names[i]);
|
||||
const krNameProperty = this.RDF.GetResource(NC_NS + "Name");
|
||||
const krTypeProperty = this.RDF.GetResource(RDF_NS + "type");
|
||||
const krBookmark = this.RDF.GetResource(NC_NS + "Bookmark");
|
||||
this.db.Assert(krCurrent, krNameProperty, krName, true);
|
||||
this.db.Assert(krCurrent, krTypeProperty, krBookmark, true);
|
||||
}
|
||||
ix = ksRDFC.IndexOf(krSource);
|
||||
if (ix != -1)
|
||||
ksRDFC.InsertElementAt(krCurrent, ix+1, true);
|
||||
else
|
||||
ksRDFC.AppendElement(krCurrent);
|
||||
if ("addItemToSelection" in this)
|
||||
this.addItemToSelection(krCurrent.Value);
|
||||
}
|
||||
},
|
||||
|
||||
canPaste: function ()
|
||||
{
|
||||
const kClipboardContractID = "@mozilla.org/widget/clipboard;1";
|
||||
const kClipboardIID = Components.interfaces.nsIClipboard;
|
||||
var clipboard = Components.classes[kClipboardContractID].getService(kClipboardIID);
|
||||
const kSuppArrayContractID = "@mozilla.org/supports-array;1";
|
||||
const kSuppArrayIID = Components.interfaces.nsISupportsArray;
|
||||
var flavourArray = Components.classes[kSuppArrayContractID].createInstance(kSuppArrayIID);
|
||||
const kSuppStringContractID = "@mozilla.org/supports-string;1";
|
||||
const kSuppStringIID = Components.interfaces.nsISupportsString;
|
||||
|
||||
var flavours = ["moz/bookmarkclipboarditem", "text/x-moz-url"];
|
||||
for (var i = 0; i < flavours.length; ++i) {
|
||||
const kSuppString = Components.classes[kSuppStringContractID].createInstance(kSuppStringIID);
|
||||
kSuppString.data = flavours[i];
|
||||
flavourArray.AppendElement(kSuppString);
|
||||
}
|
||||
var hasFlavors = clipboard.hasDataMatchingFlavors(flavourArray, kClipboardIID.kGlobalClipboard);
|
||||
return hasFlavors;
|
||||
},
|
||||
|
||||
deleteSelection: function (aSelection)
|
||||
{
|
||||
const kRDFCContractID = "@mozilla.org/rdf/container;1";
|
||||
const kRDFCIID = Components.interfaces.nsIRDFContainer;
|
||||
const ksRDFC = Components.classes[kRDFCContractID].getService(kRDFCIID);
|
||||
// We must create a copy here because we're going to be modifying the
|
||||
// selectedItems list.
|
||||
var tempSelection = aSelection;
|
||||
var nextElement;
|
||||
for (var i = 0; i < tempSelection.length; ++i) {
|
||||
const currParent = this.findRDFNode(tempSelection[i], false);
|
||||
const kSelectionURI = NODE_ID(tempSelection[i]);
|
||||
|
||||
// Disallow the removal of certain 'special' nodes
|
||||
if (kSelectionURI == "NC:BookmarksRoot" || kSelectionURI == "NC:IEFavoritesRoot")
|
||||
continue;
|
||||
|
||||
const krParent = this.RDF.GetResource(NODE_ID(currParent));
|
||||
const krNode = this.RDF.GetResource(kSelectionURI);
|
||||
const kBMDS = this.RDF.GetDataSource("rdf:bookmarks");
|
||||
ksRDFC.Init(kBMDS, krParent);
|
||||
nextElement = this.getNextElement(tempSelection[i]);
|
||||
ksRDFC.RemoveElement(krNode, true);
|
||||
}
|
||||
this.selectElement(nextElement);
|
||||
},
|
||||
|
||||
moveBookmark: function (aBookmarkURI, aFromFolderURI, aToFolderURI)
|
||||
{
|
||||
const kBMDS = this.RDF.GetDataSource("rdf:bookmarks");
|
||||
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(kBMDS, krNewParent);
|
||||
kRDFC.AppendElement(krSrc);
|
||||
kRDFC.Init(kBMDS, krOldParent);
|
||||
kRDFC.RemoveElement(krSrc, true);
|
||||
},
|
||||
|
||||
openRDFNode: function (aRDFNode)
|
||||
{
|
||||
var urlValue = LITERAL(this.db, aRDFNode, NC_NS + "URL");
|
||||
// Ignore "NC:" and empty urls.
|
||||
if (urlValue.substring(0,3) == "NC:" || !urlValue) return;
|
||||
openDialog (getBrowserURL(), "_blank", "chrome,all,dialog=no", urlValue);
|
||||
},
|
||||
|
||||
open: function (aEvent)
|
||||
{
|
||||
if (!this.isValidOpenEvent(aEvent))
|
||||
return;
|
||||
|
||||
var rdfNode = this.findRDFNode(aEvent.target, true);
|
||||
if (rdfNode.getAttribute("container") == "true")
|
||||
return;
|
||||
|
||||
var urlValue = LITERAL(this.db, rdfNode, NC_NS + "URL");
|
||||
|
||||
// Ignore "NC:" and empty urls.
|
||||
if (urlValue.substring(0,3) == "NC:" || !urlValue) return;
|
||||
|
||||
if (aEvent.altKey)
|
||||
this.showPropertiesForNode (rdfNode);
|
||||
else
|
||||
openDialog (getBrowserURL(), "_blank", "chrome,all,dialog=no", urlValue);
|
||||
|
||||
aEvent.preventBubble();
|
||||
},
|
||||
|
||||
showPropertiesForNode: function (aBookmarkItem)
|
||||
{
|
||||
openDialog("chrome://communicator/content/bookmarks/bm-props.xul",
|
||||
"", "centerscreen,chrome,dialog=no,resizable=no",
|
||||
NODE_ID(aBookmarkItem));
|
||||
},
|
||||
|
||||
findInBookmarks: function ()
|
||||
{
|
||||
openDialog("chrome://communicator/content/bookmarks/bm-find.xul",
|
||||
"FindBookmarksWindow",
|
||||
"centerscreen,chrome,resizable");
|
||||
},
|
||||
|
||||
getLocaleString: function (aStringKey)
|
||||
{
|
||||
var bundle = document.getElementById("bookmarksbundle");
|
||||
return bundle.getString (aStringKey);
|
||||
},
|
||||
|
||||
flushDataSource: function ()
|
||||
{
|
||||
const kBMDS = this.RDF.GetDataSource("rdf:bookmarks");
|
||||
var remoteDS = kBMDS.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
|
||||
remoteDS.Flush();
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Determine the rdf:type property for the given resource.
|
||||
resolveType: function (aID)
|
||||
{
|
||||
const bmTree = document.getElementById("bookmarksTree");
|
||||
const krType = this.RDF.GetResource(RDF_NS + "type");
|
||||
const krElement = this.RDF.GetResource(aID);
|
||||
const type = bmTree.database.GetTarget(krElement, krType, true);
|
||||
return type.QueryInterface(Components.interfaces.nsIRDFResource).Value;
|
||||
}
|
||||
};
|
||||
|
||||
function CommandArrayEnumerator (aCommandArray)
|
||||
{
|
||||
this._inner = [];
|
||||
const kRDFContractID = "@mozilla.org/rdf/rdf-service;1";
|
||||
const kRDFIID = Components.interfaces.nsIRDFService;
|
||||
const RDF = Components.classes[kRDFContractID].getService(kRDFIID);
|
||||
for (var i = 0; i < aCommandArray.length; ++i)
|
||||
this._inner.push(RDF.GetResource(NC_NS_CMD + aCommandArray[i]));
|
||||
|
||||
this._index = 0;
|
||||
}
|
||||
|
||||
CommandArrayEnumerator.prototype = {
|
||||
getNext: function ()
|
||||
{
|
||||
return this._inner[this._index];
|
||||
},
|
||||
|
||||
hasMoreElements: function ()
|
||||
{
|
||||
return this._index < this._inner.length;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
<?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)
|
||||
-->
|
||||
|
||||
<!DOCTYPE window SYSTEM "chrome://communicator/locale/bookmarks/bookmarksOverlay.dtd">
|
||||
|
||||
<overlay id="bookmarksOverlay"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<stringbundleset id="stringbundleset">
|
||||
<stringbundle id="bookmarksbundle"
|
||||
src="chrome://communicator/locale/bookmarks/bookmark.properties"/>
|
||||
</stringbundleset>
|
||||
|
||||
<popupset id="popupset">
|
||||
<popup id="bmContext"
|
||||
oncreate="if (gBookmarksShell) gBookmarksShell.createContextMenu(event);"/>
|
||||
</popupset>
|
||||
|
||||
</overlay>
|
||||
|
||||
|
|
@ -0,0 +1,593 @@
|
|||
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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)
|
||||
*/
|
||||
|
||||
var gBookmarksShell = null;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Tracks the selected item, the cell last clicked on, and the number of clicks
|
||||
// given to it. Used to activate inline edit mode.
|
||||
var gSelectionTracker = { currentItem: null, currentCell: null, clickCount: 0 };
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Class which defines methods for a bookmarks UI implementation based around
|
||||
// a treeview. Subclasses BookmarksBase in bookmarksOverlay.js. Some methods
|
||||
// are required by the base class, others are for event handling. Window specific
|
||||
// glue code should go into the BookmarksWindow class in bookmarks.js
|
||||
function BookmarksTree (aID)
|
||||
{
|
||||
this.id = aID;
|
||||
}
|
||||
|
||||
BookmarksTree.prototype = {
|
||||
__proto__: BookmarksUIElement.prototype,
|
||||
|
||||
get tree ()
|
||||
{
|
||||
return document.getElementById(this.id);
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// This method constructs a menuitem for a context menu for the given command.
|
||||
// This is implemented by the client so that it can intercept menuitem naming
|
||||
// as appropriate.
|
||||
createMenuItem: function (aDisplayName, aCommandName, aItemNode)
|
||||
{
|
||||
const kXULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
var xulElement = document.createElementNS(kXULNS, "menuitem");
|
||||
xulElement.setAttribute("command", aCommandName);
|
||||
xulElement.setAttribute("observes", "cmd_" + aCommandName.substring(NC_NS_CMD.length));
|
||||
|
||||
switch (aCommandName) {
|
||||
case NC_NS_CMD + "open":
|
||||
xulElement.setAttribute("value", aDisplayName);
|
||||
xulElement.setAttribute("default", "true");
|
||||
break;
|
||||
case NC_NS_CMD + "openfolder":
|
||||
aDisplayName = aItemNode.getAttribute("open") == "true" ? this.getLocaleString("cmd_openfolder2") : aDisplayName;
|
||||
xulElement.setAttribute("value", aDisplayName);
|
||||
xulElement.setAttribute("default", "true");
|
||||
break;
|
||||
case NC_NS_CMD + "renamebookmark":
|
||||
if (!document.popupNode.hasAttribute("type")) {
|
||||
xulElement.setAttribute("value", this.getLocaleString("cmd_renamebookmark2"));
|
||||
xulElement.setAttribute("command", (NC_NS_CMD + "editurl"));
|
||||
}
|
||||
else
|
||||
xulElement.setAttribute("value", aDisplayName);
|
||||
break;
|
||||
default:
|
||||
xulElement.setAttribute("value", aDisplayName);
|
||||
break;
|
||||
}
|
||||
return xulElement;
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// For the given selection, determines the element that should form the
|
||||
// container to paste items into.
|
||||
resolvePasteFolder: function (aSelection)
|
||||
{
|
||||
const lastSelected = aSelection[aSelection.length-1];
|
||||
if (lastSelected.getAttribute("container") == "true" &&
|
||||
lastSelected.getAttribute("open") == "true" &&
|
||||
aSelection.length == 1)
|
||||
return lastSelected;
|
||||
return this.findRDFNode(lastSelected, false);
|
||||
},
|
||||
|
||||
// Command implementation
|
||||
commands: {
|
||||
openFolder: function (aSelectedItem)
|
||||
{
|
||||
if (aSelectedItem.getAttribute("open") == "true")
|
||||
aSelectedItem.removeAttribute("open");
|
||||
else
|
||||
aSelectedItem.setAttribute("open", "true");
|
||||
},
|
||||
|
||||
// Things Needed to Satisfy Mac Weenies:
|
||||
// 1) need to implement timed single click edit. This could be Hard.
|
||||
// 2) need to implement some other method of key access apart from F2.
|
||||
// mpt claims that 'Cmd+U' is the excel equivalent.
|
||||
editCell: function (aSelectedItem, aCell)
|
||||
{
|
||||
var editCell = aSelectedItem.firstChild.childNodes[aCell];
|
||||
if (editCell.getAttribute("editable") != "true")
|
||||
return;
|
||||
var editColGroup = document.getElementById("theColumns");
|
||||
var count = 0;
|
||||
var property = "";
|
||||
for (var i = 0; i < editColGroup.childNodes.length; ++i) {
|
||||
var currCol = editColGroup.childNodes[i];
|
||||
if (count == aCell) {
|
||||
property = currCol.getAttribute("resource");
|
||||
break;
|
||||
}
|
||||
++count;
|
||||
|
||||
// Deal with interleaved column resizer splitters
|
||||
if (currCol.nextSibling.localName == "splitter") ++i;
|
||||
}
|
||||
|
||||
if (property) {
|
||||
editCell.setMode("edit");
|
||||
editCell.addObserver(this.postModifyCallback, "accept",
|
||||
[gBookmarksShell, NODE_ID(aSelectedItem), property]);
|
||||
}
|
||||
},
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Called after an inline-edit cell has left inline-edit mode, and data
|
||||
// needs to be modified in the datasource.
|
||||
postModifyCallback: function (aParams)
|
||||
{
|
||||
var aShell = aParams[0];
|
||||
aShell.propertySet(aParams[1], aParams[2], aParams[3]);
|
||||
gBookmarksShell.tree.focus();
|
||||
gSelectionTracker.clickCount = 0;
|
||||
},
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// New Folder Creation
|
||||
// Strategy: create a dummy row with edit fields to harvest information
|
||||
// from the user, then destroy these rows and create an item
|
||||
// in its place.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Edit folder name & update the datasource if name is valid
|
||||
onEditFolderName: function (aParams, aTopic)
|
||||
{
|
||||
var name = aParams[3];
|
||||
var shell = gBookmarksShell.commands; // suck
|
||||
var dummyItem = aParams[2];
|
||||
var relativeNode = aParams[1];
|
||||
var parentNode = gBookmarksShell.findRDFNode(relativeNode, false);
|
||||
|
||||
if (!shell.validateNameAndTopic(name, aTopic, relativeNode, dummyItem))
|
||||
return;
|
||||
|
||||
// If we're attempting to create a folder as a subfolder of an open folder,
|
||||
// we need to set the parentFolder to be relativeNode, which will be the
|
||||
// parent of the new folder, rather than the parent of the relativeNode,
|
||||
// which will result in the folder being created in an incorrect position
|
||||
// (adjacent to the relativeNode).
|
||||
var selKids = ContentUtils.childByLocalName(relativeNode, "treechildren");
|
||||
if (selKids && selKids.hasChildNodes() && selKids.lastChild == dummyItem)
|
||||
parentNode = relativeNode;
|
||||
|
||||
var args = [{ property: NC_NS + "parent",
|
||||
resource: NODE_ID(parentNode) },
|
||||
{ property: NC_NS + "Name",
|
||||
literal: name }];
|
||||
|
||||
const kBMDS = gBookmarksShell.RDF.GetDataSource("rdf:bookmarks");
|
||||
kBMDS.AddObserver(newFolderRDFObserver);
|
||||
gBookmarksShell.doBookmarksCommand(NODE_ID(relativeNode), NC_NS_CMD + "newfolder", args);
|
||||
kBMDS.RemoveObserver(newFolderRDFObserver);
|
||||
var newFolderItem = document.getElementById(newFolderRDFObserver._newFolderURI);
|
||||
gBookmarksShell.tree.focus();
|
||||
gBookmarksShell.tree.selectItem(newFolderItem);
|
||||
},
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Performs simple validation on what the user has entered:
|
||||
// 1) prevents entering an empty string
|
||||
// 2) in the case of a canceled operation, remove the dummy item and
|
||||
// restore selection.
|
||||
validateNameAndTopic: function (aName, aTopic, aOldSelectedItem, aDummyItem)
|
||||
{
|
||||
// Don't allow user to enter an empty string "";
|
||||
if (!aName) return false;
|
||||
|
||||
// If the user hit escape, go no further.
|
||||
if (aTopic == "reject") {
|
||||
if (aOldSelectedItem)
|
||||
gBookmarksShell.tree.selectItem(aOldSelectedItem);
|
||||
aDummyItem.parentNode.removeChild(aDummyItem);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Creates a dummy item that can be placed in edit mode to retrieve data
|
||||
// to create new bookmarks/folders.
|
||||
createBookmarkItem: function (aMode, aSelectedItem)
|
||||
{
|
||||
aSelectedItem.removeAttribute("selected");
|
||||
var dummyItem = aSelectedItem.cloneNode(true);
|
||||
dummyItem.removeAttribute("id");
|
||||
dummyItem.removeAttribute("selected");
|
||||
if (aMode == "folder")
|
||||
dummyItem.setAttribute("container", "true");
|
||||
for (var i = 0; i < dummyItem.firstChild.childNodes.length; ++i)
|
||||
dummyItem.firstChild.childNodes[i].removeAttribute("value");
|
||||
var editCell = dummyItem.firstChild.firstChild;
|
||||
editCell.setAttribute("value",
|
||||
gBookmarksShell.getLocaleString(aMode == "folder" ? "ile_newfolder" :
|
||||
"ile_newbookmark"));
|
||||
editCell.setAttribute("type", NC_NS + (aMode == "folder" ? "Folder" : "Bookmark"));
|
||||
var relativeNode = aSelectedItem;
|
||||
if (dummyItem.getAttribute("container") == "true") {
|
||||
for (i = 0; i < dummyItem.childNodes.length; ++i) {
|
||||
if (dummyItem.childNodes[i].localName == "treechildren")
|
||||
dummyItem.removeChild(dummyItem.childNodes[i]);
|
||||
}
|
||||
|
||||
if (dummyItem.getAttribute("open") == "true") {
|
||||
var treechildren = ContentUtils.childByLocalName(aSelectedItem, "treechildren");
|
||||
if (!treechildren) {
|
||||
const kXULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
treechildren = document.createElementNS(kXULNS, "treechildren");
|
||||
aSelectedItem.appendChild(treechildren);
|
||||
}
|
||||
// Insert new item after last item.
|
||||
treechildren.appendChild(dummyItem);
|
||||
}
|
||||
else {
|
||||
if (aSelectedItem.nextSibling)
|
||||
aSelectedItem.parentNode.insertBefore(dummyItem, aSelectedItem.nextSibling);
|
||||
else
|
||||
aSelectedItem.parentNode.appendChild(dummyItem);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (aSelectedItem.nextSibling)
|
||||
aSelectedItem.parentNode.insertBefore(dummyItem, aSelectedItem.nextSibling);
|
||||
else
|
||||
aSelectedItem.parentNode.appendChild(dummyItem);
|
||||
}
|
||||
editCell.setMode("edit");
|
||||
var fn = aMode == "folder" ? this.onEditFolderName : this.onEditBookmarkName;
|
||||
editCell.addObserver(fn, "accept", [editCell, relativeNode, dummyItem]);
|
||||
editCell.addObserver(fn, "reject", [editCell, relativeNode, dummyItem]);
|
||||
}
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Evaluates an event to determine whether or not it affords opening a tree
|
||||
// item. Typically, this is when the left mouse button is used, and provided
|
||||
// the click-rate matches that specified by our owning tree class. For example,
|
||||
// some trees open an item when double clicked (bookmarks/history windows) and
|
||||
// others on a single click (sidebar panels).
|
||||
isValidOpenEvent: function (aEvent)
|
||||
{
|
||||
return !(aEvent.type == "click" &&
|
||||
(aEvent.button != 1 || aEvent.detail != this.openClickCount))
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// For the given selection, selects the best adjacent element. This method is
|
||||
// useful when an action such as a cut or a deletion is performed on a
|
||||
// selection, and focus/selection needs to be restored after the operation
|
||||
// is performed.
|
||||
getNextElement: function (aElement)
|
||||
{
|
||||
if (aElement.nextSibling)
|
||||
return aElement.nextSibling;
|
||||
else if (aElement.previousSibling)
|
||||
return aElement.previousSibling;
|
||||
else
|
||||
return aElement.parentNode.parentNode;
|
||||
},
|
||||
|
||||
selectElement: function (aElement)
|
||||
{
|
||||
this.tree.selectItem(aElement);
|
||||
},
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Add the treeitem element specified by aURI to the tree's current selection.
|
||||
addItemToSelection: function (aURI)
|
||||
{
|
||||
var item = document.getElementById(aURI) // XXX flawed for multiple ids
|
||||
this.tree.addItemToSelection(item);
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Return a set of DOM nodes that represent the selection in the tree widget.
|
||||
// This method is takes a node parameter which is the popupNode for the
|
||||
// document. If the popupNode is not contained by the selection, the
|
||||
// popupNode is selected and the new selection returned.
|
||||
getSelection: function ()
|
||||
{
|
||||
return this.tree.selectedItems;
|
||||
},
|
||||
|
||||
getBestItem: function ()
|
||||
{
|
||||
var seln = this.getSelection ();
|
||||
if (seln.length < 1) {
|
||||
var kids = ContentUtils.childByLocalName(this.tree, "treechildren");
|
||||
if (kids) return kids.lastChild;
|
||||
}
|
||||
else
|
||||
return seln[0];
|
||||
return null;
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Return a set of DOM nodes that represent the selection in the tree widget.
|
||||
// This method is takes a node parameter which is the popupNode for the
|
||||
// document. If the popupNode is not contained by the selection, the
|
||||
// popupNode is selected and the new selection returned.
|
||||
getContextSelection: function (aItemNode)
|
||||
{
|
||||
// How a context-click works:
|
||||
// if the popup node is contained by the selection, the context menu is
|
||||
// built for that selection. However, if the popup node is invoked on a
|
||||
// non-selected node, unless modifiers are pressed**, the previous
|
||||
// selection is discarded and that node selected.
|
||||
var selectedItems = this.tree.selectedItems;
|
||||
for (var i = 0; i < selectedItems.length; ++i) {
|
||||
if (selectedItems[i] == aItemNode)
|
||||
return selectedItems;
|
||||
}
|
||||
this.tree.selectItem(aItemNode);
|
||||
return this.tree.selectedItems;
|
||||
},
|
||||
|
||||
getSelectedFolder: function ()
|
||||
{
|
||||
var selectedItem = this.getBestItem();
|
||||
if (!selectedItem) return "NC:BookmarksRoot";
|
||||
while (selectedItem) {
|
||||
if (selectedItem.getAttribute("container") == "true")
|
||||
return NODE_ID(selectedItem);
|
||||
selectedItem = selectedItem.parentNode.parentNode;
|
||||
}
|
||||
return "NC:BookmarksRoot";
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// For a given start DOM element, find the enclosing DOM element that contains
|
||||
// the template builder RDF resource decorations (id, ref, etc).
|
||||
findRDFNode: function (aStartNode, aIncludeStartNodeFlag)
|
||||
{
|
||||
var temp = aIncludeStartNodeFlag ? aStartNode : aStartNode.parentNode;
|
||||
while (temp && temp.localName != "treeitem")
|
||||
temp = temp.parentNode;
|
||||
return temp || this.tree;
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Tree click events. This handles when to go into inline-edit mode for
|
||||
// editable cells.
|
||||
treeClicked: function (aEvent)
|
||||
{
|
||||
if (this.tree.selectedItems.length > 1 || aEvent.detail > 1 || aEvent.button != 1)
|
||||
return;
|
||||
if (gSelectionTracker.currentItem == this.tree.currentItem &&
|
||||
gSelectionTracker.currentCell == aEvent.target)
|
||||
++gSelectionTracker.clickCount;
|
||||
else
|
||||
gSelectionTracker.clickCount = 0;
|
||||
gSelectionTracker.currentItem = this.tree.currentItem;
|
||||
gSelectionTracker.currentCell = aEvent.target;
|
||||
|
||||
var row = gSelectionTracker.currentItem.firstChild;
|
||||
for (var i = 0; i < row.childNodes.length; ++i) {
|
||||
if (row.childNodes[i] == gSelectionTracker.currentCell) {
|
||||
// Don't allow inline-edit of cells other than name for folders.
|
||||
if (gSelectionTracker.currentItem.getAttribute("type") != NC_NS + "Bookmark" &&
|
||||
i > 1)
|
||||
return;
|
||||
if (gSelectionTracker.clickCount == 1)
|
||||
gBookmarksShell.commands.editCell(this.tree.currentItem, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Tree key events. This handles when to go into inline-edit mode for editable
|
||||
// cells, when to load a URL, etc.
|
||||
treeKeyPress: function (aEvent)
|
||||
{
|
||||
if (this.tree.selectedItems.length > 1) return;
|
||||
if (aEvent.keyCode == 113 && aEvent.shiftKey) {
|
||||
if (this.resolveType(NODE_ID(this.tree.currentItem)) == NC_NS + "Bookmark")
|
||||
gBookmarksShell.commands.editCell (this.tree.currentItem, 1);
|
||||
}
|
||||
else if (aEvent.keyCode == 113)
|
||||
goDoCommand("cmd_rename");
|
||||
else if (aEvent.keyCode == 13 &&
|
||||
this.tree.currentItem.firstChild.getAttribute("inline-edit") != "true")
|
||||
goDoCommand("cmd_open");
|
||||
},
|
||||
|
||||
selectFolderItem: function (aFolderURI, aItemURI, aAdditiveFlag)
|
||||
{
|
||||
var folder = document.getElementById(aFolderURI);
|
||||
var kids = ContentUtils.childByLocalName(aSelectedItem, "treechildren");
|
||||
if (!kids) return;
|
||||
|
||||
var item = kids.firstChild;
|
||||
while (item) {
|
||||
if (item.id == aItemURI) break;
|
||||
item = item.nextSibling;
|
||||
}
|
||||
if (!item) return;
|
||||
|
||||
this.tree[aAdditiveFlag ? "addItemToSelection" : "selectItem"](item);
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Command handling & Updating.
|
||||
controller: {
|
||||
supportsCommand: function (aCommand)
|
||||
{
|
||||
switch(aCommand) {
|
||||
case "cmd_undo":
|
||||
case "cmd_redo":
|
||||
return false;
|
||||
case "cmd_cut":
|
||||
case "cmd_copy":
|
||||
case "cmd_paste":
|
||||
case "cmd_delete":
|
||||
case "cmd_selectAll":
|
||||
return true;
|
||||
case "cmd_open":
|
||||
case "cmd_openfolder":
|
||||
case "cmd_newbookmark":
|
||||
case "cmd_newfolder":
|
||||
case "cmd_newseparator":
|
||||
case "cmd_find":
|
||||
case "cmd_properties":
|
||||
case "cmd_rename":
|
||||
case "cmd_delete":
|
||||
case "cmd_setnewbookmarkfolder":
|
||||
case "cmd_setpersonaltoolbarfolder":
|
||||
case "cmd_setnewsearchfolder":
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
isCommandEnabled: function (aCommand)
|
||||
{
|
||||
var numSelectedItems = gBookmarksShell.tree.selectedItems.length;
|
||||
switch(aCommand) {
|
||||
case "cmd_undo":
|
||||
case "cmd_redo":
|
||||
return false;
|
||||
case "cmd_paste":
|
||||
return gBookmarksShell.canPaste();
|
||||
case "cmd_cut":
|
||||
case "cmd_copy":
|
||||
case "cmd_delete":
|
||||
return numSelectedItems >= 1;
|
||||
case "cmd_selectAll":
|
||||
return true;
|
||||
case "cmd_open":
|
||||
var seln = gBookmarksShell.tree.selectedItems;
|
||||
return numSelectedItems == 1 && seln[0].getAttribute("type") == NC_NS + "Bookmark";
|
||||
case "cmd_openfolder":
|
||||
seln = gBookmarksShell.tree.selectedItems;
|
||||
return numSelectedItems == 1 && seln[0].getAttribute("type") == NC_NS + "Folder";
|
||||
case "cmd_find":
|
||||
case "cmd_newbookmark":
|
||||
case "cmd_newfolder":
|
||||
case "cmd_newseparator":
|
||||
return true;
|
||||
case "cmd_properties":
|
||||
case "cmd_rename":
|
||||
return numSelectedItems == 1;
|
||||
case "cmd_setnewbookmarkfolder":
|
||||
seln = gBookmarksShell.tree.selectedItems;
|
||||
return numSelectedItems == 1 && !(NODE_ID(seln[0]) == "NC:NewBookmarkFolder");
|
||||
case "cmd_setpersonaltoolbarfolder":
|
||||
seln = gBookmarksShell.tree.selectedItems;
|
||||
return numSelectedItems == 1 && !(NODE_ID(seln[0]) == "NC:PersonalToolbarFolder");
|
||||
case "cmd_setnewsearchfolder":
|
||||
seln = gBookmarksShell.tree.selectedItems;
|
||||
return numSelectedItems == 1 && !(NODE_ID(seln[0]) == "NC:NewSearchFolder");
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
doCommand: function (aCommand)
|
||||
{
|
||||
switch(aCommand) {
|
||||
case "cmd_undo":
|
||||
case "cmd_redo":
|
||||
break;
|
||||
case "cmd_paste":
|
||||
case "cmd_copy":
|
||||
case "cmd_cut":
|
||||
case "cmd_delete":
|
||||
case "cmd_newbookmark":
|
||||
case "cmd_newfolder":
|
||||
case "cmd_newseparator":
|
||||
case "cmd_properties":
|
||||
case "cmd_rename":
|
||||
case "cmd_open":
|
||||
case "cmd_openfolder":
|
||||
case "cmd_setnewbookmarkfolder":
|
||||
case "cmd_setpersonaltoolbarfolder":
|
||||
case "cmd_setnewsearchfolder":
|
||||
case "cmd_find":
|
||||
gBookmarksShell.execCommand(aCommand.substring("cmd_".length));
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
onEvent: function (aEvent)
|
||||
{
|
||||
switch (aEvent) {
|
||||
case "tree-select":
|
||||
this.onCommandUpdate();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
onCommandUpdate: function ()
|
||||
{
|
||||
var commands = ["cmd_properties", "cmd_rename", "cmd_copy",
|
||||
"cmd_paste", "cmd_cut", "cmd_delete",
|
||||
"cmd_setpersonaltoolbarfolder", "cmd_setnewbookmarkfolder",
|
||||
"cmd_setnewsearchfolder"];
|
||||
for (var i = 0; i < commands.length; ++i)
|
||||
goUpdateCommand(commands[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var newFolderRDFObserver = {
|
||||
_newFolderURI: null,
|
||||
onAssert: function (aDS, aSource, aProperty, aValue)
|
||||
{
|
||||
try {
|
||||
var value = aValue.QueryInterface(Components.interfaces.nsIRDFResource);
|
||||
if (aDS.URI == "rdf:bookmarks" && aProperty.Value == RDF_NS + "type" &&
|
||||
value.Value == 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) { }
|
||||
};
|
||||
|
||||
var ContentUtils = {
|
||||
childByLocalName: function (aSelectedItem, aLocalName)
|
||||
{
|
||||
var temp = aSelectedItem.firstChild;
|
||||
while (temp) {
|
||||
if (temp.localName == aLocalName)
|
||||
return temp;
|
||||
temp = temp.nextSibling;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<!--
|
||||
- The contents of this file are subject to the Mozilla 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/MPL/
|
||||
-
|
||||
- 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 Communicator.
|
||||
-
|
||||
- The Initial Developer of the Original Code is Netscape
|
||||
- Communications Corp. Portions created by Netscape Communications
|
||||
- Corp. are Copyright (C) 1999 Netscape Communications Corp. All
|
||||
- Rights Reserved.
|
||||
-
|
||||
- Contributor(s):
|
||||
- Ben Goodger <ben@netscape.com> (Original Author)
|
||||
-->
|
||||
|
||||
<!ENTITY newBookmark.title "Add Bookmark">
|
||||
<!ENTITY newbookmark.label "&brandShortName; will add a bookmark to this page.">
|
||||
<!ENTITY name.label "Name:">
|
||||
<!ENTITY name.accesskey "n">
|
||||
<!ENTITY url.label "Location:">
|
||||
<!ENTITY url.accesskey "l">
|
||||
<!ENTITY button.createin.label "Create In >>">
|
||||
<!ENTITY button.createin.accesskey "c">
|
||||
<!ENTITY button.createin2.label "Create In <<">
|
||||
<!ENTITY createin.label "Create in:">
|
||||
<!ENTITY createin.accesskey "i">
|
||||
<!ENTITY button.newfolder.label "New Folder...">
|
||||
<!ENTITY button.newfolder.accesskey "w">
|
||||
<!ENTITY alwayscreateinfolder.label "Don't show this dialog again">
|
||||
<!ENTITY alwayscreateinfolder.accesskey "a">
|
||||
<!ENTITY dontshowmessage.tooltip "When this option is selected, new Bookmarks will be added using the title provided by the page.">
|
Загрузка…
Ссылка в новой задаче