2011-01-30 09:44:01 +00:00
|
|
|
/*
|
|
|
|
***** BEGIN LICENSE BLOCK *****
|
|
|
|
|
|
|
|
Copyright © 2009 Center for History and New Media
|
|
|
|
George Mason University, Fairfax, Virginia, USA
|
|
|
|
http://zotero.org
|
|
|
|
|
|
|
|
This file is part of Zotero.
|
|
|
|
|
|
|
|
Zotero is free software: you can redistribute it and/or modify
|
2011-05-18 18:34:22 +00:00
|
|
|
it under the terms of the GNU Affero General Public License as published by
|
2011-01-30 09:44:01 +00:00
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
Zotero is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2011-05-18 18:34:22 +00:00
|
|
|
GNU Affero General Public License for more details.
|
2011-01-30 09:44:01 +00:00
|
|
|
|
2011-05-18 18:34:22 +00:00
|
|
|
You should have received a copy of the GNU Affero General Public License
|
2011-01-30 09:44:01 +00:00
|
|
|
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
***** END LICENSE BLOCK *****
|
|
|
|
*/
|
|
|
|
|
2011-05-31 05:32:45 +00:00
|
|
|
Components.utils.import("resource://gre/modules/Services.jsm");
|
|
|
|
|
|
|
|
/**
|
2011-01-30 09:44:01 +00:00
|
|
|
* This object contains the various functions for the interface
|
|
|
|
*/
|
2011-08-25 07:35:22 +00:00
|
|
|
const ZoteroStandalone = new function() {
|
2019-08-12 20:18:46 +00:00
|
|
|
const FONT_SIZES = ["1.0", "1.15", "1.3", "1.5", "1.7", "1.9", "2.1"];
|
|
|
|
//const NOTE_FONT_SIZES = ["11", "12", "13", "14", "18", "24", "36", "48", "64", "72", "96"];
|
|
|
|
const NOTE_FONT_SIZE_DEFAULT = "12";
|
|
|
|
|
2011-07-02 03:09:13 +00:00
|
|
|
/**
|
|
|
|
* Run when standalone window first opens
|
|
|
|
*/
|
2011-01-30 09:44:01 +00:00
|
|
|
this.onLoad = function() {
|
2017-07-13 22:27:06 +00:00
|
|
|
// Fix window without menubar/titlebar when Zotero is closed in full-screen mode in OS X 10.11+
|
|
|
|
if (Zotero.isMac && window.document.documentElement.getAttribute('sizemode') == 'fullscreen') {
|
|
|
|
window.document.documentElement.setAttribute('sizemode', 'normal');
|
|
|
|
}
|
2020-10-22 10:12:31 +00:00
|
|
|
|
2021-02-11 10:57:35 +00:00
|
|
|
if (Zotero.isMac && Zotero.isPDFBuild) {
|
2020-10-22 10:12:31 +00:00
|
|
|
document.documentElement.setAttribute('drawintitlebar', true);
|
|
|
|
document.documentElement.setAttribute('tabsintitlebar', true);
|
|
|
|
document.documentElement.setAttribute('chromemargin', '0,-1,-1,-1');
|
|
|
|
}
|
2020-10-26 12:09:56 +00:00
|
|
|
|
|
|
|
this.switchMenuType('library');
|
|
|
|
Zotero.Notifier.registerObserver(
|
|
|
|
{
|
|
|
|
notify: async (action, type, ids, extraData) => {
|
|
|
|
if (action == 'select') {
|
|
|
|
// "library" or "reader"
|
2020-11-10 08:59:34 +00:00
|
|
|
this.switchMenuType(extraData[ids[0]].type);
|
|
|
|
setTimeout(() => ZoteroPane.updateToolbarPosition(), 0);
|
2020-10-26 12:09:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
['tab'],
|
|
|
|
'tab'
|
|
|
|
);
|
2017-07-13 22:27:06 +00:00
|
|
|
|
Async DB megacommit
Promise-based rewrite of most of the codebase, with asynchronous database and file access -- see https://github.com/zotero/zotero/issues/518 for details.
WARNING: This includes backwards-incompatible schema changes.
An incomplete list of other changes:
- Schema overhaul
- Replace main tables with new versions with updated schema
- Enable real foreign key support and remove previous triggers
- Don't use NULLs for local libraryID, which broke the UNIQUE index
preventing object key duplication. All code (Zotero and third-party)
using NULL for the local library will need to be updated to use 0
instead (already done for Zotero code)
- Add 'compatibility' DB version that can be incremented manually to break DB
compatibility with previous versions. 'userdata' upgrades will no longer
automatically break compatibility.
- Demote creators and tags from first-class objects to item properties
- New API syncing properties
- 'synced'/'version' properties to data objects
- 'etag' to groups
- 'version' to libraries
- Create Zotero.DataObject that other objects inherit from
- Consolidate data object loading into Zotero.DataObjects
- Change object reloading so that only the loaded and changed parts of objects are reloaded, instead of reloading all data from the database (with some exceptions, including item primary data)
- Items and collections now have .parentItem and .parentKey properties, replacing item.getSource() and item.getSourceKey()
- New function Zotero.serial(fn), to wrap an async function such that all calls are run serially
- New function Zotero.Utilities.Internal.forEachChunkAsync(arr, chunkSize, func)
- Add tag selector loading message
- Various API and name changes, since everything was breaking anyway
Known broken things:
- Syncing (will be completely rewritten for API syncing)
- Translation architecture (needs promise-based rewrite)
- Duplicates view
- DB integrity check (from schema changes)
- Dragging (may be difficult to fix)
Lots of other big and little things are certainly broken, particularly with the UI, which can be affected by async code in all sorts of subtle ways.
2014-08-06 21:38:05 +00:00
|
|
|
Zotero.Promise.try(function () {
|
2013-08-12 00:51:16 +00:00
|
|
|
if(!Zotero) {
|
|
|
|
throw true;
|
|
|
|
}
|
2016-02-07 06:51:07 +00:00
|
|
|
if(Zotero.initializationPromise.isPending()) {
|
2013-08-12 00:51:16 +00:00
|
|
|
Zotero.showZoteroPaneProgressMeter();
|
|
|
|
}
|
|
|
|
return Zotero.initializationPromise;
|
|
|
|
})
|
2018-12-12 10:34:39 +00:00
|
|
|
.then(async function () {
|
2017-07-27 06:29:50 +00:00
|
|
|
document.getElementById('key_copyCitation')
|
|
|
|
.setAttribute('key', Zotero.Keys.getKeyForCommand('copySelectedItemCitationsToClipboard'));
|
|
|
|
document.getElementById('key_copyBibliography')
|
|
|
|
.setAttribute('key', Zotero.Keys.getKeyForCommand('copySelectedItemsToClipboard'));
|
|
|
|
|
2017-07-25 06:36:33 +00:00
|
|
|
ZoteroStandalone.DebugOutput.init();
|
|
|
|
|
2013-08-12 00:51:16 +00:00
|
|
|
Zotero.hideZoteroPaneOverlays();
|
|
|
|
ZoteroPane.init();
|
|
|
|
ZoteroPane.makeVisible();
|
|
|
|
|
|
|
|
// Don't ask before handing http and https URIs
|
|
|
|
var eps = Components.classes['@mozilla.org/uriloader/external-protocol-service;1']
|
|
|
|
.getService(Components.interfaces.nsIExternalProtocolService);
|
|
|
|
var hs = Components.classes["@mozilla.org/uriloader/handler-service;1"]
|
|
|
|
.getService(Components.interfaces.nsIHandlerService);
|
2016-05-03 21:51:12 +00:00
|
|
|
for (let scheme of ["http", "https"]) {
|
2013-08-12 00:51:16 +00:00
|
|
|
var handlerInfo = eps.getProtocolHandlerInfo(scheme);
|
|
|
|
handlerInfo.preferredAction = Components.interfaces.nsIHandlerInfo.useSystemDefault;
|
|
|
|
handlerInfo.alwaysAskBeforeHandling = false;
|
|
|
|
hs.store(handlerInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add add-on listeners (not yet hooked up)
|
|
|
|
Services.obs.addObserver(gXPInstallObserver, "addon-install-disabled", false);
|
|
|
|
Services.obs.addObserver(gXPInstallObserver, "addon-install-started", false);
|
|
|
|
Services.obs.addObserver(gXPInstallObserver, "addon-install-blocked", false);
|
|
|
|
Services.obs.addObserver(gXPInstallObserver, "addon-install-failed", false);
|
|
|
|
Services.obs.addObserver(gXPInstallObserver, "addon-install-complete", false);
|
|
|
|
})
|
|
|
|
.catch(function (e) {
|
2016-02-08 05:57:09 +00:00
|
|
|
try { Zotero.debug(e, 1); } catch (e) {}
|
|
|
|
Components.utils.reportError(e);
|
2011-02-10 01:53:15 +00:00
|
|
|
ZoteroPane.displayStartupError();
|
|
|
|
window.close();
|
2011-02-10 01:58:47 +00:00
|
|
|
return;
|
2013-08-12 00:51:16 +00:00
|
|
|
});
|
2011-01-30 09:44:01 +00:00
|
|
|
}
|
2020-10-26 12:09:56 +00:00
|
|
|
|
|
|
|
this.switchMenuType = function (type) {
|
|
|
|
document.querySelectorAll('.menu-type-library, .menu-type-reader').forEach(el => el.collapsed = true);
|
|
|
|
document.querySelectorAll('.menu-type-' + type).forEach(el => el.collapsed = false);
|
|
|
|
};
|
|
|
|
|
|
|
|
this.onReaderCmd = function (cmd) {
|
|
|
|
let reader = Zotero.Reader.getByTabID(Zotero_Tabs.selectedID);
|
|
|
|
reader.menuCmd(cmd);
|
|
|
|
};
|
2019-08-18 20:22:39 +00:00
|
|
|
|
|
|
|
this.onFileMenuOpen = function () {
|
|
|
|
var active = false;
|
|
|
|
try {
|
|
|
|
let zp = Zotero.getActiveZoteroPane();
|
|
|
|
if (zp) {
|
|
|
|
active = !!zp.getSelectedItems().filter((item) => {
|
|
|
|
return item.isAttachment()
|
|
|
|
|| (item.isRegularItem() && item.getAttachments().length);
|
|
|
|
}).length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (e) {}
|
|
|
|
this.updateMenuItemEnabled('manage-attachments-menu', active);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2011-07-02 03:09:13 +00:00
|
|
|
/**
|
|
|
|
* Builds new item menu
|
|
|
|
*/
|
|
|
|
this.buildNewItemMenu = function() {
|
|
|
|
var addMenu = document.getElementById('menu_NewItemPopup');
|
|
|
|
|
|
|
|
// Remove all nodes so we can regenerate
|
|
|
|
while(addMenu.hasChildNodes()) addMenu.removeChild(addMenu.firstChild);
|
|
|
|
|
|
|
|
var typeSets = [Zotero.ItemTypes.getPrimaryTypes(), Zotero.ItemTypes.getSecondaryTypes()];
|
2011-08-25 21:29:35 +00:00
|
|
|
for(var j=0; j<typeSets.length; j++) {
|
|
|
|
var t = typeSets[j];
|
2011-07-02 03:09:13 +00:00
|
|
|
|
|
|
|
// Sort by localized name
|
|
|
|
var itemTypes = [];
|
|
|
|
for (var i=0; i<t.length; i++) {
|
|
|
|
itemTypes.push({
|
|
|
|
id: t[i].id,
|
|
|
|
name: t[i].name,
|
|
|
|
localized: Zotero.ItemTypes.getLocalizedString(t[i].id)
|
|
|
|
});
|
|
|
|
}
|
|
|
|
var collation = Zotero.getLocaleCollation();
|
|
|
|
itemTypes.sort(function(a, b) {
|
|
|
|
return collation.compareString(1, a.localized, b.localized);
|
|
|
|
});
|
|
|
|
|
|
|
|
for (var i = 0; i<itemTypes.length; i++) {
|
|
|
|
var menuitem = document.createElement("menuitem");
|
|
|
|
menuitem.setAttribute("label", itemTypes[i].localized);
|
|
|
|
menuitem.setAttribute("tooltiptext", "");
|
2012-02-06 07:38:53 +00:00
|
|
|
let type = itemTypes[i].id;
|
2016-12-29 12:01:52 +00:00
|
|
|
menuitem.addEventListener("command", function() {
|
|
|
|
ZoteroPane_Local.newItem(type, null, null, true);
|
|
|
|
}, false);
|
2011-07-02 03:09:13 +00:00
|
|
|
menuitem.className = "zotero-tb-add";
|
|
|
|
addMenu.appendChild(menuitem);
|
|
|
|
}
|
|
|
|
|
|
|
|
// add separator between sets
|
2011-08-25 21:29:35 +00:00
|
|
|
if(j !== typeSets.length-1) {
|
2011-07-02 03:09:13 +00:00
|
|
|
addMenu.appendChild(document.createElement("menuseparator"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-27 06:29:50 +00:00
|
|
|
|
2019-08-18 20:22:39 +00:00
|
|
|
this.onManageAttachmentsMenuOpen = function () {
|
|
|
|
// Convert Linked Files to Stored Files
|
|
|
|
var active = false;
|
|
|
|
try {
|
|
|
|
let zp = Zotero.getActiveZoteroPane();
|
|
|
|
if (zp) {
|
|
|
|
active = !!zp.getSelectedItems().filter((item) => {
|
|
|
|
return item.isLinkedFileAttachment()
|
|
|
|
|| (item.isRegularItem()
|
|
|
|
&& item.getAttachments()
|
|
|
|
.map(id => Zotero.Items.get(id))
|
|
|
|
.some(att => att.isLinkedFileAttachment()));
|
|
|
|
}).length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (e) {}
|
|
|
|
this.updateMenuItemEnabled('file-menuitem-convert-to-stored', active);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
this.onManageAttachmentsMenuItemClick = function (event) {
|
|
|
|
var menuitem = event.originalTarget;
|
|
|
|
var id = menuitem.id;
|
|
|
|
var prefix = 'file-menuitem-';
|
|
|
|
if (menuitem.disabled || !id.startsWith(prefix)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
id = id.substr(prefix.length);
|
|
|
|
|
|
|
|
switch (id) {
|
|
|
|
case 'convert-to-stored':
|
|
|
|
ZoteroPane.convertLinkedFilesToStoredFiles();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-07-27 06:29:50 +00:00
|
|
|
this.updateQuickCopyOptions = function () {
|
2018-03-06 09:38:45 +00:00
|
|
|
var selected = false;
|
|
|
|
try {
|
|
|
|
selected = Zotero.getActiveZoteroPane()
|
|
|
|
.getSelectedItems()
|
|
|
|
.filter(item => item.isRegularItem())
|
|
|
|
.length;
|
|
|
|
}
|
|
|
|
catch (e) {}
|
|
|
|
|
2017-07-27 06:29:50 +00:00
|
|
|
var format = Zotero.QuickCopy.getFormatFromURL(Zotero.QuickCopy.lastActiveURL);
|
|
|
|
format = Zotero.QuickCopy.unserializeSetting(format);
|
|
|
|
|
|
|
|
var copyCitation = document.getElementById('menu_copyCitation');
|
|
|
|
var copyBibliography = document.getElementById('menu_copyBibliography');
|
|
|
|
var copyExport = document.getElementById('menu_copyExport');
|
|
|
|
|
2018-03-06 09:38:45 +00:00
|
|
|
copyCitation.hidden = !selected || format.mode != 'bibliography';
|
|
|
|
copyBibliography.hidden = !selected || format.mode != 'bibliography';
|
|
|
|
copyExport.hidden = !selected || format.mode != 'export';
|
2017-07-27 06:29:50 +00:00
|
|
|
if (format.mode == 'export') {
|
|
|
|
try {
|
|
|
|
let obj = Zotero.Translators.get(format.id);
|
2018-08-12 23:02:05 +00:00
|
|
|
if (obj) {
|
|
|
|
copyExport.label = Zotero.getString('quickCopy.copyAs', obj.label);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
copyExport.hidden = true;
|
|
|
|
}
|
2017-07-27 06:29:50 +00:00
|
|
|
}
|
|
|
|
catch (e) {
|
2018-03-06 09:38:45 +00:00
|
|
|
if (!(e instanceof Zotero.Exception.UnloadedDataException && e.dataType == 'translators')) {
|
|
|
|
Zotero.logError(e);
|
|
|
|
}
|
2017-07-27 06:29:50 +00:00
|
|
|
copyExport.hidden = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2019-08-12 20:18:46 +00:00
|
|
|
this.onViewMenuOpen = function () {
|
|
|
|
// Layout mode
|
|
|
|
var mode = Zotero.Prefs.get('layout');
|
2019-08-18 20:22:39 +00:00
|
|
|
this.updateMenuItemCheckmark('view-menuitem-standard', mode != 'stacked');
|
|
|
|
this.updateMenuItemCheckmark('view-menuitem-stacked', mode == 'stacked');
|
2019-08-12 20:18:46 +00:00
|
|
|
|
|
|
|
// Panes
|
|
|
|
this.updateMenuItemCheckmark(
|
2019-08-18 20:22:39 +00:00
|
|
|
'view-menuitem-collections-pane',
|
2019-08-12 20:18:46 +00:00
|
|
|
document.getElementById('zotero-collections-pane').getAttribute('collapsed') != 'true'
|
|
|
|
);
|
|
|
|
this.updateMenuItemCheckmark(
|
2019-08-18 20:22:39 +00:00
|
|
|
'view-menuitem-item-pane',
|
2019-08-12 20:18:46 +00:00
|
|
|
document.getElementById('zotero-item-pane').getAttribute('collapsed') != 'true'
|
|
|
|
);
|
|
|
|
this.updateMenuItemCheckmark(
|
2019-08-18 20:22:39 +00:00
|
|
|
'view-menuitem-tag-selector',
|
2019-08-12 20:18:46 +00:00
|
|
|
document.getElementById('zotero-tag-selector-container').getAttribute('collapsed') != 'true'
|
|
|
|
);
|
|
|
|
|
|
|
|
// Font size
|
|
|
|
var fontSize = Zotero.Prefs.get('fontSize');
|
2019-08-18 20:22:39 +00:00
|
|
|
this.updateMenuItemEnabled('view-menuitem-font-size-bigger', fontSize < FONT_SIZES[FONT_SIZES.length - 1]);
|
|
|
|
this.updateMenuItemEnabled('view-menuitem-font-size-smaller', fontSize > FONT_SIZES[0]);
|
|
|
|
this.updateMenuItemEnabled('view-menuitem-font-size-reset', fontSize != FONT_SIZES[0]);
|
2019-08-12 20:18:46 +00:00
|
|
|
|
|
|
|
var noteFontSize = Zotero.Prefs.get('note.fontSize');
|
|
|
|
for (let menuitem of document.querySelectorAll(`#note-font-size-menu menuitem`)) {
|
|
|
|
if (parseInt(menuitem.getAttribute('label')) == noteFontSize) {
|
|
|
|
menuitem.setAttribute('checked', true);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
menuitem.removeAttribute('checked');
|
|
|
|
}
|
|
|
|
}
|
2019-08-18 20:22:39 +00:00
|
|
|
this.updateMenuItemEnabled(
|
|
|
|
'view-menuitem-note-font-size-reset',
|
|
|
|
noteFontSize != NOTE_FONT_SIZE_DEFAULT
|
|
|
|
);
|
2019-08-12 20:18:46 +00:00
|
|
|
|
|
|
|
// Recursive collections
|
2019-08-18 20:22:39 +00:00
|
|
|
this.updateMenuItemCheckmark(
|
|
|
|
'view-menuitem-recursive-collections',
|
|
|
|
Zotero.Prefs.get('recursiveCollections')
|
|
|
|
);
|
2019-08-12 20:18:46 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2019-08-18 20:22:39 +00:00
|
|
|
this.onViewMenuItemClick = function (event) {
|
2019-08-12 20:18:46 +00:00
|
|
|
var menuitem = event.originalTarget;
|
|
|
|
var id = menuitem.id;
|
2019-08-18 20:22:39 +00:00
|
|
|
var prefix = 'view-menuitem-';
|
|
|
|
if (menuitem.disabled || !id.startsWith(prefix)) {
|
2019-08-12 20:18:46 +00:00
|
|
|
return;
|
|
|
|
}
|
2019-08-18 20:22:39 +00:00
|
|
|
id = id.substr(prefix.length);
|
2019-08-12 20:18:46 +00:00
|
|
|
|
|
|
|
switch (id) {
|
|
|
|
case 'standard':
|
|
|
|
Zotero.Prefs.set('layout', 'standard');
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'stacked':
|
|
|
|
Zotero.Prefs.set('layout', 'stacked');
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'collections-pane':
|
2019-10-23 22:16:43 +00:00
|
|
|
var collectionsPane = document.getElementById('zotero-collections-pane');
|
2019-08-12 20:18:46 +00:00
|
|
|
// Show
|
2019-10-23 22:16:43 +00:00
|
|
|
if (collectionsPane.getAttribute('collapsed') == 'true') {
|
2019-08-12 20:18:46 +00:00
|
|
|
document.getElementById('zotero-collections-splitter').setAttribute('state', 'open');
|
2019-10-23 22:16:43 +00:00
|
|
|
collectionsPane.setAttribute('collapsed', false);
|
2019-08-12 20:18:46 +00:00
|
|
|
}
|
|
|
|
// Hide
|
|
|
|
else {
|
|
|
|
document.getElementById('zotero-collections-splitter').setAttribute('state', 'collapsed');
|
2019-10-23 22:16:43 +00:00
|
|
|
collectionsPane.setAttribute('collapsed', true);
|
2019-08-12 20:18:46 +00:00
|
|
|
}
|
|
|
|
ZoteroPane.updateToolbarPosition();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'item-pane':
|
2019-10-23 22:16:43 +00:00
|
|
|
var itemPane = document.getElementById('zotero-item-pane');
|
2019-08-12 20:18:46 +00:00
|
|
|
// Show
|
2019-10-23 22:16:43 +00:00
|
|
|
if (itemPane.getAttribute('collapsed') == 'true') {
|
2019-08-12 20:18:46 +00:00
|
|
|
document.getElementById('zotero-items-splitter').setAttribute('state', 'open');
|
2019-10-23 22:16:43 +00:00
|
|
|
itemPane.setAttribute('collapsed', false);
|
2019-08-12 20:18:46 +00:00
|
|
|
}
|
|
|
|
// Hide
|
|
|
|
else {
|
|
|
|
document.getElementById('zotero-items-splitter').setAttribute('state', 'collapsed');
|
2019-10-23 22:16:43 +00:00
|
|
|
itemPane.setAttribute('collapsed', true);
|
2019-08-12 20:18:46 +00:00
|
|
|
}
|
|
|
|
ZoteroPane.updateToolbarPosition();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'tag-selector':
|
|
|
|
ZoteroPane.toggleTagSelector();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'font-size-bigger':
|
|
|
|
increaseFontSize('fontSize', FONT_SIZES);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'font-size-smaller':
|
|
|
|
decreaseFontSize('fontSize', FONT_SIZES);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'font-size-reset':
|
|
|
|
Zotero.Prefs.clear('fontSize');
|
|
|
|
break;
|
|
|
|
|
|
|
|
/*case 'note-font-size-bigger':
|
|
|
|
increaseFontSize('note.fontSize', NOTE_FONT_SIZES);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'note-font-size-smaller':
|
|
|
|
decreaseFontSize('note.fontSize', NOTE_FONT_SIZES);
|
|
|
|
break;
|
|
|
|
*/
|
|
|
|
|
|
|
|
case 'note-font-size-reset':
|
|
|
|
Zotero.Prefs.clear('note.fontSize');
|
|
|
|
this.promptForRestart();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'recursive-collections':
|
|
|
|
this.toggleBooleanPref('recursiveCollections');
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2019-08-18 20:22:39 +00:00
|
|
|
this.updateMenuItemCheckmark = function (id, checked) {
|
|
|
|
var menuitem = document.getElementById(id);
|
|
|
|
if (checked) {
|
|
|
|
menuitem.setAttribute('checked', true);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
menuitem.removeAttribute('checked');
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
this.updateMenuItemEnabled = function (id, enabled) {
|
|
|
|
var menuitem = document.getElementById(id);
|
|
|
|
if (enabled) {
|
|
|
|
menuitem.removeAttribute('disabled');
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
menuitem.setAttribute('disabled', true);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2019-08-12 20:18:46 +00:00
|
|
|
this.toggleBooleanPref = function (pref) {
|
|
|
|
Zotero.Prefs.set(pref, !Zotero.Prefs.get(pref));
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
function decreaseFontSize(pref, sizes) {
|
|
|
|
var fontSize = Zotero.Prefs.get(pref);
|
|
|
|
var lastSize = fontSize;
|
|
|
|
// Get the highest font size below the current one
|
|
|
|
for (let i = sizes.length - 1; i >= 0; i--) {
|
|
|
|
if (fontSize > sizes[i]) {
|
|
|
|
lastSize = sizes[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Zotero.Prefs.set(pref, lastSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
function increaseFontSize(pref, sizes) {
|
|
|
|
var fontSize = Zotero.Prefs.get(pref);
|
|
|
|
var lastSize = fontSize;
|
|
|
|
// Get the font size above the current one
|
|
|
|
for (let i = 0; i < sizes.length; i++) {
|
|
|
|
if (sizes[i] > fontSize) {
|
|
|
|
lastSize = sizes[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Zotero.Prefs.set(pref, lastSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
this.updateNoteFontSize = function (event) {
|
|
|
|
var size = event.originalTarget.getAttribute('label');
|
|
|
|
Zotero.Prefs.set('note.fontSize', size);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
this.promptForRestart = function () {
|
|
|
|
// Prompt to restart
|
|
|
|
var ps = Services.prompt;
|
|
|
|
var buttonFlags = ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING
|
|
|
|
+ ps.BUTTON_POS_1 * ps.BUTTON_TITLE_IS_STRING;
|
|
|
|
var index = ps.confirmEx(
|
|
|
|
null,
|
|
|
|
Zotero.getString('general.restartRequired'),
|
|
|
|
Zotero.getString('general.restartRequiredForChange', [ZOTERO_CONFIG.CLIENT_NAME]),
|
|
|
|
buttonFlags,
|
|
|
|
Zotero.getString('general.restartNow'),
|
|
|
|
Zotero.getString('general.restartLater'),
|
|
|
|
null, null, {}
|
|
|
|
);
|
|
|
|
|
|
|
|
if (index == 0) {
|
|
|
|
Zotero.Utilities.Internal.quitZotero(true);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-07-23 20:21:43 +00:00
|
|
|
this.updateAddonsPane = function (doc) {
|
2019-08-23 07:18:35 +00:00
|
|
|
// Unsigned add-on warnings are hidden by default in extensions.css (via style rules added
|
|
|
|
// by fetch_xulrunner.sh), but allow other warnings
|
|
|
|
function updateExtensions () {
|
|
|
|
var addonList = doc.getElementById('addon-list');
|
|
|
|
|
2016-07-23 20:21:43 +00:00
|
|
|
for (let i = 0; i < addonList.itemCount; i++) {
|
|
|
|
let richListItem = addonList.getItemAtIndex(i);
|
|
|
|
let container = doc.getAnonymousElementByAttribute(
|
|
|
|
richListItem, 'anonid', 'warning-container'
|
|
|
|
);
|
|
|
|
if (container) {
|
|
|
|
let link = doc.getAnonymousElementByAttribute(
|
|
|
|
richListItem, 'anonid', 'warning-link'
|
|
|
|
);
|
2019-08-23 07:18:35 +00:00
|
|
|
if (link) {
|
|
|
|
if (!link.href.includes('unsigned-addons')) {
|
|
|
|
container.classList.add('allowed-warning');
|
|
|
|
}
|
2016-07-23 20:21:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-08-23 07:18:35 +00:00
|
|
|
}
|
|
|
|
doc.getElementById('category-extension').onclick = updateExtensions;
|
|
|
|
setTimeout(updateExtensions);
|
2011-07-02 07:16:24 +00:00
|
|
|
}
|
|
|
|
|
2011-07-02 03:09:13 +00:00
|
|
|
/**
|
|
|
|
* Handles help menu requests
|
|
|
|
*/
|
2011-05-31 06:34:21 +00:00
|
|
|
this.openHelp = function(type) {
|
2017-07-12 05:17:41 +00:00
|
|
|
Components.utils.import("resource://zotero/config.js");
|
|
|
|
|
2017-05-26 23:10:41 +00:00
|
|
|
switch (type) {
|
|
|
|
case "troubleshooting":
|
|
|
|
ZoteroPane.loadURI(ZOTERO_CONFIG.TROUBLESHOOTING_URL);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case "feedback":
|
|
|
|
ZoteroPane.loadURI(ZOTERO_CONFIG.FEEDBACK_URL);
|
|
|
|
break;
|
|
|
|
|
2017-06-27 20:23:46 +00:00
|
|
|
case "connectors":
|
|
|
|
ZoteroPane.loadURI(ZOTERO_CONFIG.CONNECTORS_URL);
|
2017-06-26 22:49:31 +00:00
|
|
|
break;
|
|
|
|
|
2017-05-26 23:10:41 +00:00
|
|
|
default:
|
|
|
|
ZoteroPane.loadURI(ZOTERO_CONFIG.SUPPORT_URL);
|
2011-05-31 06:34:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-11 14:54:51 +00:00
|
|
|
/**
|
|
|
|
* Checks for updates
|
|
|
|
*/
|
|
|
|
this.checkForUpdates = function() {
|
|
|
|
window.open('chrome://mozapps/content/update/updates.xul', 'updateChecker', 'chrome,centerscreen');
|
|
|
|
}
|
|
|
|
|
2011-07-02 03:09:13 +00:00
|
|
|
/**
|
|
|
|
* Called before standalone window is closed
|
|
|
|
*/
|
2011-01-30 09:44:01 +00:00
|
|
|
this.onUnload = function() {
|
|
|
|
ZoteroPane.destroy();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-25 06:36:33 +00:00
|
|
|
|
|
|
|
ZoteroStandalone.DebugOutput = {
|
|
|
|
_timer: null,
|
|
|
|
|
|
|
|
init: function () {
|
|
|
|
var storing = Zotero.Debug.storing;
|
|
|
|
this._showMenu();
|
|
|
|
this.update();
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
toggleStore: function () {
|
|
|
|
Zotero.Debug.setStore(!Zotero.Debug.storing);
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
update: function () {
|
|
|
|
var enabled = Zotero.Debug.storing;
|
|
|
|
var lines = Zotero.Debug.count();
|
|
|
|
var empty = lines == 0;
|
|
|
|
|
|
|
|
// Show "Submit" when enabled, but leave disabled until there's output
|
|
|
|
var menuitem = document.getElementById('debug-output-submit');
|
|
|
|
menuitem.hidden = !enabled && empty;
|
|
|
|
menuitem.disabled = empty;
|
|
|
|
|
|
|
|
// Toggle between "Enable" and "Disable"
|
|
|
|
menuitem = document.getElementById('debug-output-enable-disable');
|
|
|
|
menuitem.label = Zotero.getString('general.' + (enabled ? 'disable' : 'enable'));
|
|
|
|
|
|
|
|
// Update line count
|
|
|
|
var str = Zotero.getString('zotero.debugOutputLogging.linesLogged', lines, lines);
|
|
|
|
document.getElementById('debug-output-status').label = str;
|
|
|
|
|
|
|
|
// Enable "Clear" when there's output
|
|
|
|
document.getElementById('debug-output-clear').disabled = empty;
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
submit: function () {
|
|
|
|
// 'Zotero' isn't defined yet when this function is created, so do it inline
|
|
|
|
return Zotero.Promise.coroutine(function* () {
|
2018-06-04 06:08:07 +00:00
|
|
|
Zotero.debug("Submitting debug output");
|
|
|
|
|
2017-07-25 06:36:33 +00:00
|
|
|
Components.utils.import("resource://zotero/config.js");
|
|
|
|
|
|
|
|
var url = ZOTERO_CONFIG.REPOSITORY_URL + "report?debug=1";
|
|
|
|
var output = yield Zotero.Debug.get(
|
|
|
|
Zotero.Prefs.get('debug.store.submitSize'),
|
|
|
|
Zotero.Prefs.get('debug.store.submitLineLength')
|
|
|
|
);
|
|
|
|
Zotero.Debug.setStore(false);
|
|
|
|
|
|
|
|
var ps = Services.prompt;
|
|
|
|
try {
|
|
|
|
var xmlhttp = yield Zotero.HTTP.request(
|
|
|
|
"POST",
|
|
|
|
url,
|
|
|
|
{
|
|
|
|
compressBody: true,
|
|
|
|
body: output,
|
|
|
|
logBodyLength: 30,
|
|
|
|
timeout: 15000,
|
|
|
|
requestObserver: function (req) {
|
|
|
|
// Don't fail during tests, with fake XHR
|
|
|
|
if (!req.channel) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
req.channel.notificationCallbacks = {
|
|
|
|
onProgress: function (request, context, progress, progressMax) {},
|
|
|
|
|
|
|
|
// nsIInterfaceRequestor
|
|
|
|
getInterface: function (iid) {
|
|
|
|
try {
|
|
|
|
return this.QueryInterface(iid);
|
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
throw Components.results.NS_NOINTERFACE;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
QueryInterface: function(iid) {
|
|
|
|
if (iid.equals(Components.interfaces.nsISupports) ||
|
|
|
|
iid.equals(Components.interfaces.nsIInterfaceRequestor) ||
|
|
|
|
iid.equals(Components.interfaces.nsIProgressEventSink)) {
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
throw Components.results.NS_NOINTERFACE;
|
|
|
|
},
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
Zotero.logError(e);
|
|
|
|
let title = Zotero.getString('general.error');
|
|
|
|
let msg;
|
|
|
|
if (e instanceof Zotero.HTTP.UnexpectedStatusException) {
|
|
|
|
msg = Zotero.getString('general.invalidResponseServer');
|
|
|
|
}
|
|
|
|
else if (e instanceof Zotero.HTTP.BrowserOfflineException) {
|
|
|
|
msg = Zotero.getString('general.browserIsOffline', Zotero.appName);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
msg = Zotero.getString('zotero.debugOutputLogging.dialog.error');
|
|
|
|
}
|
|
|
|
ps.alert(null, title, msg);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Zotero.debug(xmlhttp.responseText);
|
|
|
|
|
|
|
|
var reported = xmlhttp.responseXML.getElementsByTagName('reported');
|
|
|
|
if (reported.length != 1) {
|
|
|
|
ps.alert(
|
|
|
|
null,
|
|
|
|
Zotero.getString('general.error'),
|
|
|
|
Zotero.getString('general.serverError')
|
|
|
|
);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
var reportID = reported[0].getAttribute('reportID');
|
|
|
|
|
|
|
|
var buttonFlags = ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING
|
|
|
|
+ ps.BUTTON_POS_1 * ps.BUTTON_TITLE_CANCEL;
|
|
|
|
var index = ps.confirmEx(
|
|
|
|
null,
|
|
|
|
Zotero.getString('zotero.debugOutputLogging.dialog.title'),
|
|
|
|
Zotero.getString('zotero.debugOutputLogging.dialog.sent', [ZOTERO_CONFIG.DOMAIN_NAME, reportID]),
|
|
|
|
buttonFlags,
|
|
|
|
Zotero.getString('general.copyToClipboard'),
|
|
|
|
null, null, null, {}
|
|
|
|
);
|
|
|
|
if (index == 0) {
|
|
|
|
const helper = Components.classes["@mozilla.org/widget/clipboardhelper;1"]
|
|
|
|
.getService(Components.interfaces.nsIClipboardHelper);
|
|
|
|
helper.copyString("D" + reportID);
|
|
|
|
}
|
|
|
|
|
|
|
|
Zotero.Debug.clear();
|
|
|
|
return true;
|
|
|
|
}.bind(this))();
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
view: function () {
|
|
|
|
Zotero.openInViewer("chrome://zotero/content/debugViewer.html", function (doc) {
|
|
|
|
var submitted = false;
|
|
|
|
doc.querySelector('#submit-button').addEventListener('click', function (event) {
|
|
|
|
submitted = true;
|
|
|
|
});
|
|
|
|
doc.querySelector('#clear-button').addEventListener('click', function (event) {
|
|
|
|
Zotero.Debug.clear();
|
|
|
|
});
|
|
|
|
// If output has been submitted, disable logging when window is closed
|
|
|
|
doc.defaultView.addEventListener('unload', function (event) {
|
|
|
|
if (submitted) {
|
|
|
|
Zotero.Debug.setStore(false);
|
|
|
|
Zotero.Debug.clear();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
clear: function () {
|
|
|
|
Zotero.Debug.clear();
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
restartEnabled: function () {
|
2017-08-05 17:44:58 +00:00
|
|
|
var ps = Services.prompt;
|
|
|
|
var buttonFlags = ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING
|
|
|
|
+ ps.BUTTON_POS_1 * ps.BUTTON_TITLE_CANCEL
|
|
|
|
+ ps.BUTTON_POS_2 * ps.BUTTON_TITLE_IS_STRING;
|
|
|
|
var index = ps.confirmEx(
|
|
|
|
null,
|
|
|
|
Zotero.getString('zotero.debugOutputLogging'),
|
|
|
|
Zotero.getString('zotero.debugOutputLogging.enabledAfterRestart', [Zotero.clientName]),
|
|
|
|
buttonFlags,
|
|
|
|
Zotero.getString('general.restartNow'),
|
|
|
|
null, Zotero.getString('general.restartLater'), null, {}
|
|
|
|
);
|
|
|
|
if (index != 1) {
|
|
|
|
Zotero.Prefs.set('debug.store', true);
|
|
|
|
}
|
|
|
|
if (index == 0) {
|
|
|
|
Zotero.Utilities.Internal.quit(true);
|
|
|
|
}
|
2017-07-25 06:36:33 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
_showMenu: function () {
|
|
|
|
document.getElementById('debug-output-menu').hidden = false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2011-05-31 05:32:45 +00:00
|
|
|
function toJavaScriptConsole() {
|
2019-08-27 23:37:39 +00:00
|
|
|
openWindowByType('chrome://global/content/console.xul', 'global:console');
|
2011-05-31 05:32:45 +00:00
|
|
|
}
|
|
|
|
|
2019-01-22 05:10:14 +00:00
|
|
|
function openRunJSWindow() {
|
2019-08-27 23:37:39 +00:00
|
|
|
openWindowByType(
|
|
|
|
'chrome://zotero/content/runJS.html',
|
|
|
|
'zotero:run-js',
|
|
|
|
'chrome,width=900,height=700,resizable,centerscreen'
|
|
|
|
);
|
2019-01-22 05:10:14 +00:00
|
|
|
}
|
|
|
|
|
2019-08-05 09:05:57 +00:00
|
|
|
function openStyleEditor() {
|
2019-08-27 23:37:39 +00:00
|
|
|
openWindowByType(
|
|
|
|
'chrome://zotero/content/tools/csledit.xul',
|
|
|
|
'zotero:style-editor',
|
|
|
|
'chrome,width=950,height=700,resizable'
|
|
|
|
);
|
2019-08-05 09:05:57 +00:00
|
|
|
}
|
|
|
|
|
2019-08-02 10:09:36 +00:00
|
|
|
function openScaffold() {
|
2019-08-27 23:37:39 +00:00
|
|
|
openWindowByType(
|
|
|
|
'chrome://scaffold/content/scaffold.xul',
|
|
|
|
'zotero:scaffold',
|
|
|
|
'chrome,resizable'
|
|
|
|
);
|
2019-08-02 10:09:36 +00:00
|
|
|
}
|
|
|
|
|
2019-08-27 23:37:39 +00:00
|
|
|
function openWindowByType(uri, type, features) {
|
|
|
|
var win = Services.wm.getMostRecentWindow(type);
|
2011-05-31 05:32:45 +00:00
|
|
|
|
2019-08-27 23:37:39 +00:00
|
|
|
if (win) {
|
|
|
|
win.focus();
|
|
|
|
}
|
|
|
|
else if (features) {
|
2011-05-31 05:32:45 +00:00
|
|
|
window.open(uri, "_blank", features);
|
2019-08-27 23:37:39 +00:00
|
|
|
}
|
|
|
|
else {
|
2011-05-31 05:32:45 +00:00
|
|
|
window.open(uri, "_blank", "chrome,extrachrome,menubar,resizable,scrollbars,status,toolbar");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-25 07:35:22 +00:00
|
|
|
const gXPInstallObserver = {
|
2020-01-02 03:17:31 +00:00
|
|
|
observe: function (subject, topic, data) {
|
|
|
|
const { installs } = subject.wrappedJSObject;
|
|
|
|
switch (topic) {
|
2011-08-25 07:35:22 +00:00
|
|
|
case "addon-install-disabled":
|
|
|
|
case "addon-install-blocked":
|
|
|
|
case "addon-install-failed":
|
2020-01-02 03:17:31 +00:00
|
|
|
Zotero.alert(
|
|
|
|
null,
|
|
|
|
Zotero.getString("standalone.addonInstallationFailed.title"),
|
|
|
|
Zotero.getString("standalone.addonInstallationFailed.body", installs[0].name));
|
2011-08-25 07:35:22 +00:00
|
|
|
break;
|
|
|
|
/*case "addon-install-started":
|
|
|
|
case "addon-install-complete":*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-01-16 07:56:58 +00:00
|
|
|
// Used by update prompt
|
|
|
|
function openUILinkIn(url) {
|
|
|
|
ZoteroPane.loadURI(url);
|
|
|
|
}
|
|
|
|
|
2019-11-30 07:41:29 +00:00
|
|
|
// Support context menus on HTML text boxes
|
|
|
|
//
|
|
|
|
// Adapted from editMenuOverlay.js in Fx68
|
|
|
|
window.addEventListener("contextmenu", e => {
|
|
|
|
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
|
|
|
let needsContextMenu =
|
|
|
|
e.target.ownerDocument == document &&
|
|
|
|
!e.defaultPrevented &&
|
|
|
|
e.target.parentNode.nodeName != "moz-input-box" &&
|
|
|
|
((["textarea", "input"].includes(e.target.localName) &&
|
|
|
|
e.target.namespaceURI == HTML_NS) ||
|
|
|
|
e.target.closest("search-textbox"));
|
|
|
|
|
|
|
|
if (!needsContextMenu) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let popup = document.getElementById("contentAreaContextMenu");
|
|
|
|
popup.openPopupAtScreen(e.screenX, e.screenY, true);
|
|
|
|
// Don't show any other context menu at the same time. There can be a
|
|
|
|
// context menu from an ancestor too but we only want to show this one.
|
|
|
|
e.preventDefault();
|
|
|
|
});
|
|
|
|
|
|
|
|
|
2011-01-30 09:44:01 +00:00
|
|
|
window.addEventListener("load", function(e) { ZoteroStandalone.onLoad(e); }, false);
|
|
|
|
window.addEventListener("unload", function(e) { ZoteroStandalone.onUnload(e); }, false);
|