
Made rememberSelection() in certain notify() conditions only get called when necessary, which may or may not fix or reduce the crash, depending on where it was happening Added debug output to better tell where the crash is occurring
1715 lines
50 KiB
JavaScript
1715 lines
50 KiB
JavaScript
/*
|
|
***** BEGIN LICENSE BLOCK *****
|
|
|
|
Copyright (c) 2006 Center for History and New Media
|
|
George Mason University, Fairfax, Virginia, USA
|
|
http://chnm.gmu.edu
|
|
|
|
Licensed under the Educational Community License, Version 1.0 (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.opensource.org/licenses/ecl1.php
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
|
|
***** END LICENSE BLOCK *****
|
|
*/
|
|
|
|
/*
|
|
* This object contains the various functions for the interface
|
|
*/
|
|
var ZoteroPane = new function()
|
|
{
|
|
this.collectionsView = false;
|
|
this.itemsView = false;
|
|
|
|
//Privileged methods
|
|
this.onLoad = onLoad;
|
|
this.onUnload = onUnload;
|
|
this.toggleDisplay = toggleDisplay;
|
|
this.fullScreen = fullScreen;
|
|
this.handleKeyDown = handleKeyDown;
|
|
this.handleKeyUp = handleKeyUp;
|
|
this.setHighlightedRowsCallback = setHighlightedRowsCallback;
|
|
this.handleKeyPress = handleKeyPress;
|
|
this.newItem = newItem;
|
|
this.newCollection = newCollection;
|
|
this.newSearch = newSearch;
|
|
this.openAdvancedSearchWindow = openAdvancedSearchWindow;
|
|
this.toggleTagSelector = toggleTagSelector;
|
|
this.updateTagSelectorSize = updateTagSelectorSize;
|
|
this.getTagSelection = getTagSelection;
|
|
this.updateTagFilter = updateTagFilter;
|
|
this.onCollectionSelected = onCollectionSelected;
|
|
this.itemSelected = itemSelected;
|
|
this.duplicateSelectedItem = duplicateSelectedItem;
|
|
this.deleteSelectedItem = deleteSelectedItem;
|
|
this.deleteSelectedCollection = deleteSelectedCollection;
|
|
this.editSelectedCollection = editSelectedCollection;
|
|
this.copySelectedItemsToClipboard = copySelectedItemsToClipboard;
|
|
this.clearQuicksearch = clearQuicksearch;
|
|
this.handleSearchKeypress = handleSearchKeypress;
|
|
this.handleSearchInput = handleSearchInput;
|
|
this.search = search;
|
|
this.selectItem = selectItem;
|
|
this.getSelectedCollection = getSelectedCollection;
|
|
this.getSelectedSavedSearch = getSelectedSavedSearch;
|
|
this.getSelectedItems = getSelectedItems;
|
|
this.getSortedItems = getSortedItems;
|
|
this.getSortField = getSortField;
|
|
this.getSortDirection = getSortDirection;
|
|
this.buildCollectionContextMenu = buildCollectionContextMenu;
|
|
this.buildItemContextMenu = buildItemContextMenu;
|
|
this.onDoubleClick = onDoubleClick;
|
|
this.loadURI = loadURI;
|
|
this.setItemsPaneMessage = setItemsPaneMessage;
|
|
this.clearItemsPaneMessage = clearItemsPaneMessage;
|
|
this.contextPopupShowing = contextPopupShowing;
|
|
this.openNoteWindow = openNoteWindow;
|
|
this.newNote = newNote;
|
|
this.addTextToNote = addTextToNote;
|
|
this.addItemFromPage = addItemFromPage;
|
|
this.addAttachmentFromDialog = addAttachmentFromDialog;
|
|
this.addAttachmentFromPage = addAttachmentFromPage;
|
|
this.viewAttachment = viewAttachment;
|
|
this.viewSelectedAttachment = viewSelectedAttachment;
|
|
this.showSelectedAttachmentInFilesystem = showSelectedAttachmentInFilesystem;
|
|
this.showAttachmentNotFoundDialog = showAttachmentNotFoundDialog;
|
|
this.relinkAttachment = relinkAttachment;
|
|
|
|
var self = this;
|
|
|
|
/*
|
|
* Called when the window is open
|
|
*/
|
|
function onLoad()
|
|
{
|
|
if (!Zotero || !Zotero.initialized) {
|
|
return;
|
|
}
|
|
|
|
if(Zotero.Prefs.get("zoteroPaneOnTop"))
|
|
{
|
|
var oldPane = document.getElementById('zotero-pane');
|
|
var oldSplitter = document.getElementById('zotero-splitter');
|
|
var appContent = document.getElementById('appcontent');
|
|
|
|
var newPane = document.createElement('hbox');
|
|
newPane.setAttribute('id','zotero-pane');
|
|
newPane.setAttribute('persist','height');
|
|
newPane.setAttribute('hidden', true);
|
|
newPane.setAttribute('onkeydown', 'ZoteroPane.handleKeyDown(event, this.id)');
|
|
newPane.setAttribute('onkeyup', 'ZoteroPane.handleKeyUp(event, this.id)');
|
|
|
|
newPane.height = oldPane.height;
|
|
while(oldPane.hasChildNodes())
|
|
newPane.appendChild(oldPane.firstChild);
|
|
appContent.removeChild(oldPane);
|
|
appContent.insertBefore(newPane, document.getElementById('content'));
|
|
|
|
var newSplitter = document.createElement('splitter');
|
|
newSplitter.setAttribute('id','zotero-splitter');
|
|
newSplitter.setAttribute('hidden', true);
|
|
newSplitter.setAttribute('resizebefore','closest');
|
|
newSplitter.setAttribute('resizeafter','closest');
|
|
newSplitter.setAttribute('onmouseup', 'ZoteroPane.updateTagSelectorSize()');
|
|
appContent.removeChild(oldSplitter);
|
|
appContent.insertBefore(newSplitter, document.getElementById('content'));
|
|
|
|
document.getElementById('zotero-tb-fullscreen').setAttribute('zoterotop','true');
|
|
}
|
|
|
|
Zotero.setFontSize(document.getElementById('zotero-pane'))
|
|
|
|
//Initialize collections view
|
|
this.collectionsView = new Zotero.CollectionTreeView();
|
|
var collectionsTree = document.getElementById('zotero-collections-tree');
|
|
collectionsTree.view = this.collectionsView;
|
|
collectionsTree.controllers.appendController(new Zotero.CollectionTreeCommandController(collectionsTree));
|
|
|
|
var itemsTree = document.getElementById('zotero-items-tree');
|
|
itemsTree.controllers.appendController(new Zotero.ItemTreeCommandController(itemsTree));
|
|
|
|
this.updateTagSelectorSize();
|
|
|
|
// Create the New Item (+) menu with each item type
|
|
var addMenu = document.getElementById('zotero-tb-add').firstChild;
|
|
var separator = document.getElementById('zotero-tb-add').firstChild.firstChild;
|
|
var moreMenu = document.getElementById('zotero-tb-add-more');
|
|
var itemTypes = Zotero.ItemTypes.getPrimaryTypes();
|
|
for(var i = 0; i<itemTypes.length; i++)
|
|
{
|
|
var menuitem = document.createElement("menuitem");
|
|
menuitem.setAttribute("label", Zotero.getString("itemTypes."+itemTypes[i]['name']));
|
|
menuitem.setAttribute("oncommand","ZoteroPane.newItem("+itemTypes[i]['id']+")");
|
|
menuitem.setAttribute("tooltiptext", "");
|
|
addMenu.insertBefore(menuitem, separator);
|
|
}
|
|
// Create submenu for secondary item types
|
|
var itemTypes = Zotero.ItemTypes.getSecondaryTypes();
|
|
for(var i = 0; i<itemTypes.length; i++)
|
|
{
|
|
var menuitem = document.createElement("menuitem");
|
|
menuitem.setAttribute("label", Zotero.getString("itemTypes."+itemTypes[i]['name']));
|
|
menuitem.setAttribute("oncommand","ZoteroPane.newItem("+itemTypes[i]['id']+")");
|
|
menuitem.setAttribute("tooltiptext", "");
|
|
moreMenu.appendChild(menuitem);
|
|
}
|
|
|
|
var menu = document.getElementById("contentAreaContextMenu");
|
|
menu.addEventListener("popupshowing", ZoteroPane.contextPopupShowing, false);
|
|
|
|
Zotero.Keys.windowInit(document);
|
|
}
|
|
|
|
|
|
/*
|
|
* Called when the window closes
|
|
*/
|
|
function onUnload()
|
|
{
|
|
if (!Zotero || !Zotero.initialized) {
|
|
return;
|
|
}
|
|
|
|
var tagSelector = document.getElementById('zotero-tag-selector');
|
|
tagSelector.unregister();
|
|
|
|
this.collectionsView.unregister();
|
|
if (this.itemsView)
|
|
this.itemsView.unregister();
|
|
}
|
|
|
|
/*
|
|
* Hides/displays the Zotero interface
|
|
*/
|
|
function toggleDisplay()
|
|
{
|
|
// Visible == target visibility
|
|
var visible = document.getElementById('zotero-pane').getAttribute('hidden') == 'true';
|
|
|
|
// If Zotero not initialized, try to get the error handler
|
|
// or load the default error page
|
|
if (visible && (!Zotero || !Zotero.initialized)) {
|
|
if (Zotero) {
|
|
var errFunc = Zotero.startupErrorHandler;
|
|
}
|
|
|
|
if (errFunc) {
|
|
errFunc();
|
|
}
|
|
else {
|
|
// TODO: Add a better error page/window here with reporting
|
|
// instructions
|
|
// window.loadURI('chrome://zotero/content/error.xul');
|
|
// TODO: localize if possible
|
|
alert("There was an error starting Zotero.");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
document.getElementById('zotero-pane').setAttribute('hidden', !visible);
|
|
document.getElementById('zotero-splitter').setAttribute('hidden', !visible);
|
|
|
|
if (visible) {
|
|
// Focus the quicksearch on pane open
|
|
setTimeout("document.getElementById('zotero-tb-search').inputField.select();", 1);
|
|
}
|
|
else {
|
|
document.getElementById('content').setAttribute('collapsed', false);
|
|
document.getElementById('zotero-tb-fullscreen').setAttribute('fullscreenmode', false);
|
|
|
|
// Return focus to the browser content pane
|
|
window.content.window.focus();
|
|
}
|
|
}
|
|
|
|
function fullScreen()
|
|
{
|
|
var collapsed = document.getElementById('content').getAttribute('collapsed') == 'true';
|
|
// Turn Z-pane flex on to stretch to window in full-screen, but off otherwise so persist works
|
|
document.getElementById('zotero-pane').setAttribute('flex', collapsed ? "0" : "1");
|
|
document.getElementById('content').setAttribute('collapsed', !collapsed);
|
|
document.getElementById('zotero-splitter').setAttribute('hidden', !collapsed);
|
|
document.getElementById('zotero-tb-fullscreen').setAttribute('fullscreenmode', !collapsed);
|
|
}
|
|
|
|
|
|
/*
|
|
* Trigger actions based on keyboard shortcuts
|
|
*/
|
|
function handleKeyDown(event, from) {
|
|
if (from == 'zotero-pane') {
|
|
// Highlight collections containing selected items
|
|
//
|
|
// We use Control (17) on Windows because Alt triggers the menubar;
|
|
// otherwise we use Alt/Option (18)
|
|
if ((Zotero.isWin && event.keyCode == 17 && !event.altKey) ||
|
|
(!Zotero.isWin && event.keyCode == 18 && !event.ctrlKey)
|
|
&& !event.shiftKey && !event.metaKey) {
|
|
|
|
this.highlightTimer = Components.classes["@mozilla.org/timer;1"].
|
|
createInstance(Components.interfaces.nsITimer);
|
|
// {} implements nsITimerCallback
|
|
this.highlightTimer.initWithCallback({
|
|
notify: ZoteroPane.setHighlightedRowsCallback
|
|
}, 225, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
|
|
}
|
|
else if ((Zotero.isWin && event.ctrlKey) ||
|
|
(!Zotero.isWin && event.altKey)) {
|
|
if (this.highlightTimer) {
|
|
this.highlightTimer.cancel();
|
|
this.highlightTimer = null;
|
|
}
|
|
ZoteroPane.collectionsView.setHighlightedRows();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// Ignore keystrokes if Zotero pane is closed
|
|
if (document.getElementById('zotero-pane').getAttribute('hidden') == 'true') {
|
|
return;
|
|
}
|
|
|
|
var useShift = Zotero.isMac;
|
|
|
|
var key = String.fromCharCode(event.which);
|
|
if (!key) {
|
|
Zotero.debug('No key');
|
|
return;
|
|
}
|
|
|
|
// Ignore modifiers other than accel-alt (or accel-shift if useShift is on)
|
|
if (!((Zotero.isMac ? event.metaKey : event.ctrlKey) &&
|
|
useShift ? event.shiftKey : event.altKey)) {
|
|
return;
|
|
}
|
|
|
|
var command = Zotero.Keys.getCommand(key);
|
|
if (!command) {
|
|
return;
|
|
}
|
|
|
|
Zotero.debug(command);
|
|
|
|
switch (command) {
|
|
case 'library':
|
|
document.getElementById('zotero-collections-tree').focus();
|
|
ZoteroPane.collectionsView.selection.select(0);
|
|
break;
|
|
case 'quicksearch':
|
|
document.getElementById('zotero-tb-search').select();
|
|
break;
|
|
case 'newItem':
|
|
ZoteroPane.newItem(2); // book
|
|
document.getElementById('zotero-editpane-type-menu').focus();
|
|
break;
|
|
case 'newNote':
|
|
// Use key that's not the modifier as the popup toggle
|
|
ZoteroPane.newNote(useShift ? event.altKey : event.shiftKey);
|
|
break;
|
|
case 'toggleTagSelector':
|
|
ZoteroPane.toggleTagSelector();
|
|
break;
|
|
case 'toggleFullscreen':
|
|
ZoteroPane.fullScreen();
|
|
break;
|
|
case 'copySelectedItemsToClipboard':
|
|
ZoteroPane.copySelectedItemsToClipboard();
|
|
break;
|
|
default:
|
|
throw ('Command "' + command + '" not found in ZoteroPane.handleKeyDown()');
|
|
}
|
|
|
|
event.preventDefault();
|
|
}
|
|
|
|
|
|
function handleKeyUp(event, from) {
|
|
if (from == 'zotero-pane') {
|
|
if ((Zotero.isWin && event.keyCode == 17) ||
|
|
(!Zotero.isWin && event.keyCode == 18)) {
|
|
if (this.highlightTimer) {
|
|
this.highlightTimer.cancel();
|
|
this.highlightTimer = null;
|
|
}
|
|
ZoteroPane.collectionsView.setHighlightedRows();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Highlights collections containing selected items on Ctrl (Win) or
|
|
* Option/Alt (Mac/Linux) press
|
|
*/
|
|
function setHighlightedRowsCallback() {
|
|
var itemIDs = ZoteroPane.getSelectedItems(true);
|
|
if (itemIDs && itemIDs.length) {
|
|
var collectionIDs = Zotero.Collections.getCollectionsContainingItems(itemIDs, true);
|
|
if (collectionIDs) {
|
|
ZoteroPane.collectionsView.setHighlightedRows(collectionIDs);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
function handleKeyPress(event, from) {
|
|
var key = String.fromCharCode(event.which);
|
|
|
|
if (from == 'zotero-collections-tree') {
|
|
if (event.keyCode == event.DOM_VK_BACK_SPACE ||
|
|
event.keyCode == event.DOM_VK_DELETE) {
|
|
ZoteroPane.deleteSelectedCollection();
|
|
event.preventDefault();
|
|
return;
|
|
}
|
|
}
|
|
else if (from == 'zotero-items-tree') {
|
|
if (event.keyCode == event.DOM_VK_BACK_SPACE ||
|
|
event.keyCode == event.DOM_VK_DELETE) {
|
|
ZoteroPane.deleteSelectedItem();
|
|
event.preventDefault();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Create a new item
|
|
*
|
|
* _data_ is an optional object with field:value for itemData
|
|
*/
|
|
function newItem(typeID, data)
|
|
{
|
|
var item = new Zotero.Item(typeID);
|
|
|
|
for (var i in data)
|
|
{
|
|
item.setField(i, data[i]);
|
|
}
|
|
|
|
item.save();
|
|
|
|
if (this.itemsView && this.itemsView._itemGroup.isCollection()) {
|
|
this.itemsView._itemGroup.ref.addItem(item.getID());
|
|
}
|
|
|
|
//set to Info tab
|
|
document.getElementById('zotero-view-item').selectedIndex = 0;
|
|
|
|
this.selectItem(item.getID());
|
|
|
|
return item;
|
|
}
|
|
|
|
function newCollection(parent)
|
|
{
|
|
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
|
.getService(Components.interfaces.nsIPromptService);
|
|
|
|
var untitled = Zotero.DB.getNextName('collections', 'collectionName',
|
|
Zotero.getString('pane.collections.untitled'));
|
|
|
|
var newName = { value: untitled };
|
|
var result = promptService.prompt(window, "",
|
|
Zotero.getString('pane.collections.name'), newName, "", {});
|
|
|
|
if (!result)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!newName.value)
|
|
{
|
|
newName.value = untitled;
|
|
}
|
|
|
|
Zotero.Collections.add(newName.value, parent);
|
|
}
|
|
|
|
function newSearch()
|
|
{
|
|
var s = new Zotero.Search();
|
|
s.addCondition('title', 'contains', '');
|
|
|
|
var untitled = Zotero.getString('pane.collections.untitled');
|
|
untitled = Zotero.DB.getNextName('savedSearches', 'savedSearchName',
|
|
Zotero.getString('pane.collections.untitled'));
|
|
var io = {dataIn: {search: s, name: untitled}, dataOut: null};
|
|
window.openDialog('chrome://zotero/content/searchDialog.xul','','chrome,modal',io);
|
|
}
|
|
|
|
|
|
function openAdvancedSearchWindow() {
|
|
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
|
.getService(Components.interfaces.nsIWindowMediator);
|
|
var enumerator = wm.getEnumerator('zotero:search');
|
|
while (enumerator.hasMoreElements()) {
|
|
var win = enumerator.getNext();
|
|
}
|
|
|
|
if (win) {
|
|
win.focus();
|
|
return;
|
|
}
|
|
|
|
var s = new Zotero.Search();
|
|
s.addCondition('title', 'contains', '');
|
|
var io = {dataIn: {search: s}, dataOut: null};
|
|
window.openDialog('chrome://zotero/content/advancedSearch.xul', '', 'chrome,dialog=no,centerscreen', io);
|
|
}
|
|
|
|
|
|
function toggleTagSelector(){
|
|
var zoteroPane = document.getElementById('zotero-pane');
|
|
var splitter = document.getElementById('zotero-tags-splitter');
|
|
var tagSelector = document.getElementById('zotero-tag-selector');
|
|
|
|
var showing = tagSelector.getAttribute('collapsed') == 'true';
|
|
tagSelector.setAttribute('collapsed', !showing);
|
|
splitter.setAttribute('collapsed', !showing);
|
|
this.updateTagSelectorSize();
|
|
|
|
// If showing, set scope to items in current view
|
|
// and focus filter textbox
|
|
if (showing) {
|
|
_setTagScope();
|
|
tagSelector.focusTextbox();
|
|
}
|
|
// If hiding, clear selection
|
|
else {
|
|
tagSelector.uninit();
|
|
}
|
|
}
|
|
|
|
|
|
function updateTagSelectorSize() {
|
|
var zoteroPane = document.getElementById('zotero-pane');
|
|
var tagSelector = document.getElementById('zotero-tag-selector');
|
|
|
|
height = tagSelector.boxObject.height;
|
|
|
|
/*
|
|
Zotero.debug(tagSelector.boxObject.height);
|
|
Zotero.debug(tagSelector.getAttribute('height'));
|
|
Zotero.debug(zoteroPane.boxObject.height);
|
|
Zotero.debug(zoteroPane.getAttribute('height'));
|
|
*/
|
|
|
|
// Don't let the Z-pane jump back down to its previous height
|
|
// (if shrinking or hiding the tag selector let it clear the min-height)
|
|
if (zoteroPane.getAttribute('height') < zoteroPane.boxObject.height) {
|
|
zoteroPane.setAttribute('height', zoteroPane.boxObject.height);
|
|
}
|
|
|
|
if (tagSelector.getAttribute('collapsed') == 'true') {
|
|
// 32px is the default Z pane min-height in overlay.css
|
|
height = 32;
|
|
}
|
|
else {
|
|
// tS.boxObject.height doesn't exist at startup, so get from attribute
|
|
if (!height) {
|
|
height = parseInt(tagSelector.getAttribute('height'));
|
|
}
|
|
// 121px seems to be enough room for the toolbar and collections
|
|
// tree at minimum height
|
|
height = height + 125;
|
|
}
|
|
|
|
//Zotero.debug('Setting Zotero pane minheight to ' + height);
|
|
zoteroPane.setAttribute('minheight', height);
|
|
|
|
// Fix bug whereby resizing the Z pane downward after resizing
|
|
// the tag selector up and then down sometimes caused the Z pane to
|
|
// stay at a fixed size and get pushed below the bottom
|
|
tagSelector.height++;
|
|
tagSelector.height--;
|
|
}
|
|
|
|
|
|
function getTagSelection(){
|
|
var tagSelector = document.getElementById('zotero-tag-selector');
|
|
return tagSelector.selection ? tagSelector.selection : {};
|
|
}
|
|
|
|
|
|
/*
|
|
* Sets the tag filter on the items view
|
|
*/
|
|
function updateTagFilter(){
|
|
this.itemsView.setFilter('tags', getTagSelection());
|
|
}
|
|
|
|
|
|
/*
|
|
* Set the tags scope to the items in the current view
|
|
*
|
|
* Passed to the items tree to trigger on changes
|
|
*/
|
|
function _setTagScope() {
|
|
var itemgroup = self.collectionsView.
|
|
_getItemAtRow(self.collectionsView.selection.currentIndex);
|
|
var tagSelector = document.getElementById('zotero-tag-selector');
|
|
if (!tagSelector.getAttribute('collapsed') ||
|
|
tagSelector.getAttribute('collapsed') == 'false') {
|
|
Zotero.debug('Updating tag selector with current tags');
|
|
tagSelector.scope = itemgroup.getChildTags();
|
|
}
|
|
}
|
|
|
|
|
|
function onCollectionSelected()
|
|
{
|
|
if (this.itemsView)
|
|
{
|
|
this.itemsView.unregister();
|
|
}
|
|
|
|
document.getElementById('zotero-tb-search').value = "";
|
|
|
|
if (this.collectionsView.selection.count == 1 && this.collectionsView.selection.currentIndex != -1) {
|
|
var itemgroup = this.collectionsView._getItemAtRow(this.collectionsView.selection.currentIndex);
|
|
itemgroup.setSearch('');
|
|
itemgroup.setTags(getTagSelection());
|
|
|
|
Zotero.UnresponsiveScriptIndicator.disable();
|
|
this.itemsView = new Zotero.ItemTreeView(itemgroup);
|
|
this.itemsView.addCallback(_setTagScope);
|
|
document.getElementById('zotero-items-tree').view = this.itemsView;
|
|
Zotero.debug('crashdebug6');
|
|
this.itemsView.selection.clearSelection();
|
|
Zotero.UnresponsiveScriptIndicator.enable();
|
|
}
|
|
else
|
|
{
|
|
document.getElementById('zotero-items-tree').view = this.itemsView = null;
|
|
}
|
|
}
|
|
|
|
function itemSelected()
|
|
{
|
|
if (this.itemsView && this.itemsView.selection.count == 1 && this.itemsView.selection.currentIndex != -1)
|
|
{
|
|
var item = this.itemsView._getItemAtRow(this.itemsView.selection.currentIndex);
|
|
|
|
if(item.isNote())
|
|
{
|
|
var noteEditor = document.getElementById('zotero-note-editor');
|
|
noteEditor.item = null;
|
|
noteEditor.note = item.ref;
|
|
document.getElementById('zotero-view-note-button').setAttribute('noteID',item.ref.getID());
|
|
if(item.ref.getSource())
|
|
{
|
|
document.getElementById('zotero-view-note-button').setAttribute('sourceID',item.ref.getSource());
|
|
}
|
|
else
|
|
{
|
|
document.getElementById('zotero-view-note-button').removeAttribute('sourceID');
|
|
}
|
|
document.getElementById('zotero-item-pane-content').selectedIndex = 2;
|
|
}
|
|
else if(item.isAttachment())
|
|
{
|
|
// DEBUG: this is annoying -- we really want to use an abstracted
|
|
// version of createValueElement() from itemPane.js
|
|
// (ideally in an XBL binding)
|
|
|
|
// Wrap title to multiple lines if necessary
|
|
var label = document.getElementById('zotero-attachment-label');
|
|
while (label.hasChildNodes())
|
|
{
|
|
label.removeChild(label.firstChild);
|
|
}
|
|
var val = item.getField('title');
|
|
|
|
var firstSpace = val.indexOf(" ");
|
|
// Crop long uninterrupted text
|
|
if ((firstSpace == -1 && val.length > 29 ) || firstSpace > 29)
|
|
{
|
|
label.setAttribute('crop', 'end');
|
|
label.setAttribute('value', val);
|
|
}
|
|
// Create a <description> element, essentially
|
|
else
|
|
{
|
|
label.appendChild(document.createTextNode(val));
|
|
}
|
|
|
|
// For the time being, use a silly little popup
|
|
label.className = 'zotero-clicky';
|
|
label.onclick = function(event){
|
|
var nsIPS = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
|
.getService(Components.interfaces.nsIPromptService);
|
|
|
|
var newTitle = { value: val };
|
|
var checkState = { value: Zotero.Prefs.get('lastRenameAssociatedFile') };
|
|
|
|
while (true) {
|
|
var result = nsIPS.prompt(window,
|
|
Zotero.getString('pane.item.attachments.rename.title'),
|
|
'', newTitle,
|
|
Zotero.getString('pane.item.attachments.rename.renameAssociatedFile'),
|
|
checkState);
|
|
|
|
// If they hit cancel or left it blank
|
|
if (!result || !newTitle.value) {
|
|
return;
|
|
}
|
|
|
|
Zotero.Prefs.set('lastRenameAssociatedFile', checkState.value);
|
|
|
|
// Rename associated file
|
|
if (checkState.value) {
|
|
var renamed = item.ref.renameAttachmentFile(newTitle.value);
|
|
if (renamed == -1) {
|
|
var confirmed = confirm(newTitle.value + ' exists. Overwrite existing file?');
|
|
if (confirmed) {
|
|
item.ref.renameAttachmentFile(newTitle.value, true);
|
|
break;
|
|
}
|
|
// If they said not to overwrite existing file,
|
|
// start again
|
|
continue;
|
|
}
|
|
else if (renamed == -2 || !renamed) {
|
|
alert(Zotero.getString('pane.item.attachments.rename.error'));
|
|
return;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (newTitle.value != val) {
|
|
item.ref.setField('title', newTitle.value);
|
|
item.ref.save();
|
|
}
|
|
}
|
|
|
|
|
|
var isImportedURL = item.ref.getAttachmentLinkMode() == Zotero.Attachments.LINK_MODE_IMPORTED_URL;
|
|
|
|
// Metadata for URL's
|
|
if (item.ref.getAttachmentLinkMode() == Zotero.Attachments.LINK_MODE_LINKED_URL
|
|
|| isImportedURL)
|
|
{
|
|
// "View Page"/"View Snapshot" label
|
|
if (isImportedURL)
|
|
{
|
|
var str = Zotero.getString('pane.item.attachments.view.snapshot');
|
|
}
|
|
else
|
|
{
|
|
var str = Zotero.getString('pane.item.attachments.view.link');
|
|
}
|
|
|
|
document.getElementById('zotero-attachment-show').setAttribute('hidden', !isImportedURL);
|
|
|
|
// URL
|
|
document.getElementById('zotero-attachment-url').setAttribute('value', item.getField('url'));
|
|
document.getElementById('zotero-attachment-url').setAttribute('hidden', false);
|
|
// Access date
|
|
document.getElementById('zotero-attachment-accessed').setAttribute('value',
|
|
Zotero.getString('itemFields.accessDate') + ': '
|
|
+ Zotero.Date.sqlToDate(item.getField('accessDate'), true).toLocaleString());
|
|
document.getElementById('zotero-attachment-accessed').setAttribute('hidden', false);
|
|
}
|
|
// Metadata for files
|
|
else
|
|
{
|
|
var str = Zotero.getString('pane.item.attachments.view.file');
|
|
document.getElementById('zotero-attachment-show').setAttribute('hidden', false);
|
|
document.getElementById('zotero-attachment-url').setAttribute('hidden', true);
|
|
document.getElementById('zotero-attachment-accessed').setAttribute('hidden', true);
|
|
}
|
|
|
|
document.getElementById('zotero-attachment-view').setAttribute('label', str);
|
|
|
|
var noteEditor = document.getElementById('zotero-attachment-note-editor');
|
|
noteEditor.item = null;
|
|
noteEditor.note = item.ref;
|
|
|
|
document.getElementById('zotero-item-pane-content').selectedIndex = 3;
|
|
}
|
|
else
|
|
{
|
|
ZoteroItemPane.viewItem(item.ref);
|
|
document.getElementById('zotero-item-pane-content').selectedIndex = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
document.getElementById('zotero-item-pane-content').selectedIndex = 0;
|
|
|
|
var label = document.getElementById('zotero-view-selected-label');
|
|
|
|
if (this.itemsView && this.itemsView.selection.count) {
|
|
label.value = Zotero.getString('pane.item.selected.multiple', this.itemsView.selection.count);
|
|
}
|
|
else {
|
|
label.value = Zotero.getString('pane.item.selected.zero');
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
function duplicateSelectedItem() {
|
|
var newItemID = this.getSelectedItems()[0].clone();
|
|
var newItem = Zotero.Items.get(newItemID);
|
|
|
|
if (this.itemsView._itemGroup.isCollection()) {
|
|
this.itemsView._itemGroup.ref.addItem(newItem.getID());
|
|
this.selectItem(newItemID);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* _force_ deletes item from DB even if removing from a collection or search
|
|
*/
|
|
function deleteSelectedItem(force)
|
|
{
|
|
if (this.itemsView && this.itemsView.selection.count > 0) {
|
|
if (!force){
|
|
if (this.itemsView._itemGroup.isCollection()) {
|
|
var noPrompt = true;
|
|
}
|
|
// Do nothing in search view
|
|
else if (this.itemsView._itemGroup.isSearch()) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
var eraseChildren = {value: true};
|
|
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
|
.getService(Components.interfaces.nsIPromptService);
|
|
var hasChildren;
|
|
|
|
if (!this.getSelectedCollection()) {
|
|
var start = new Object();
|
|
var end = new Object();
|
|
for (var i=0, len=this.itemsView.selection.getRangeCount(); i<len; i++) {
|
|
this.itemsView.selection.getRangeAt(i,start,end);
|
|
for (var j=start.value; j<=end.value; j++)
|
|
if (this.itemsView._getItemAtRow(j).numChildren()) {
|
|
hasChildren = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (noPrompt || promptService.confirmCheck(
|
|
window,
|
|
Zotero.getString('pane.items.delete.title'),
|
|
Zotero.getString('pane.items.delete' + (this.itemsView.selection.count>1 ? '.multiple' : '')),
|
|
hasChildren ? Zotero.getString('pane.items.delete.attached') : '',
|
|
eraseChildren))
|
|
{
|
|
this.itemsView.deleteSelection(eraseChildren.value, force);
|
|
}
|
|
}
|
|
}
|
|
|
|
function deleteSelectedCollection()
|
|
{
|
|
if (this.collectionsView.selection.count == 1) {
|
|
var row =
|
|
this.collectionsView._getItemAtRow(this.collectionsView.selection.currentIndex);
|
|
|
|
if (row.isCollection())
|
|
{
|
|
if (confirm(Zotero.getString('pane.collections.delete')))
|
|
{
|
|
this.collectionsView.deleteSelection();
|
|
}
|
|
}
|
|
else if (row.isSearch())
|
|
{
|
|
if (confirm(Zotero.getString('pane.collections.deleteSearch')))
|
|
{
|
|
this.collectionsView.deleteSelection();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function editSelectedCollection()
|
|
{
|
|
if (this.collectionsView.selection.count > 0) {
|
|
var collection = this.collectionsView._getItemAtRow(this.collectionsView.selection.currentIndex);
|
|
|
|
if(collection.isCollection())
|
|
{
|
|
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
|
.getService(Components.interfaces.nsIPromptService);
|
|
|
|
var newName = { value: collection.getName() };
|
|
var result = promptService.prompt(window, "",
|
|
Zotero.getString('pane.collections.rename'), newName, "", {});
|
|
|
|
if (result && newName.value)
|
|
{
|
|
collection.ref.rename(newName.value);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var s = new Zotero.Search();
|
|
s.load(collection.ref['id']);
|
|
var io = {dataIn: {search: s, name: collection.getName()}, dataOut: null};
|
|
window.openDialog('chrome://zotero/content/searchDialog.xul','','chrome,modal',io);
|
|
if(io.dataOut)
|
|
this.onCollectionSelected(); //reload itemsView
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
function copySelectedItemsToClipboard() {
|
|
var items = this.getSelectedItems();
|
|
if (!items.length) {
|
|
return;
|
|
}
|
|
|
|
// Make sure at least one item is not a standalone note or attachment
|
|
var haveRegularItem = false;
|
|
for each(var item in items) {
|
|
if (item.isRegularItem()) {
|
|
haveRegularItem = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!haveRegularItem) {
|
|
window.alert(Zotero.getString("fileInterface.noReferencesError"));
|
|
return;
|
|
}
|
|
|
|
var [mode, format] = Zotero.Prefs.get("export.quickCopy.setting").split('=');
|
|
Zotero.debug(mode);
|
|
Zotero.debug(format);
|
|
if (mode == 'bibliography') {
|
|
Zotero_File_Interface.copyItemsToClipboard(items, format);
|
|
}
|
|
else if (mode == 'export') {
|
|
Zotero_File_Interface.exportItemsToClipboard(items, format);
|
|
}
|
|
}
|
|
|
|
|
|
function clearQuicksearch() {
|
|
document.getElementById('zotero-tb-search').value = "";
|
|
document.getElementById('zotero-tb-search').doCommand('cmd_zotero_search');
|
|
}
|
|
|
|
|
|
function handleSearchKeypress(textbox, event) {
|
|
// Events that turn find-as-you-type on
|
|
if (event.keyCode == event.DOM_VK_ESCAPE) {
|
|
textbox.value = '';
|
|
ZoteroPane.setItemsPaneMessage(Zotero.getString('searchInProgress'));
|
|
setTimeout("document.getElementById('zotero-tb-search').doCommand('cmd_zotero_search'); ZoteroPane.clearItemsPaneMessage();", 1);
|
|
}
|
|
else if (event.keyCode == event.DOM_VK_RETURN ||
|
|
event.keyCode == event.DOM_VK_ENTER) {
|
|
textbox.skipTimeout = true;
|
|
ZoteroPane.setItemsPaneMessage(Zotero.getString('searchInProgress'));
|
|
setTimeout("document.getElementById('zotero-tb-search').doCommand('cmd_zotero_search'); ZoteroPane.clearItemsPaneMessage();", 1);
|
|
}
|
|
}
|
|
|
|
|
|
function handleSearchInput(textbox, event) {
|
|
// This is the new length, except, it seems, when the change is a
|
|
// result of Undo or Redo
|
|
if (!textbox.value.length) {
|
|
textbox.skipTimeout = true;
|
|
ZoteroPane.setItemsPaneMessage(Zotero.getString('searchInProgress'));
|
|
setTimeout("document.getElementById('zotero-tb-search').doCommand('cmd_zotero_search'); ZoteroPane.clearItemsPaneMessage();", 1);
|
|
}
|
|
else if (textbox.value.indexOf('"') != -1) {
|
|
ZoteroPane.setItemsPaneMessage(Zotero.getString('advancedSearchMode'));
|
|
}
|
|
}
|
|
|
|
|
|
function search()
|
|
{
|
|
if (this.itemsView) {
|
|
var searchVal = document.getElementById('zotero-tb-search').value;
|
|
this.itemsView.setFilter('search', searchVal);
|
|
|
|
document.getElementById('zotero-tb-search-cancel').hidden = searchVal == "";
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* Select item in current collection or, if not there, in Library
|
|
*
|
|
* If _inLibrary_, force switch to Library
|
|
* If _expand_, open item if it's a container
|
|
*/
|
|
function selectItem(itemID, inLibrary, expand)
|
|
{
|
|
if (!itemID) {
|
|
return;
|
|
}
|
|
|
|
if (this.itemsView) {
|
|
if (!this.itemsView._itemGroup.isLibrary() && inLibrary) {
|
|
this.collectionsView.selection.select(0);
|
|
}
|
|
|
|
var selected = this.itemsView.selectItem(itemID, expand);
|
|
if (!selected) {
|
|
this.collectionsView.selection.select(0);
|
|
this.itemsView.selectItem(itemID, expand);
|
|
}
|
|
}
|
|
}
|
|
|
|
function getSelectedCollection(asID) {
|
|
if (this.collectionsView.selection
|
|
&& this.collectionsView.selection.count > 0
|
|
&& this.collectionsView.selection.currentIndex != -1) {
|
|
var collection = this.collectionsView._getItemAtRow(this.collectionsView.selection.currentIndex);
|
|
if (collection && collection.isCollection()) {
|
|
if (asID) {
|
|
return collection.ref.getID();
|
|
}
|
|
else {
|
|
return collection.ref;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function getSelectedSavedSearch(asID)
|
|
{
|
|
if (this.collectionsView.selection.count > 0 && this.collectionsView.selection.currentIndex != -1) {
|
|
var collection = this.collectionsView._getItemAtRow(this.collectionsView.selection.currentIndex);
|
|
if (collection && collection.isSearch()) {
|
|
if (asID) {
|
|
return collection.ref.id;
|
|
}
|
|
else {
|
|
return collection.ref;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* Return an array of Item objects for selected items
|
|
*
|
|
* If asIDs is true, return an array of itemIDs instead
|
|
*/
|
|
function getSelectedItems(asIDs)
|
|
{
|
|
if (this.itemsView) {
|
|
return this.itemsView.getSelectedItems(asIDs);
|
|
}
|
|
return [];
|
|
}
|
|
|
|
|
|
/*
|
|
* Returns an array of item ids of visible items in current sort order
|
|
*/
|
|
function getSortedItems() {
|
|
if (!this.itemsView) {
|
|
return false;
|
|
}
|
|
|
|
return this.itemsView.getSortedItems();
|
|
}
|
|
|
|
|
|
function getSortField() {
|
|
if (!this.itemsView) {
|
|
return false;
|
|
}
|
|
|
|
return this.itemsView.getSortField();
|
|
}
|
|
|
|
|
|
function getSortDirection() {
|
|
if (!this.itemsView) {
|
|
return false;
|
|
}
|
|
|
|
return this.itemsView.getSortDirection();
|
|
}
|
|
|
|
|
|
function buildCollectionContextMenu()
|
|
{
|
|
var menu = document.getElementById('zotero-collectionmenu');
|
|
|
|
var m = {
|
|
newCollection: 0,
|
|
newSavedSearch: 1,
|
|
newSubcollection: 2,
|
|
sep1: 3,
|
|
editSelectedCollection: 4,
|
|
removeCollection: 5,
|
|
sep2: 6,
|
|
exportCollection: 7,
|
|
createBibCollection: 8,
|
|
exportFile: 9,
|
|
loadReport: 10
|
|
};
|
|
|
|
// Collection
|
|
if (this.collectionsView.selection.count == 1 &&
|
|
this.collectionsView._getItemAtRow(this.collectionsView.selection.currentIndex).isCollection())
|
|
{
|
|
var hide = [m.newCollection, m.newSavedSearch, m.exportFile];
|
|
var show = [m.newSubcollection, m.sep1, m.editSelectedCollection, m.removeCollection,
|
|
m.sep2, m.exportCollection, m.createBibCollection, m.loadReport];
|
|
if (this.itemsView.rowCount>0) {
|
|
var enable = [m.exportCollection, m.createBibCollection, m.loadReport];
|
|
}
|
|
else
|
|
{
|
|
var disable = [m.exportCollection, m.createBibCollection, m.loadReport];
|
|
}
|
|
|
|
menu.childNodes[m.editSelectedCollection].setAttribute('label', Zotero.getString('pane.collections.menu.rename.collection'));
|
|
menu.childNodes[m.removeCollection].setAttribute('label', Zotero.getString('pane.collections.menu.remove.collection'));
|
|
menu.childNodes[m.exportCollection].setAttribute('label', Zotero.getString('pane.collections.menu.export.collection'));
|
|
menu.childNodes[m.createBibCollection].setAttribute('label', Zotero.getString('pane.collections.menu.createBib.collection'));
|
|
menu.childNodes[m.loadReport].setAttribute('label', Zotero.getString('pane.collections.menu.generateReport.collection'));
|
|
}
|
|
// Saved Search
|
|
else if (this.collectionsView.selection.count == 1 &&
|
|
this.collectionsView._getItemAtRow(this.collectionsView.selection.currentIndex).isSearch()) {
|
|
var hide = [m.newCollection, m.newSavedSearch, m.newSubcollection, m.sep1, m.exportFile]
|
|
var show = [m.editSelectedCollection, m.removeCollection, m.sep2, m.exportCollection,
|
|
m.createBibCollection, m.loadReport];
|
|
|
|
if (this.itemsView.rowCount>0) {
|
|
var enable = [m.exportCollection, m.createBibCollection, m.loadReport];
|
|
}
|
|
else
|
|
{
|
|
var disable = [m.exportCollection, m.createBibCollection, m.loadReport];
|
|
}
|
|
|
|
menu.childNodes[m.editSelectedCollection].setAttribute('label', Zotero.getString('pane.collections.menu.edit.savedSearch'));
|
|
menu.childNodes[m.removeCollection].setAttribute('label', Zotero.getString('pane.collections.menu.remove.savedSearch'));
|
|
menu.childNodes[m.exportCollection].setAttribute('label', Zotero.getString('pane.collections.menu.export.savedSearch'));
|
|
menu.childNodes[m.createBibCollection].setAttribute('label', Zotero.getString('pane.collections.menu.createBib.savedSearch'));
|
|
menu.childNodes[m.loadReport].setAttribute('label', Zotero.getString('pane.collections.menu.generateReport.savedSearch'));
|
|
}
|
|
// Library
|
|
else
|
|
{
|
|
var hide = [m.newSubcollection, m.editSelectedCollection, m.removeCollection, m.sep2,
|
|
m.exportCollection, m.createBibCollection, m.loadReport];
|
|
var show = [m.newCollection, m.newSavedSearch, m.sep1, m.exportFile];
|
|
}
|
|
|
|
for (var i in disable)
|
|
{
|
|
menu.childNodes[disable[i]].setAttribute('disabled', true);
|
|
}
|
|
|
|
for (var i in enable)
|
|
{
|
|
menu.childNodes[enable[i]].setAttribute('disabled', false);
|
|
}
|
|
|
|
for (var i in hide)
|
|
{
|
|
menu.childNodes[hide[i]].setAttribute('hidden', true);
|
|
}
|
|
|
|
for (var i in show)
|
|
{
|
|
menu.childNodes[show[i]].setAttribute('hidden', false);
|
|
}
|
|
}
|
|
|
|
function buildItemContextMenu()
|
|
{
|
|
var m = {
|
|
showInLibrary: 0,
|
|
sep1: 1,
|
|
addNote: 2,
|
|
attachSnapshot: 3,
|
|
attachLink: 4,
|
|
sep2: 5,
|
|
duplicateItem: 6,
|
|
deleteItem: 7,
|
|
deleteFromLibrary: 8,
|
|
sep3: 9,
|
|
exportItems: 10,
|
|
createBib: 11,
|
|
loadReport: 12
|
|
};
|
|
|
|
var menu = document.getElementById('zotero-itemmenu');
|
|
|
|
var enable = [], disable = [], show = [], hide = [], multiple = '';
|
|
|
|
if (this.itemsView && this.itemsView.selection.count > 0) {
|
|
enable.push(m.showInLibrary, m.addNote, m.attachSnapshot, m.attachLink,
|
|
m.sep2, m.duplicateItem, m.deleteItem, m.deleteFromLibrary,
|
|
m.exportItems, m.createBib, m.loadReport);
|
|
|
|
// Multiple items selected
|
|
if (this.itemsView.selection.count > 1) {
|
|
var multiple = '.multiple';
|
|
hide.push(m.showInLibrary, m.sep1, m.addNote, m.attachSnapshot,
|
|
m.attachLink, m.sep2, m.duplicateItem);
|
|
}
|
|
// Single item selected
|
|
else
|
|
{
|
|
var item = this.itemsView._getItemAtRow(this.itemsView.selection.currentIndex).ref;
|
|
var itemID = item.getID();
|
|
menu.setAttribute('itemID', itemID);
|
|
|
|
// Show in Library
|
|
if (!this.itemsView._itemGroup.isLibrary()) {
|
|
show.push(m.showInLibrary, m.sep1);
|
|
}
|
|
else {
|
|
hide.push(m.showInLibrary, m.sep1);
|
|
}
|
|
|
|
if (item.isRegularItem())
|
|
{
|
|
show.push(m.addNote, m.attachSnapshot, m.attachLink, m.sep2);
|
|
}
|
|
else
|
|
{
|
|
hide.push(m.addNote, m.attachSnapshot, m.attachLink, m.sep2);
|
|
}
|
|
|
|
if (item.isAttachment()) {
|
|
hide.push(m.duplicateItem);
|
|
}
|
|
else {
|
|
show.push(m.duplicateItem);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Show in Library
|
|
if (!this.itemsView._itemGroup.isLibrary()) {
|
|
show.push(m.showInLibrary, m.sep1);
|
|
}
|
|
else {
|
|
hide.push(m.showInLibrary, m.sep1);
|
|
}
|
|
|
|
disable.push(m.showInLibrary, m.duplicateItem, m.deleteItem,
|
|
m.deleteFromLibrary, m.exportItems, m.createBib, m.loadReport);
|
|
hide.push(m.addNote, m.attachSnapshot, m.attachLink, m.sep2);
|
|
}
|
|
|
|
// Remove from collection
|
|
if (this.itemsView._itemGroup.isCollection() && !(item && item.getSource()))
|
|
{
|
|
menu.childNodes[m.deleteItem].setAttribute('label', Zotero.getString('pane.items.menu.remove' + multiple));
|
|
show.push(m.deleteItem);
|
|
}
|
|
else
|
|
{
|
|
hide.push(m.deleteItem);
|
|
}
|
|
|
|
// Plural if necessary
|
|
menu.childNodes[m.deleteFromLibrary].setAttribute('label', Zotero.getString('pane.items.menu.erase' + multiple));
|
|
menu.childNodes[m.exportItems].setAttribute('label', Zotero.getString('pane.items.menu.export' + multiple));
|
|
menu.childNodes[m.createBib].setAttribute('label', Zotero.getString('pane.items.menu.createBib' + multiple));
|
|
menu.childNodes[m.loadReport].setAttribute('label', Zotero.getString('pane.items.menu.generateReport' + multiple));
|
|
|
|
for (var i in disable)
|
|
{
|
|
menu.childNodes[disable[i]].setAttribute('disabled', true);
|
|
}
|
|
|
|
for (var i in enable)
|
|
{
|
|
menu.childNodes[enable[i]].setAttribute('disabled', false);
|
|
}
|
|
|
|
for (var i in hide)
|
|
{
|
|
menu.childNodes[hide[i]].setAttribute('hidden', true);
|
|
}
|
|
|
|
for (var i in show)
|
|
{
|
|
menu.childNodes[show[i]].setAttribute('hidden', false);
|
|
}
|
|
}
|
|
|
|
|
|
// Adapted from: http://www.xulplanet.com/references/elemref/ref_tree.html#cmnote-9
|
|
function onDoubleClick(event, tree)
|
|
{
|
|
if (event && tree && event.type == "dblclick") {
|
|
var row = {}, col = {}, obj = {};
|
|
tree.treeBoxObject.getCellAt(event.clientX, event.clientY, row, col, obj);
|
|
|
|
// obj.value == 'cell'/'text'/'image'
|
|
if (!obj.value) {
|
|
return;
|
|
}
|
|
|
|
if (tree.id == 'zotero-collections-tree') {
|
|
var s = this.getSelectedSavedSearch();
|
|
if (s) {
|
|
this.editSelectedCollection();
|
|
}
|
|
}
|
|
else if (tree.id == 'zotero-items-tree') {
|
|
if (this.itemsView && this.itemsView.selection.currentIndex > -1) {
|
|
var item = this.getSelectedItems()[0];
|
|
if (item && item.isNote()) {
|
|
document.getElementById('zotero-view-note-button').doCommand();
|
|
}
|
|
else if (item && item.isAttachment()) {
|
|
this.viewSelectedAttachment(event);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Loads a URL following the standard modifier key behavior
|
|
* (e.g. meta-click == new background tab, meta-shift-click == new front tab,
|
|
* shift-click == new window, no modifier == frontmost tab
|
|
*/
|
|
function loadURI(uri, event, data) {
|
|
// Open in new tab
|
|
if (event.metaKey) {
|
|
var tab = gBrowser.addTab(uri);
|
|
var browser = gBrowser.getBrowserForTab(tab);
|
|
|
|
if (data && data.attachmentID) {
|
|
Zotero_Browser.annotatePage(data.attachmentID, browser);
|
|
// In case the page has already loaded, update
|
|
Zotero_Browser.updateStatus();
|
|
}
|
|
|
|
if (event.shiftKey) {
|
|
gBrowser.selectedTab = tab;
|
|
}
|
|
}
|
|
else if (event.shiftKey) {
|
|
window.open(uri, "zotero-loaded-page",
|
|
"menubar=yes,location=yes,toolbar=yes,personalbar=yes,resizable=yes,scrollbars=yes,status=yes");
|
|
|
|
if (data && data.attachmentID) {
|
|
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
|
.getService(Components.interfaces.nsIWindowMediator);
|
|
var newWindow = wm.getMostRecentWindow("navigator:browser");
|
|
//var browser = newWindow.getBrowser();
|
|
|
|
newWindow.Zotero_Browser.annotatePage(data.attachmentID);
|
|
// In case the page has already loaded, update
|
|
newWindow.Zotero_Browser.updateStatus();
|
|
}
|
|
}
|
|
else {
|
|
if (data && data.attachmentID) {
|
|
// Enable annotation
|
|
Zotero_Browser.annotatePage(data.attachmentID);
|
|
}
|
|
window.loadURI(uri);
|
|
}
|
|
}
|
|
|
|
|
|
function setItemsPaneMessage(msg) {
|
|
document.getElementById('zotero-items-pane-content').selectedIndex = 1;
|
|
var elem = document.getElementById('zotero-items-pane-message');
|
|
elem.value = msg;
|
|
}
|
|
|
|
|
|
function clearItemsPaneMessage() {
|
|
document.getElementById('zotero-items-pane-content').selectedIndex = 0;
|
|
document.getElementById('zotero-items-pane-message').value = '';
|
|
}
|
|
|
|
|
|
// Updates browser context menu options
|
|
function contextPopupShowing()
|
|
{
|
|
var menuitem = document.getElementById("zotero-context-add-to-current-note");
|
|
var showing = false;
|
|
if (menuitem){
|
|
var items = ZoteroPane.getSelectedItems();
|
|
if (ZoteroPane.itemsView.selection.count==1 && items[0] && items[0].isNote()
|
|
&& window.gContextMenu.isTextSelected)
|
|
{
|
|
menuitem.hidden = false;
|
|
showing = true;
|
|
}
|
|
else
|
|
{
|
|
menuitem.hidden = true;
|
|
}
|
|
}
|
|
|
|
var menuitem = document.getElementById("zotero-context-add-to-new-note");
|
|
if (menuitem){
|
|
if (window.gContextMenu.isTextSelected)
|
|
{
|
|
menuitem.hidden = false;
|
|
showing = true;
|
|
}
|
|
else
|
|
{
|
|
menuitem.hidden = true;
|
|
}
|
|
}
|
|
|
|
var menuitem = document.getElementById("zotero-context-save-link-as-snapshot");
|
|
if (menuitem) {
|
|
if (window.gContextMenu.onLink) {
|
|
menuitem.hidden = false;
|
|
showing = true;
|
|
}
|
|
else {
|
|
menuitem.hidden = true;
|
|
}
|
|
}
|
|
|
|
var menuitem = document.getElementById("zotero-context-save-image-as-snapshot");
|
|
if (menuitem) {
|
|
// Not using window.gContextMenu.hasBGImage -- if the user wants it,
|
|
// they can use the Firefox option to view and then import from there
|
|
if (window.gContextMenu.onImage) {
|
|
menuitem.hidden = false;
|
|
showing = true;
|
|
}
|
|
else {
|
|
menuitem.hidden = true;
|
|
}
|
|
}
|
|
|
|
var separator = document.getElementById("zotero-context-separator");
|
|
separator.hidden = !showing;
|
|
}
|
|
|
|
|
|
function newNote(popup, parent, text) {
|
|
if (!popup) {
|
|
try {
|
|
// trim
|
|
text = text.replace(/^[\xA0\r\n\s]*(.*)[\xA0\r\n\s]*$/m, "$1");
|
|
}
|
|
catch (e){}
|
|
|
|
var itemID = Zotero.Notes.add(text, parent);
|
|
|
|
if (this.itemsView && this.itemsView._itemGroup.isCollection()) {
|
|
this.itemsView._itemGroup.ref.addItem(itemID);
|
|
}
|
|
|
|
this.selectItem(itemID);
|
|
|
|
document.getElementById('zotero-note-editor').focus();
|
|
}
|
|
else
|
|
{
|
|
// TODO: _text_
|
|
var c = this.getSelectedCollection();
|
|
if (c) {
|
|
this.openNoteWindow(null, c.getID());
|
|
}
|
|
else {
|
|
this.openNoteWindow();
|
|
}
|
|
}
|
|
}
|
|
|
|
function addTextToNote(text)
|
|
{
|
|
try {
|
|
// trim
|
|
text = text.replace(/^[\xA0\r\n\s]*(.*)[\xA0\r\n\s]*$/m, "$1");
|
|
}
|
|
catch (e){}
|
|
|
|
if (!text || !text.length)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var items = this.getSelectedItems();
|
|
if (this.itemsView.selection.count == 1 && items[0] && items[0].isNote()) {
|
|
var note = items[0].getNote()
|
|
items[0].updateNote(note == '' ? text : note + "\n\n" + text);
|
|
var noteElem = document.getElementById('zotero-note-editor')
|
|
noteElem.focus();
|
|
noteElem.id('noteField').inputField.editor.
|
|
selectionController.scrollSelectionIntoView(1,
|
|
1,
|
|
true);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function openNoteWindow(id, parent)
|
|
{
|
|
if (id) {
|
|
var item = Zotero.Items.get(id)
|
|
}
|
|
window.open('chrome://zotero/content/note.xul?v=1'
|
|
+ (id ? '&id=' + id : '') + (parent ? '&coll=' + parent : ''),
|
|
'', 'chrome,resizable,centerscreen');
|
|
}
|
|
|
|
|
|
function addAttachmentFromDialog(link, id)
|
|
{
|
|
var nsIFilePicker = Components.interfaces.nsIFilePicker;
|
|
var fp = Components.classes["@mozilla.org/filepicker;1"]
|
|
.createInstance(nsIFilePicker);
|
|
fp.init(window, Zotero.getString('pane.item.attachments.select'), nsIFilePicker.modeOpenMultiple);
|
|
fp.appendFilters(Components.interfaces.nsIFilePicker.filterAll);
|
|
|
|
if(fp.show() == nsIFilePicker.returnOK)
|
|
{
|
|
var files = fp.files;
|
|
while (files.hasMoreElements()){
|
|
var file = files.getNext();
|
|
file.QueryInterface(Components.interfaces.nsILocalFile);
|
|
var attachmentID;
|
|
if(link)
|
|
attachmentID = Zotero.Attachments.linkFromFile(file, id);
|
|
else
|
|
attachmentID = Zotero.Attachments.importFromFile(file, id);
|
|
|
|
if(attachmentID && !id)
|
|
{
|
|
var c = this.getSelectedCollection();
|
|
if(c)
|
|
c.addItem(attachmentID);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
function addItemFromPage() {
|
|
var progressWin = new Zotero.ProgressWindow();
|
|
progressWin.changeHeadline(Zotero.getString('ingester.scraping'));
|
|
var icon = 'chrome://zotero/skin/treeitem-webpage.png';
|
|
progressWin.addLines(window.content.document.title, icon)
|
|
progressWin.show();
|
|
progressWin.startCloseTimer();
|
|
|
|
var data = {
|
|
title: window.content.document.title,
|
|
url: window.content.document.location.href,
|
|
accessDate: "CURRENT_TIMESTAMP"
|
|
}
|
|
|
|
var item = this.newItem(Zotero.ItemTypes.getID('webpage'), data);
|
|
|
|
// Automatically save snapshot if pref set
|
|
if (item.getID() && Zotero.Prefs.get('automaticSnapshots'))
|
|
{
|
|
var f = function() {
|
|
// We set |noParent|, since child items don't belong to collections
|
|
ZoteroPane.addAttachmentFromPage(false, item.getID(), true);
|
|
}
|
|
// Give progress window time to appear
|
|
setTimeout(f, 300);
|
|
}
|
|
|
|
return item.getID();
|
|
}
|
|
|
|
|
|
/*
|
|
* Create an attachment from the current page
|
|
*
|
|
* |link| -- create web link instead of snapshot
|
|
* |itemID| -- itemID of parent item
|
|
* |noParent| -- don't add to current collection
|
|
*/
|
|
function addAttachmentFromPage(link, itemID, noParent)
|
|
{
|
|
if (!noParent) {
|
|
var progressWin = new Zotero.ProgressWindow();
|
|
progressWin.changeHeadline(Zotero.getString('save.' + (link ? 'link' : 'attachment')));
|
|
var type = link ? 'web-link' : 'snapshot';
|
|
var icon = 'chrome://zotero/skin/treeitem-attachment-' + type + '.png';
|
|
progressWin.addLines(window.content.document.title, icon)
|
|
progressWin.show();
|
|
progressWin.startCloseTimer();
|
|
|
|
if (this.itemsView && this.itemsView._itemGroup.isCollection()) {
|
|
var parentCollectionID = this.itemsView._itemGroup.ref.getID();
|
|
}
|
|
}
|
|
|
|
var f = function() {
|
|
if (link) {
|
|
Zotero.Attachments.linkFromDocument(window.content.document, itemID, parentCollectionID);
|
|
}
|
|
else {
|
|
Zotero.Attachments.importFromDocument(window.content.document, itemID, false, parentCollectionID);
|
|
}
|
|
}
|
|
// Give progress window time to appear
|
|
setTimeout(f, 100);
|
|
}
|
|
|
|
|
|
function viewAttachment(itemID, event) {
|
|
var attachment = Zotero.Items.get(itemID);
|
|
if (!attachment.isAttachment()) {
|
|
throw ("Item " + itemID + " is not an attachment in ZoteroPane.viewAttachment()");
|
|
}
|
|
|
|
if (attachment.getAttachmentLinkMode() == Zotero.Attachments.LINK_MODE_LINKED_URL) {
|
|
this.loadURI(attachment.getField('url'), event);
|
|
return;
|
|
}
|
|
|
|
var file = attachment.getFile();
|
|
if (file) {
|
|
var mimeType = attachment.getAttachmentMimeType();
|
|
if (mimeType) {
|
|
var ext = Zotero.File.getExtension(file);
|
|
var internal = Zotero.MIME.hasInternalHandler(mimeType, ext);
|
|
}
|
|
|
|
var fileURL = attachment.getLocalFileURL();
|
|
|
|
if (internal || Zotero.MIME.fileHasInternalHandler(file)) {
|
|
this.loadURI(fileURL, event, { attachmentID: itemID});
|
|
}
|
|
else {
|
|
// Some platforms don't have nsILocalFile.launch, so we just load it and
|
|
// let the Firefox external helper app window handle it
|
|
try {
|
|
file.launch();
|
|
}
|
|
catch (e) {
|
|
window.loadURI(fileURL, event);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
this.showAttachmentNotFoundDialog(itemID);
|
|
}
|
|
}
|
|
|
|
|
|
function viewSelectedAttachment(event)
|
|
{
|
|
if (this.itemsView && this.itemsView.selection.count == 1) {
|
|
this.viewAttachment(this.getSelectedItems(true)[0], event);
|
|
}
|
|
}
|
|
|
|
|
|
function showSelectedAttachmentInFilesystem()
|
|
{
|
|
if (this.itemsView && this.itemsView.selection.count == 1) {
|
|
var attachment = this.getSelectedItems()[0];
|
|
|
|
if (attachment.getAttachmentLinkMode() != Zotero.Attachments.LINK_MODE_LINKED_URL)
|
|
{
|
|
var file = attachment.getFile();
|
|
if (file){
|
|
try {
|
|
file.reveal();
|
|
}
|
|
catch (e) {
|
|
// On platforms that don't support nsILocalFile.reveal() (e.g. Linux), we
|
|
// open a small window with a selected read-only textbox containing the
|
|
// file path, so the user can open it, Control-c, Control-w, Alt-Tab, and
|
|
// Control-v the path into another app
|
|
var io = {alertText: file.path};
|
|
window.openDialog('chrome://zotero/content/selectableAlert.xul', "zotero-reveal-window", "chrome", io);
|
|
}
|
|
}
|
|
else {
|
|
this.showAttachmentNotFoundDialog(attachment.getID())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
function showAttachmentNotFoundDialog(itemID) {
|
|
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].
|
|
createInstance(Components.interfaces.nsIPromptService);
|
|
var buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_OK)
|
|
+ (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_IS_STRING);
|
|
var index = ps.confirmEx(null,
|
|
Zotero.getString('pane.item.attachments.fileNotFound.title'),
|
|
Zotero.getString('pane.item.attachments.fileNotFound.text'),
|
|
buttonFlags, null, Zotero.getString('general.locate'),
|
|
null, null, {});
|
|
|
|
if (index == 1) {
|
|
this.relinkAttachment(itemID);
|
|
}
|
|
}
|
|
|
|
|
|
function relinkAttachment(itemID) {
|
|
var item = Zotero.Items.get(itemID);
|
|
if (!item) {
|
|
throw('Item ' + itemID + ' not found in ZoteroPane.relinkAttachment()');
|
|
}
|
|
|
|
var nsIFilePicker = Components.interfaces.nsIFilePicker;
|
|
var fp = Components.classes["@mozilla.org/filepicker;1"]
|
|
.createInstance(nsIFilePicker);
|
|
fp.init(window, Zotero.getString('pane.item.attachments.select'), nsIFilePicker.modeOpen);
|
|
|
|
|
|
var file = item.getFile(false, true);
|
|
var dir = Zotero.File.getClosestDirectory(file);
|
|
if (dir) {
|
|
dir.QueryInterface(Components.interfaces.nsILocalFile);
|
|
fp.displayDirectory = dir;
|
|
}
|
|
|
|
fp.appendFilters(Components.interfaces.nsIFilePicker.filterAll);
|
|
|
|
if (fp.show() == nsIFilePicker.returnOK) {
|
|
var file = fp.file;
|
|
file.QueryInterface(Components.interfaces.nsILocalFile);
|
|
item.relinkAttachmentFile(file);
|
|
}
|
|
}
|
|
}
|
|
|
|
window.addEventListener("load", function(e) { ZoteroPane.onLoad(e); }, false);
|
|
window.addEventListener("unload", function(e) { ZoteroPane.onUnload(e); }, false);
|