2006-10-04 17:16:56 +00:00
|
|
|
/*
|
|
|
|
***** BEGIN LICENSE BLOCK *****
|
2009-12-28 09:47:49 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
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
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
2006-10-04 17:16:56 +00:00
|
|
|
|
|
|
|
***** END LICENSE BLOCK *****
|
|
|
|
*/
|
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
const RESELECT_KEY_URI = 1;
|
|
|
|
const RESELECT_KEY_ITEM_KEY = 2;
|
|
|
|
const RESELECT_KEY_ITEM_ID = 3;
|
2010-05-30 11:25:25 +00:00
|
|
|
const DATA_VERSION = 3;
|
2007-10-23 07:11:59 +00:00
|
|
|
|
2010-09-16 06:22:39 +00:00
|
|
|
// this is used only for update checking
|
|
|
|
const INTEGRATION_PLUGINS = ["zoteroMacWordIntegration@zotero.org",
|
|
|
|
"zoteroOpenOfficeIntegration@zotero.org", "zoteroWinWordIntegration@zotero.org"];
|
|
|
|
const INTEGRATION_MIN_VERSION = "3.1a0";
|
|
|
|
|
2006-10-02 23:15:27 +00:00
|
|
|
Zotero.Integration = new function() {
|
2010-03-02 21:54:53 +00:00
|
|
|
var _fifoFile = null;
|
2011-03-20 08:12:39 +00:00
|
|
|
var _tmpFile = null;
|
|
|
|
var _shCmd = null;
|
|
|
|
var _shProc = null;
|
2010-03-02 21:54:53 +00:00
|
|
|
var _osascriptFile;
|
2010-06-17 06:38:03 +00:00
|
|
|
var _inProgress = false;
|
2010-09-16 06:22:39 +00:00
|
|
|
var _integrationVersionsOK = null;
|
2011-03-26 04:20:22 +00:00
|
|
|
var _pipeMode = false;
|
2011-03-01 06:13:43 +00:00
|
|
|
var _winUser32;
|
Merged revisions 2710-2712,2714-2716,2718-2728,2730-2731,2734,2736-2738,2740-2750,2752-2753,2755,2758-2768,2770-2779,2782,2789-2790,2794,2797-2802,2804,2808-2810,2812,2814-2824,2826-2832,2834-2835 via svnmerge from 1.0 branch
2008-06-11 08:55:59 +00:00
|
|
|
|
2008-07-10 11:05:43 +00:00
|
|
|
this.sessions = {};
|
2008-11-30 20:18:48 +00:00
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
/**
|
|
|
|
* Initializes the pipe used for integration on non-Windows platforms.
|
2006-08-28 05:38:37 +00:00
|
|
|
*/
|
2009-08-20 05:02:55 +00:00
|
|
|
this.init = function() {
|
2010-12-19 06:26:47 +00:00
|
|
|
// initialize SOAP server just to throw version errors
|
|
|
|
Zotero.Integration.Compat.init();
|
|
|
|
|
|
|
|
// Windows uses a command line handler for integration. See
|
|
|
|
// components/zotero-integration-service.js for this implementation.
|
|
|
|
if(Zotero.isWin) return;
|
|
|
|
|
|
|
|
// Determine where to put the pipe
|
|
|
|
if(Zotero.isMac) {
|
|
|
|
// on OS X, first try /Users/Shared for those who can't put pipes in their home
|
|
|
|
// directories
|
|
|
|
_fifoFile = Components.classes["@mozilla.org/file/local;1"].
|
|
|
|
createInstance(Components.interfaces.nsILocalFile);
|
|
|
|
_fifoFile.initWithPath("/Users/Shared");
|
2010-03-02 21:54:53 +00:00
|
|
|
|
2010-12-19 06:26:47 +00:00
|
|
|
if(_fifoFile.exists() && _fifoFile.isDirectory() && _fifoFile.isWritable()) {
|
|
|
|
var logname = Components.classes["@mozilla.org/process/environment;1"].
|
|
|
|
getService(Components.interfaces.nsIEnvironment).
|
|
|
|
get("LOGNAME");
|
|
|
|
_fifoFile.append(".zoteroIntegrationPipe_"+logname);
|
|
|
|
} else {
|
|
|
|
_fifoFile = null;
|
2010-03-02 21:54:53 +00:00
|
|
|
}
|
2010-12-19 06:26:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(!_fifoFile) {
|
|
|
|
// on other platforms, or as a fallback, use home directory
|
|
|
|
_fifoFile = Components.classes["@mozilla.org/file/directory_service;1"].
|
|
|
|
getService(Components.interfaces.nsIProperties).
|
|
|
|
get("Home", Components.interfaces.nsIFile);
|
|
|
|
_fifoFile.append(".zoteroIntegrationPipe");
|
|
|
|
}
|
|
|
|
|
|
|
|
Zotero.debug("Initializing Zotero integration pipe at "+_fifoFile.path);
|
|
|
|
|
|
|
|
// destroy old pipe, if one exists
|
|
|
|
try {
|
|
|
|
if(_fifoFile.exists()) {
|
|
|
|
_fifoFile.remove(false);
|
2010-05-10 21:13:52 +00:00
|
|
|
}
|
2010-12-19 06:26:47 +00:00
|
|
|
} catch (e) {
|
|
|
|
// if pipe can't be deleted, log an error
|
|
|
|
Zotero.debug("Error removing old integration pipe", 1);
|
|
|
|
Components.utils.reportError(
|
|
|
|
"Zotero word processor integration initialization failed. "
|
|
|
|
+ "See http://forums.zotero.org/discussion/12054/#Item_10 "
|
|
|
|
+ "for instructions on correcting this problem."
|
|
|
|
);
|
|
|
|
if(Zotero.isMac) {
|
|
|
|
// can attempt to delete on OS X
|
|
|
|
try {
|
|
|
|
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
|
|
|
.getService(Components.interfaces.nsIPromptService);
|
|
|
|
var deletePipe = promptService.confirm(null, Zotero.getString("integration.error.title"), Zotero.getString("integration.error.deletePipe"));
|
|
|
|
if(!deletePipe) return;
|
|
|
|
let escapedFifoFile = _fifoFile.path.replace("'", "'\\''");
|
|
|
|
_executeAppleScript("do shell script \"rmdir '"+escapedFifoFile+"'; rm -f '"+escapedFifoFile+"'\" with administrator privileges", true);
|
|
|
|
if(_fifoFile.exists()) return;
|
|
|
|
} catch(e) {
|
|
|
|
Zotero.logError(e);
|
|
|
|
return;
|
2009-08-20 05:02:55 +00:00
|
|
|
}
|
2006-08-28 05:38:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-19 06:26:47 +00:00
|
|
|
// try to initialize pipe
|
2010-12-20 05:11:22 +00:00
|
|
|
try {
|
2011-03-20 08:58:20 +00:00
|
|
|
var pipeInitialized = _initializeIntegrationPipe();
|
2010-12-20 05:11:22 +00:00
|
|
|
} catch(e) {
|
|
|
|
Components.utils.reportError(e);
|
|
|
|
}
|
2010-12-19 06:26:47 +00:00
|
|
|
|
|
|
|
if(pipeInitialized) {
|
|
|
|
// if initialization succeeded, add an observer so that we don't hang shutdown
|
|
|
|
var observerService = Components.classes["@mozilla.org/observer-service;1"]
|
|
|
|
.getService(Components.interfaces.nsIObserverService);
|
2010-12-21 05:49:53 +00:00
|
|
|
observerService.addObserver({ observe: Zotero.Integration.destroy }, "quit-application", false);
|
2010-12-19 06:26:47 +00:00
|
|
|
}
|
2006-08-28 05:38:37 +00:00
|
|
|
}
|
Merged revisions 2710-2712,2714-2716,2718-2728,2730-2731,2734,2736-2738,2740-2750,2752-2753,2755,2758-2768,2770-2779,2782,2789-2790,2794,2797-2802,2804,2808-2810,2812,2814-2824,2826-2832,2834-2835 via svnmerge from 1.0 branch
2008-06-11 08:55:59 +00:00
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
/**
|
2010-09-16 06:22:39 +00:00
|
|
|
* Executes an integration command, first checking to make sure that versions are compatible
|
2009-08-20 05:02:55 +00:00
|
|
|
*/
|
2010-06-20 10:48:38 +00:00
|
|
|
this.execCommand = function execCommand(agent, command, docId) {
|
2010-06-17 06:38:03 +00:00
|
|
|
if(_inProgress) {
|
|
|
|
Zotero.Integration.activate();
|
|
|
|
Zotero.debug("Integration: Request already in progress; not executing "+agent+" "+command);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
_inProgress = true;
|
|
|
|
|
2010-09-16 06:22:39 +00:00
|
|
|
// Check integration component versions
|
|
|
|
if(!_integrationVersionsOK) {
|
2011-03-01 05:31:20 +00:00
|
|
|
var verComp = Components.classes["@mozilla.org/xpcom/version-comparator;1"]
|
|
|
|
.getService(Components.interfaces.nsIVersionComparator);
|
|
|
|
var addonsChecked = false;
|
|
|
|
function _checkAddons(addons) {
|
|
|
|
addonsChecked = true;
|
|
|
|
for each(var addon in addons) {
|
|
|
|
if(!addon) continue;
|
|
|
|
|
|
|
|
if(verComp.compare(INTEGRATION_MIN_VERSION, addon.version) > 0) {
|
|
|
|
_inProgress = false;
|
|
|
|
_integrationVersionsOK = false;
|
|
|
|
Zotero.Integration.activate();
|
|
|
|
var msg = Zotero.getString(
|
|
|
|
"integration.error.incompatibleVersion2",
|
|
|
|
[Zotero.version, addon.name, INTEGRATION_MIN_VERSION]
|
|
|
|
);
|
|
|
|
Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
|
|
|
.getService(Components.interfaces.nsIPromptService)
|
|
|
|
.alert(null, Zotero.getString("integration.error.title"), msg);
|
|
|
|
throw msg;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_integrationVersionsOK = true;
|
|
|
|
_callIntegration(agent, command, docId);
|
|
|
|
}
|
|
|
|
|
2010-09-16 06:22:39 +00:00
|
|
|
if(Zotero.isFx4) {
|
|
|
|
Components.utils.import("resource://gre/modules/AddonManager.jsm");
|
|
|
|
AddonManager.getAddonsByIDs(INTEGRATION_PLUGINS, _checkAddons);
|
2011-03-01 05:31:20 +00:00
|
|
|
while(!addonsChecked) Zotero.mainThread.processNextEvent(true);
|
2010-09-16 06:22:39 +00:00
|
|
|
} else {
|
|
|
|
var extMan = Components.classes['@mozilla.org/extensions/manager;1'].
|
|
|
|
getService(Components.interfaces.nsIExtensionManager);
|
|
|
|
_checkAddons([extMan.getItemForID(id) for each(id in INTEGRATION_PLUGINS)]);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
_callIntegration(agent, command, docId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-19 06:26:47 +00:00
|
|
|
/**
|
2011-03-20 08:58:20 +00:00
|
|
|
* Parses a command received from the integration pipe
|
2010-12-19 06:26:47 +00:00
|
|
|
*/
|
2011-03-20 08:58:20 +00:00
|
|
|
function _parseIntegrationPipeCommand(string) {
|
2011-03-20 08:12:39 +00:00
|
|
|
if(string != "") {
|
2011-03-20 08:26:25 +00:00
|
|
|
// exec command if possible
|
2011-03-20 08:12:39 +00:00
|
|
|
var parts = string.match(/^([^ \n]*) ([^ \n]*)(?: ([^\n]*))?\n?$/);
|
|
|
|
if(parts) {
|
|
|
|
var agent = parts[1].toString();
|
|
|
|
var cmd = parts[2].toString();
|
|
|
|
|
2011-03-20 08:26:25 +00:00
|
|
|
// return if we were told to shutdown
|
|
|
|
if(agent === "Zotero" && cmd === "shutdown") return;
|
2011-03-20 08:58:20 +00:00
|
|
|
|
|
|
|
_initializePipeStreamPump();
|
2011-03-20 08:12:39 +00:00
|
|
|
|
2011-03-20 08:26:25 +00:00
|
|
|
var document = parts[3] ? parts[3].toString() : null;
|
2011-03-20 08:12:39 +00:00
|
|
|
Zotero.Integration.execCommand(agent, cmd, document);
|
|
|
|
} else {
|
2011-03-20 08:58:20 +00:00
|
|
|
_initializePipeStreamPump();
|
2011-03-20 08:26:25 +00:00
|
|
|
Components.utils.reportError("Zotero: Invalid integration input received: "+string);
|
2010-12-19 06:26:47 +00:00
|
|
|
}
|
2011-03-20 08:26:25 +00:00
|
|
|
} else {
|
2011-03-20 08:58:20 +00:00
|
|
|
_initializePipeStreamPump();
|
2010-12-19 06:26:47 +00:00
|
|
|
}
|
2011-03-20 08:58:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2011-03-20 08:59:32 +00:00
|
|
|
* Listens asynchronously for data on the integration pipe and reads it when available
|
|
|
|
*
|
2011-03-26 04:20:22 +00:00
|
|
|
* Used to read from the integration pipe on Fx 4.2
|
2011-03-20 08:58:20 +00:00
|
|
|
*/
|
2011-03-26 04:20:22 +00:00
|
|
|
var _integrationPipeListenerFx42 = {
|
2011-03-20 08:58:20 +00:00
|
|
|
"onStartRequest":function() {},
|
|
|
|
"onStopRequest":function() {},
|
|
|
|
|
|
|
|
"onDataAvailable":function(request, context, inputStream, offset, count) {
|
|
|
|
// read from pipe
|
|
|
|
var converterInputStream = Components.classes["@mozilla.org/intl/converter-input-stream;1"]
|
|
|
|
.createInstance(Components.interfaces.nsIConverterInputStream);
|
|
|
|
converterInputStream.init(inputStream, "UTF-8", 4096,
|
|
|
|
Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
|
|
|
|
var out = {};
|
|
|
|
converterInputStream.readString(count, out);
|
2011-03-20 09:09:54 +00:00
|
|
|
inputStream.close();
|
2011-03-20 08:58:20 +00:00
|
|
|
|
|
|
|
_parseIntegrationPipeCommand(out.value);
|
2011-03-20 08:12:39 +00:00
|
|
|
}};
|
2010-12-19 06:26:47 +00:00
|
|
|
|
|
|
|
/**
|
2011-03-20 08:58:20 +00:00
|
|
|
* Reads from the temp file set up to handle integration pipe and executes the appropriate
|
|
|
|
* integration command
|
2011-03-20 08:59:32 +00:00
|
|
|
*
|
|
|
|
* Used to read from the integration pipe on Fx 3.6
|
2010-12-19 06:26:47 +00:00
|
|
|
*/
|
2011-03-20 08:58:20 +00:00
|
|
|
var _integrationPipeObserverFx36 = {"observe":function(subject) {
|
|
|
|
// if we had an error reading from the pipe, return immediately, because trying to read
|
|
|
|
// again will probably just cause us to loop
|
|
|
|
if(subject.exitValue !== 0) {
|
|
|
|
Components.utils.reportError("Zotero: An error occurred reading from integration pipe");
|
|
|
|
return;
|
|
|
|
}
|
2011-03-20 08:12:39 +00:00
|
|
|
|
2011-03-20 08:58:20 +00:00
|
|
|
// read from pipe
|
|
|
|
var string = Zotero.File.getContents(_tmpFile);
|
|
|
|
|
|
|
|
_parseIntegrationPipeCommand(string);
|
|
|
|
}};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Initializes the nsIInputStream and nsIInputStreamPump to read from _fifoFile
|
|
|
|
*/
|
|
|
|
function _initializePipeStreamPump() {
|
2011-03-26 04:20:22 +00:00
|
|
|
if(_pipeMode === "deferredOpen") {
|
|
|
|
// Fx >4 supports deferred open; no need to use sh
|
2011-03-20 08:58:20 +00:00
|
|
|
var fifoStream = Components.classes["@mozilla.org/network/file-input-stream;1"].
|
|
|
|
createInstance(Components.interfaces.nsIFileInputStream);
|
|
|
|
fifoStream.QueryInterface(Components.interfaces.nsIFileInputStream);
|
|
|
|
// 16 = open as deferred so that we don't block on open
|
|
|
|
fifoStream.init(_fifoFile, -1, 0, 16);
|
|
|
|
|
|
|
|
var pump = Components.classes["@mozilla.org/network/input-stream-pump;1"].
|
|
|
|
createInstance(Components.interfaces.nsIInputStreamPump);
|
|
|
|
pump.init(fifoStream, -1, -1, 4096, 1, true);
|
2011-03-26 04:20:22 +00:00
|
|
|
pump.asyncRead(_integrationPipeListenerFx42, null);
|
2011-03-20 08:58:20 +00:00
|
|
|
} else {
|
|
|
|
// Fx 3.6 doesn't support deferred open
|
|
|
|
_shProc.runAsync(_shCmd, _shCmd.length, _integrationPipeObserverFx36);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2011-03-20 08:59:32 +00:00
|
|
|
* Initializes the Zotero Integration Pipe
|
2011-03-20 08:58:20 +00:00
|
|
|
*/
|
|
|
|
function _initializeIntegrationPipe() {
|
2011-03-26 04:20:22 +00:00
|
|
|
var verComp = Components.classes["@mozilla.org/xpcom/version-comparator;1"]
|
|
|
|
.getService(Components.interfaces.nsIVersionComparator);
|
|
|
|
var appInfo = Components.classes["@mozilla.org/xre/app-info;1"].
|
|
|
|
getService(Components.interfaces.nsIXULAppInfo);
|
|
|
|
if(Zotero.isFx4) {
|
|
|
|
if(verComp.compare("2.0b9pre", appInfo.platformVersion) > 0) {
|
|
|
|
Components.utils.reportError("Zotero word processor integration requires "+
|
|
|
|
"Firefox 4.0b9 or later. Please update to the latest Firefox 4.0 beta.");
|
|
|
|
return;
|
|
|
|
} else if(verComp.compare("2.2a1pre", appInfo.platformVersion) <= 0) {
|
|
|
|
_pipeMode = "deferredOpen";
|
|
|
|
} else {
|
|
|
|
_pipeMode = "fx4thread";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if(Zotero.isMac) {
|
|
|
|
_pipeMode = "subprocess";
|
|
|
|
} else {
|
|
|
|
_pipeMode = "fx36thread";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Zotero.debug("Using integration pipe mode "+_pipeMode);
|
2011-03-21 20:30:46 +00:00
|
|
|
|
2010-12-19 06:26:47 +00:00
|
|
|
// make a new pipe
|
|
|
|
var mkfifo = Components.classes["@mozilla.org/file/local;1"].
|
|
|
|
createInstance(Components.interfaces.nsILocalFile);
|
|
|
|
mkfifo.initWithPath("/usr/bin/mkfifo");
|
|
|
|
if(!mkfifo.exists()) mkfifo.initWithPath("/bin/mkfifo");
|
|
|
|
if(!mkfifo.exists()) mkfifo.initWithPath("/usr/local/bin/mkfifo");
|
|
|
|
|
2011-03-20 08:12:39 +00:00
|
|
|
// get sh
|
|
|
|
var sh = Components.classes["@mozilla.org/file/local;1"].
|
|
|
|
createInstance(Components.interfaces.nsILocalFile);
|
|
|
|
sh.initWithPath("/bin/sh");
|
|
|
|
|
|
|
|
if(mkfifo.exists() && sh.exists()) {
|
|
|
|
// create named pipe
|
|
|
|
var proc = Components.classes["@mozilla.org/process/util;1"].
|
|
|
|
createInstance(Components.interfaces.nsIProcess);
|
|
|
|
proc.init(mkfifo);
|
|
|
|
proc.run(true, [_fifoFile.path], 1);
|
2010-12-19 06:26:47 +00:00
|
|
|
|
2011-03-20 08:12:39 +00:00
|
|
|
if(_fifoFile.exists()) {
|
2011-03-26 04:20:22 +00:00
|
|
|
if(_pipeMode === "subprocess") {
|
2011-03-20 08:59:32 +00:00
|
|
|
// no deferred open capability, so we need to use the sh/tmpfile hack
|
|
|
|
|
2011-03-20 08:58:20 +00:00
|
|
|
// make a tmp file
|
|
|
|
_tmpFile = Components.classes["@mozilla.org/file/directory_service;1"].
|
|
|
|
getService(Components.interfaces.nsIProperties).
|
|
|
|
get("TmpD", Components.interfaces.nsIFile);
|
|
|
|
_tmpFile.append("zoteroIntegrationTmp");
|
|
|
|
_tmpFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0666);
|
2011-03-20 08:12:39 +00:00
|
|
|
|
2011-03-20 08:58:20 +00:00
|
|
|
// begin reading from named pipe
|
|
|
|
_shCmd = ["-c", "cat '"+_fifoFile.path.replace("'", "'\\''")+"' > '"+
|
|
|
|
_tmpFile.path.replace("'", "'\\''")+"'"];
|
|
|
|
Zotero.debug("Calling sh "+_shCmd.join(" "));
|
|
|
|
|
|
|
|
_shProc = Components.classes["@mozilla.org/process/util;1"].
|
|
|
|
createInstance(Components.interfaces.nsIProcess);
|
|
|
|
_shProc.init(sh);
|
2011-03-26 04:20:22 +00:00
|
|
|
|
|
|
|
_initializePipeStreamPump();
|
|
|
|
} else if(_pipeMode === "deferredOpen") {
|
|
|
|
_initializePipeStreamPump();
|
|
|
|
} else if(_pipeMode === "fx36thread") {
|
|
|
|
var main = Components.classes["@mozilla.org/thread-manager;1"].getService().mainThread;
|
|
|
|
var background = Components.classes["@mozilla.org/thread-manager;1"].getService().newThread(0);
|
|
|
|
|
|
|
|
function mainThread(agent, cmd, doc) {
|
|
|
|
this.agent = agent;
|
|
|
|
this.cmd = cmd;
|
|
|
|
this.document = doc;
|
|
|
|
}
|
|
|
|
mainThread.prototype.run = function() {
|
|
|
|
Zotero.Integration.execCommand(this.agent, this.cmd, this.document);
|
|
|
|
}
|
|
|
|
|
|
|
|
function fifoThread() {}
|
|
|
|
fifoThread.prototype.run = function() {
|
|
|
|
var fifoStream = Components.classes["@mozilla.org/network/file-input-stream;1"].
|
|
|
|
createInstance(Components.interfaces.nsIFileInputStream);
|
|
|
|
var line = {};
|
|
|
|
while(true) {
|
|
|
|
fifoStream.QueryInterface(Components.interfaces.nsIFileInputStream);
|
|
|
|
fifoStream.init(_fifoFile, -1, 0, 0);
|
|
|
|
fifoStream.QueryInterface(Components.interfaces.nsILineInputStream);
|
|
|
|
fifoStream.readLine(line);
|
|
|
|
fifoStream.close();
|
|
|
|
|
|
|
|
var parts = line.value.split(" ");
|
|
|
|
var agent = parts[0];
|
|
|
|
var cmd = parts[1];
|
|
|
|
var document = parts.length >= 3 ? line.value.substr(agent.length+cmd.length+2) : null;
|
|
|
|
if(agent == "Zotero" && cmd == "shutdown") return;
|
|
|
|
main.dispatch(new mainThread(agent, cmd, document), background.DISPATCH_NORMAL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fifoThread.prototype.QueryInterface = mainThread.prototype.QueryInterface = function(iid) {
|
|
|
|
if (iid.equals(Components.interfaces.nsIRunnable) ||
|
|
|
|
iid.equals(Components.interfaces.nsISupports)) return this;
|
|
|
|
throw Components.results.NS_ERROR_NO_INTERFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
background.dispatch(new fifoThread(), background.DISPATCH_NORMAL);
|
|
|
|
} else if(_pipeMode === "fx4thread") {
|
|
|
|
Components.utils.import("resource://gre/modules/ctypes.jsm");
|
|
|
|
|
|
|
|
// get possible names for libc
|
|
|
|
if(Zotero.isMac) {
|
|
|
|
var possibleLibcs = ["/usr/lib/libc.dylib"];
|
|
|
|
} else {
|
|
|
|
var possibleLibcs = [
|
|
|
|
"libc.so.6",
|
|
|
|
"libc.so.6.1",
|
|
|
|
"libc.so"
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
// try all possibilities
|
|
|
|
while(possibleLibcs.length) {
|
|
|
|
var libc = possibleLibcs.shift();
|
|
|
|
try {
|
|
|
|
var lib = ctypes.open(libc);
|
|
|
|
break;
|
|
|
|
} catch(e) {}
|
|
|
|
}
|
|
|
|
|
|
|
|
// throw appropriate error on failure
|
|
|
|
if(!lib) {
|
|
|
|
throw "libc could not be loaded. Please post on the Zotero Forums so we can add "+
|
|
|
|
"support for your operating system.";
|
|
|
|
}
|
|
|
|
|
|
|
|
// int mkfifo(const char *path, mode_t mode);
|
|
|
|
var mkfifo = lib.declare("mkfifo", ctypes.default_abi, ctypes.int, ctypes.char.ptr, ctypes.unsigned_int);
|
|
|
|
|
|
|
|
// make pipe
|
|
|
|
var ret = mkfifo(_fifoFile.path, 0600);
|
|
|
|
if(!_fifoFile.exists()) return false;
|
|
|
|
lib.close();
|
|
|
|
|
|
|
|
// set up worker
|
|
|
|
var worker = Components.classes["@mozilla.org/threads/workerfactory;1"]
|
|
|
|
.createInstance(Components.interfaces.nsIWorkerFactory)
|
|
|
|
.newChromeWorker("chrome://zotero/content/xpcom/integration_worker.js");
|
|
|
|
worker.onmessage = function(event) {
|
|
|
|
if(event.data[0] == "Exception") {
|
|
|
|
throw event.data[1];
|
|
|
|
} else if(event.data[0] == "Debug") {
|
|
|
|
Zotero.debug(event.data[1]);
|
|
|
|
} else {
|
|
|
|
Zotero.Integration.execCommand(event.data[0], event.data[1], event.data[2]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
worker.postMessage({"path":_fifoFile.path, "libc":libc});
|
2011-03-20 08:58:20 +00:00
|
|
|
}
|
|
|
|
|
2011-03-20 08:12:39 +00:00
|
|
|
return true;
|
2010-12-19 06:26:47 +00:00
|
|
|
}
|
|
|
|
|
2011-03-20 08:12:39 +00:00
|
|
|
Components.utils.reportError("Zotero: mkfifo failed -- not initializing integration pipe");
|
|
|
|
return false;
|
2010-12-19 06:26:47 +00:00
|
|
|
} else {
|
2011-03-20 08:12:39 +00:00
|
|
|
Components.utils.reportError("Zotero: mkfifo or sh not found -- not initializing integration pipe");
|
2010-12-19 06:26:47 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-16 06:22:39 +00:00
|
|
|
/**
|
|
|
|
* Calls the Integration applicatoon
|
|
|
|
*/
|
|
|
|
function _callIntegration(agent, command, docId) {
|
2009-08-25 07:02:24 +00:00
|
|
|
// Try to load the appropriate Zotero component; otherwise display an error using the alert
|
|
|
|
// service
|
|
|
|
try {
|
|
|
|
var componentClass = "@zotero.org/Zotero/integration/application?agent="+agent+";1";
|
2010-10-31 05:19:43 +00:00
|
|
|
Zotero.debug("Integration: Instantiating "+componentClass+" for command "+command+(docId ? " with doc "+docId : ""));
|
2009-08-25 07:02:24 +00:00
|
|
|
var application = Components.classes[componentClass]
|
|
|
|
.getService(Components.interfaces.zoteroIntegrationApplication);
|
|
|
|
} catch(e) {
|
2010-06-17 06:38:03 +00:00
|
|
|
_inProgress = false;
|
2009-08-26 21:24:40 +00:00
|
|
|
Zotero.Integration.activate();
|
2009-08-25 07:02:24 +00:00
|
|
|
Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
|
|
|
.getService(Components.interfaces.nsIPromptService)
|
|
|
|
.alert(null, Zotero.getString("integration.error.title"),
|
|
|
|
Zotero.getString("integration.error.notInstalled"));
|
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
|
2010-12-20 23:50:47 +00:00
|
|
|
// Try to execute the command; otherwise display an error in alert service or word processor
|
|
|
|
// (depending on what is possible)
|
|
|
|
var integration, document;
|
2009-08-20 05:02:55 +00:00
|
|
|
try {
|
2010-12-20 23:50:47 +00:00
|
|
|
document = (application.getDocument && docId ? application.getDocument(docId) : application.getActiveDocument());
|
|
|
|
integration = new Zotero.Integration.Document(application, document);
|
2009-08-20 05:02:55 +00:00
|
|
|
integration[command]();
|
2010-07-06 06:53:45 +00:00
|
|
|
integration.cleanup();
|
2009-08-20 05:02:55 +00:00
|
|
|
} catch(e) {
|
2010-12-20 23:50:47 +00:00
|
|
|
if(integration) {
|
|
|
|
try {
|
|
|
|
integration.cleanup();
|
|
|
|
} catch(e) {
|
|
|
|
Components.utils.reportError(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-21 08:41:07 +00:00
|
|
|
if(!(e instanceof Zotero.Integration.UserCancelledException)) {
|
2010-12-20 23:50:47 +00:00
|
|
|
try {
|
|
|
|
var displayError = null;
|
|
|
|
if(e instanceof Zotero.Integration.DisplayException) {
|
|
|
|
displayError = e.toString();
|
|
|
|
} else {
|
|
|
|
// check to see whether there's a pyxpcom error in the console, since it doesn't
|
|
|
|
// get thrown directly
|
|
|
|
var message = "";
|
|
|
|
|
|
|
|
var consoleService = Components.classes["@mozilla.org/consoleservice;1"]
|
|
|
|
.getService(Components.interfaces.nsIConsoleService);
|
|
|
|
|
|
|
|
var messages = {};
|
|
|
|
consoleService.getMessageArray(messages, {});
|
|
|
|
messages = messages.value;
|
|
|
|
if(messages && messages.length) {
|
|
|
|
var lastMessage = messages[messages.length-1];
|
|
|
|
try {
|
|
|
|
var error = lastMessage.QueryInterface(Components.interfaces.nsIScriptError);
|
|
|
|
} catch(e2) {
|
|
|
|
if(lastMessage.message && lastMessage.message.substr(0, 12) == "ERROR:xpcom:") {
|
|
|
|
// print just the last line of the message, but re-throw the rest
|
|
|
|
message = lastMessage.message.substr(0, lastMessage.message.length-1);
|
|
|
|
message = "\n"+message.substr(message.lastIndexOf("\n"))
|
|
|
|
}
|
2009-09-19 04:17:40 +00:00
|
|
|
}
|
|
|
|
}
|
2010-12-20 23:50:47 +00:00
|
|
|
|
|
|
|
if(!message && typeof(e) == "object" && e.message) message = "\n\n"+e.message;
|
|
|
|
|
|
|
|
if(message != "\n\nExceptionAlreadyDisplayed") {
|
|
|
|
displayError = Zotero.getString("integration.error.generic")+message;
|
|
|
|
}
|
|
|
|
Zotero.debug(e);
|
2009-09-19 04:17:40 +00:00
|
|
|
}
|
|
|
|
|
2010-12-20 23:50:47 +00:00
|
|
|
if(displayError) {
|
|
|
|
if(integration) {
|
|
|
|
integration._doc.displayAlert(displayError,
|
|
|
|
Components.interfaces.zoteroIntegrationDocument.DIALOG_ICON_STOP,
|
|
|
|
Components.interfaces.zoteroIntegrationDocument.DIALOG_BUTTONS_OK);
|
|
|
|
} else {
|
|
|
|
Zotero.Integration.activate();
|
|
|
|
Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
|
|
|
.getService(Components.interfaces.nsIPromptService)
|
|
|
|
.alert(null, Zotero.getString("integration.error.title"), displayError);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} finally {
|
2009-08-25 07:02:24 +00:00
|
|
|
throw e;
|
|
|
|
}
|
2009-08-21 08:41:07 +00:00
|
|
|
}
|
2009-08-20 05:02:55 +00:00
|
|
|
} finally {
|
2010-06-17 06:38:03 +00:00
|
|
|
_inProgress = false;
|
Merged revisions 2710-2712,2714-2716,2718-2728,2730-2731,2734,2736-2738,2740-2750,2752-2753,2755,2758-2768,2770-2779,2782,2789-2790,2794,2797-2802,2804,2808-2810,2812,2814-2824,2826-2832,2834-2835 via svnmerge from 1.0 branch
2008-06-11 08:55:59 +00:00
|
|
|
}
|
|
|
|
}
|
2006-08-28 05:38:37 +00:00
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
/**
|
|
|
|
* Destroys the integration pipe.
|
2006-08-28 05:38:37 +00:00
|
|
|
*/
|
2009-08-20 05:02:55 +00:00
|
|
|
this.destroy = function() {
|
|
|
|
// send shutdown message to fifo thread
|
|
|
|
var oStream = Components.classes["@mozilla.org/network/file-output-stream;1"].
|
|
|
|
getService(Components.interfaces.nsIFileOutputStream);
|
|
|
|
oStream.init(_fifoFile, 0x02 | 0x10, 0, 0);
|
|
|
|
var cmd = "Zotero shutdown\n";
|
|
|
|
oStream.write(cmd, cmd.length);
|
|
|
|
oStream.close();
|
|
|
|
_fifoFile.remove(false);
|
2011-03-26 04:20:22 +00:00
|
|
|
if(_pipeMode === "subprocess") _tmpFile.remove(false);
|
2006-08-28 05:38:37 +00:00
|
|
|
}
|
Merged revisions 2710-2712,2714-2716,2718-2728,2730-2731,2734,2736-2738,2740-2750,2752-2753,2755,2758-2768,2770-2779,2782,2789-2790,2794,2797-2802,2804,2808-2810,2812,2814-2824,2826-2832,2834-2835 via svnmerge from 1.0 branch
2008-06-11 08:55:59 +00:00
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
/**
|
|
|
|
* Activates Firefox
|
|
|
|
*/
|
|
|
|
this.activate = function() {
|
|
|
|
if(Zotero.isMac) {
|
2010-12-19 06:26:47 +00:00
|
|
|
const BUNDLE_IDS = {
|
|
|
|
"Zotero":"org.zotero.zotero",
|
|
|
|
"Firefox":"org.mozilla.firefox",
|
|
|
|
"Minefield":"org.mozilla.minefield"
|
|
|
|
};
|
|
|
|
|
|
|
|
if(Zotero.oscpu == "PPC Mac OS X 10.4" || Zotero.oscpu == "Intel Mac OS X 10.4"
|
|
|
|
|| !BUNDLE_IDS[Zotero.appName]) {
|
2010-06-30 03:24:14 +00:00
|
|
|
// 10.4 doesn't support "tell application id"
|
2010-12-19 06:26:47 +00:00
|
|
|
_executeAppleScript('tell application "'+Zotero.appName+'" to activate');
|
2010-06-30 03:24:14 +00:00
|
|
|
} else {
|
2010-12-19 06:26:47 +00:00
|
|
|
_executeAppleScript('tell application id "'+BUNDLE_IDS[Zotero.appName]+'" to activate');
|
2009-08-20 05:02:55 +00:00
|
|
|
}
|
2011-03-01 06:13:43 +00:00
|
|
|
} else if(Zotero.isWin) {
|
|
|
|
try {
|
|
|
|
if(!_winUser32) {
|
|
|
|
Components.utils.import("resource://gre/modules/ctypes.jsm");
|
|
|
|
var lib = ctypes.open("user32.dll");
|
|
|
|
_winUser32 = new function() {
|
|
|
|
this.FindWindow = lib.declare("FindWindowW", ctypes.default_abi, ctypes.int32_t,
|
|
|
|
ctypes.ustring, ctypes.ustring);
|
|
|
|
this.SetForegroundWindow = lib.declare("SetForegroundWindow", ctypes.default_abi, ctypes.bool,
|
|
|
|
ctypes.int32_t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var thWnd = _winUser32.FindWindow(Zotero.appName+"MessageWindow", null);
|
|
|
|
if(thWnd) _winUser32.SetForegroundWindow(thWnd);
|
|
|
|
} catch(e) {
|
|
|
|
// Don't throw if we don't succeed
|
|
|
|
Components.utils.reportError(e);
|
|
|
|
return;
|
|
|
|
}
|
2009-08-20 05:02:55 +00:00
|
|
|
}
|
Merged revisions 2710-2712,2714-2716,2718-2728,2730-2731,2734,2736-2738,2740-2750,2752-2753,2755,2758-2768,2770-2779,2782,2789-2790,2794,2797-2802,2804,2808-2810,2812,2814-2824,2826-2832,2834-2835 via svnmerge from 1.0 branch
2008-06-11 08:55:59 +00:00
|
|
|
}
|
2010-06-30 03:24:14 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Runs an AppleScript on OS X
|
|
|
|
*
|
|
|
|
* @param script {String}
|
|
|
|
* @param block {Boolean} Whether the script should block until the process is finished.
|
|
|
|
*/
|
|
|
|
function _executeAppleScript(script, block) {
|
|
|
|
if(_osascriptFile === undefined) {
|
|
|
|
_osascriptFile = Components.classes["@mozilla.org/file/local;1"].
|
|
|
|
createInstance(Components.interfaces.nsILocalFile);
|
|
|
|
_osascriptFile.initWithPath("/usr/bin/osascript");
|
|
|
|
if(!_osascriptFile.exists()) _osascriptFile = false;
|
|
|
|
}
|
|
|
|
if(_osascriptFile) {
|
|
|
|
var proc = Components.classes["@mozilla.org/process/util;1"].
|
|
|
|
createInstance(Components.interfaces.nsIProcess);
|
|
|
|
proc.init(_osascriptFile);
|
2010-07-12 10:46:25 +00:00
|
|
|
try {
|
|
|
|
proc.run(!!block, ['-e', script], 2);
|
|
|
|
} catch(e) {}
|
2010-06-30 03:24:14 +00:00
|
|
|
}
|
|
|
|
}
|
2006-08-28 05:38:37 +00:00
|
|
|
}
|
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
/**
|
|
|
|
* An exception thrown when a document contains an item that no longer exists in the current document.
|
|
|
|
*
|
|
|
|
* @param reselectKeys {Array} Keys representing the missing item
|
|
|
|
* @param reselectKeyType {Integer} The type of the keys (see RESELECT_KEY_* constants)
|
|
|
|
* @param citationIndex {Integer} The index of the missing item within the citation cluster
|
|
|
|
* @param citationLength {Integer} The number of items cited in this citation cluster
|
2006-08-28 05:38:37 +00:00
|
|
|
*/
|
2009-08-20 05:02:55 +00:00
|
|
|
Zotero.Integration.MissingItemException = function(reselectKeys, reselectKeyType, citationIndex, citationLength) {
|
|
|
|
this.reselectKeys = reselectKeys;
|
|
|
|
this.reselectKeyType = reselectKeyType;
|
|
|
|
this.citationIndex = citationIndex;
|
|
|
|
this.citationLength = citationLength;
|
|
|
|
}
|
|
|
|
Zotero.Integration.MissingItemException.prototype.name = "MissingItemException";
|
|
|
|
Zotero.Integration.MissingItemException.prototype.message = "An item in this document is missing from your Zotero library.";
|
2009-08-25 07:02:24 +00:00
|
|
|
Zotero.Integration.MissingItemException.prototype.toString = function() { return this.message; };
|
2009-08-21 08:41:07 +00:00
|
|
|
|
|
|
|
Zotero.Integration.UserCancelledException = function() {};
|
|
|
|
Zotero.Integration.UserCancelledException.prototype.name = "UserCancelledException";
|
|
|
|
Zotero.Integration.UserCancelledException.prototype.message = "User cancelled document update.";
|
2009-08-25 07:02:24 +00:00
|
|
|
Zotero.Integration.UserCancelledException.prototype.toString = function() { return this.message; };
|
|
|
|
|
2010-05-30 11:25:25 +00:00
|
|
|
Zotero.Integration.DisplayException = function(name, params) {
|
|
|
|
this.name = name;
|
|
|
|
this.params = params ? params : [];
|
|
|
|
};
|
|
|
|
Zotero.Integration.DisplayException.prototype.toString = function() { return Zotero.getString("integration.error."+this.name, this.params); };
|
2006-08-28 05:38:37 +00:00
|
|
|
|
2009-09-18 17:11:03 +00:00
|
|
|
Zotero.Integration.CorruptFieldException = function(corruptFieldString) {
|
|
|
|
this.corruptFieldString = corruptFieldString;
|
|
|
|
}
|
|
|
|
Zotero.Integration.CorruptFieldException.prototype.name = "CorruptFieldException";
|
|
|
|
Zotero.Integration.CorruptFieldException.prototype.message = "A field code in this document is corrupted.";
|
|
|
|
Zotero.Integration.CorruptFieldException.prototype.toString = function() { return this.message+" "+this.corruptFieldString.toSource(); }
|
2009-08-20 05:02:55 +00:00
|
|
|
|
|
|
|
// Field code for an item
|
2009-08-21 08:41:07 +00:00
|
|
|
const ITEM_CODE = "ITEM";
|
2009-08-20 05:02:55 +00:00
|
|
|
// Field code for a bibliography
|
2009-08-21 08:41:07 +00:00
|
|
|
const BIBLIOGRAPHY_CODE = "BIBL";
|
2009-08-20 05:02:55 +00:00
|
|
|
// Placeholder for an empty bibliography
|
2009-08-21 08:41:07 +00:00
|
|
|
const BIBLIOGRAPHY_PLACEHOLDER = "{Bibliography}";
|
2009-08-20 05:02:55 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
2006-08-28 05:38:37 +00:00
|
|
|
*/
|
2010-06-20 10:48:38 +00:00
|
|
|
Zotero.Integration.Document = function(app, doc) {
|
2009-08-20 05:02:55 +00:00
|
|
|
this._app = app;
|
2010-06-20 10:48:38 +00:00
|
|
|
this._doc = doc;
|
2009-08-20 05:02:55 +00:00
|
|
|
}
|
2006-08-28 05:38:37 +00:00
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
/**
|
|
|
|
* Creates a new session
|
|
|
|
* @param data {Zotero.Integration.DocumentData} Document data for new session
|
2006-08-28 05:38:37 +00:00
|
|
|
*/
|
2009-08-20 05:02:55 +00:00
|
|
|
Zotero.Integration.Document.prototype._createNewSession = function(data) {
|
|
|
|
data.sessionID = Zotero.randomString();
|
|
|
|
var session = Zotero.Integration.sessions[data.sessionID] = new Zotero.Integration.Session();
|
|
|
|
session.setData(data);
|
|
|
|
return session;
|
2006-08-28 05:38:37 +00:00
|
|
|
}
|
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
/**
|
|
|
|
* Gets preferences for a document
|
|
|
|
* @param require {Boolean} Whether an error should be thrown if no preferences exist (otherwise,
|
|
|
|
* the set doc prefs dialog is shown)
|
|
|
|
* @param dontRunSetDocPrefs {Boolean} Whether to show the Set Document Preferences window if no
|
|
|
|
* preferences exist
|
2006-08-28 05:38:37 +00:00
|
|
|
*/
|
2009-08-20 05:02:55 +00:00
|
|
|
Zotero.Integration.Document.prototype._getSession = function(require, dontRunSetDocPrefs) {
|
2009-08-26 18:08:33 +00:00
|
|
|
this._reloadSession = false;
|
2009-08-20 05:02:55 +00:00
|
|
|
var dataString = this._doc.getDocumentData();
|
|
|
|
if(!dataString) {
|
|
|
|
if(require) {
|
2009-08-25 07:02:24 +00:00
|
|
|
throw new Zotero.Integration.DisplayException("mustInsertCitation");
|
2009-08-20 05:02:55 +00:00
|
|
|
} else {
|
|
|
|
// Set doc prefs if no data string yet
|
|
|
|
this._session = this._createNewSession(new Zotero.Integration.DocumentData());
|
|
|
|
if(dontRunSetDocPrefs) return false;
|
2006-08-28 05:38:37 +00:00
|
|
|
|
2009-08-24 03:26:17 +00:00
|
|
|
Zotero.Integration.activate();
|
2009-08-25 07:02:24 +00:00
|
|
|
try {
|
|
|
|
var ret = this._session.setDocPrefs(this._app.primaryFieldType, this._app.secondaryFieldType);
|
|
|
|
} finally {
|
|
|
|
this._doc.activate();
|
|
|
|
}
|
2009-08-20 05:02:55 +00:00
|
|
|
// save doc prefs in doc
|
|
|
|
this._doc.setDocumentData(this._session.data.serializeXML());
|
2006-08-28 05:38:37 +00:00
|
|
|
}
|
2009-08-20 05:02:55 +00:00
|
|
|
} else {
|
2010-05-30 11:25:25 +00:00
|
|
|
var data = new Zotero.Integration.DocumentData(dataString);
|
|
|
|
if(data.dataVersion < DATA_VERSION) {
|
2010-07-06 06:47:59 +00:00
|
|
|
if(data.dataVersion == 1 && data.prefs.fieldType == "Field" && this._app.primaryFieldType == "ReferenceMark") {
|
|
|
|
// Converted OOo docs use ReferenceMarks, not fields
|
|
|
|
data.prefs.fieldType = "ReferenceMark";
|
|
|
|
}
|
|
|
|
|
2009-08-21 08:41:07 +00:00
|
|
|
var warning = this._doc.displayAlert(Zotero.getString("integration.upgradeWarning"),
|
|
|
|
Components.interfaces.zoteroIntegrationDocument.DIALOG_ICON_WARNING,
|
|
|
|
Components.interfaces.zoteroIntegrationDocument.DIALOG_BUTTONS_OK_CANCEL);
|
|
|
|
if(!warning) throw new Zotero.Integration.UserCancelledException();
|
2010-05-30 11:25:25 +00:00
|
|
|
} else if(data.dataVersion > DATA_VERSION) {
|
|
|
|
throw new Zotero.Integration.DisplayException("newerDocumentVersion", [data.zoteroVersion, Zotero.version]);
|
2009-08-21 08:41:07 +00:00
|
|
|
}
|
2009-08-20 05:02:55 +00:00
|
|
|
if(Zotero.Integration.sessions[data.sessionID]) {
|
|
|
|
this._session = Zotero.Integration.sessions[data.sessionID];
|
|
|
|
} else {
|
|
|
|
this._session = this._createNewSession(data);
|
2006-08-28 05:38:37 +00:00
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
// make sure style is defined
|
|
|
|
if(!this._session.style) {
|
2009-08-24 03:26:17 +00:00
|
|
|
Zotero.Integration.activate();
|
2009-08-25 07:02:24 +00:00
|
|
|
try {
|
|
|
|
this._session.setDocPrefs(this._app.primaryFieldType, this._app.secondaryFieldType);
|
|
|
|
} finally {
|
|
|
|
this._doc.activate();
|
|
|
|
}
|
2006-08-28 05:38:37 +00:00
|
|
|
}
|
2009-08-20 05:02:55 +00:00
|
|
|
this._doc.setDocumentData(this._session.data.serializeXML());
|
2009-08-26 18:08:33 +00:00
|
|
|
|
|
|
|
this._reloadSession = true;
|
2006-08-28 05:38:37 +00:00
|
|
|
}
|
|
|
|
}
|
2009-08-20 05:02:55 +00:00
|
|
|
|
2010-10-15 21:32:49 +00:00
|
|
|
this._session.resetRequest(this);
|
2009-08-25 07:02:24 +00:00
|
|
|
return !!dataString;
|
2006-08-28 05:38:37 +00:00
|
|
|
}
|
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
/**
|
|
|
|
* Gets all fields for a document
|
|
|
|
* @param require {Boolean} Whether an error should be thrown if no fields exist
|
2006-08-28 05:38:37 +00:00
|
|
|
*/
|
2009-08-25 07:02:24 +00:00
|
|
|
Zotero.Integration.Document.prototype._getFields = function(require) {
|
|
|
|
if(this._fields) return;
|
|
|
|
if(!this._session && !this._getSession(require, true)) return;
|
2009-08-20 05:02:55 +00:00
|
|
|
|
2009-08-26 21:24:40 +00:00
|
|
|
var getFieldsTime = (new Date()).getTime();
|
2009-08-20 05:02:55 +00:00
|
|
|
var fields = this._doc.getFields(this._session.data.prefs['fieldType']);
|
|
|
|
this._fields = [];
|
|
|
|
while(fields.hasMoreElements()) {
|
|
|
|
this._fields.push(fields.getNext().QueryInterface(Components.interfaces.zoteroIntegrationField));
|
2006-08-28 05:38:37 +00:00
|
|
|
}
|
2010-05-30 11:25:25 +00:00
|
|
|
var endTime = (new Date()).getTime();
|
2009-08-26 21:24:40 +00:00
|
|
|
Zotero.debug("Got "+this._fields.length+" fields in "+(endTime-getFieldsTime)/1000+"; "+1000/((endTime-getFieldsTime)/this._fields.length)+" fields/second");
|
2009-08-20 05:02:55 +00:00
|
|
|
|
|
|
|
if(require && !this._fields.length) {
|
2009-08-25 07:02:24 +00:00
|
|
|
throw new Zotero.Integration.DisplayException("mustInsertCitation");
|
2006-08-28 05:38:37 +00:00
|
|
|
}
|
2009-08-20 05:02:55 +00:00
|
|
|
|
2009-08-25 07:02:24 +00:00
|
|
|
return;
|
2006-08-28 05:38:37 +00:00
|
|
|
}
|
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
/**
|
|
|
|
* Checks that it is appropriate to add fields to the current document at the current
|
|
|
|
* positon, then adds one.
|
2006-08-28 05:38:37 +00:00
|
|
|
*/
|
2009-08-20 05:02:55 +00:00
|
|
|
Zotero.Integration.Document.prototype._addField = function(note) {
|
|
|
|
// Get citation types if necessary
|
|
|
|
if(!this._doc.canInsertField(this._session.data.prefs['fieldType'])) {
|
2009-08-25 07:02:24 +00:00
|
|
|
throw new Zotero.Integration.DisplayException("cannotInsertHere");
|
2009-08-20 05:02:55 +00:00
|
|
|
return false;
|
|
|
|
}
|
2006-08-28 05:38:37 +00:00
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
var field = this._doc.cursorInField(this._session.data.prefs['fieldType']);
|
|
|
|
if(field) {
|
|
|
|
if(!this._doc.displayAlert(Zotero.getString("integration.replace"),
|
|
|
|
Components.interfaces.zoteroIntegrationDocument.DIALOG_ICON_STOP,
|
|
|
|
Components.interfaces.zoteroIntegrationDocument.DIALOG_BUTTONS_OK_CANCEL)) return false;
|
|
|
|
}
|
2007-10-23 07:11:59 +00:00
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
if(!field) {
|
|
|
|
var field = this._doc.insertField(this._session.data.prefs['fieldType'],
|
|
|
|
(note ? this._session.data.prefs["noteType"] : 0));
|
2006-09-06 03:49:41 +00:00
|
|
|
}
|
2009-08-20 05:02:55 +00:00
|
|
|
|
|
|
|
return field;
|
2006-08-28 05:38:37 +00:00
|
|
|
}
|
|
|
|
|
2011-03-23 06:05:34 +00:00
|
|
|
/**
|
|
|
|
* Shows an error if a field code is corrupted
|
|
|
|
* @param {Exception} e The exception thrown
|
|
|
|
* @param {Field} field The Zotero field object
|
|
|
|
* @param {Integer} i The field index
|
|
|
|
*/
|
|
|
|
Zotero.Integration.Document.prototype._showCorruptFieldError = function(e, field, i) {
|
|
|
|
var msg = Zotero.getString("integration.corruptField")+'\n\n'+
|
|
|
|
Zotero.getString('integration.corruptField.description');
|
|
|
|
field.select();
|
|
|
|
var result = this._doc.displayAlert(msg,
|
|
|
|
Components.interfaces.zoteroIntegrationDocument.DIALOG_ICON_CAUTION,
|
|
|
|
Components.interfaces.zoteroIntegrationDocument.DIALOG_BUTTONS_YES_NO_CANCEL);
|
|
|
|
|
|
|
|
if(result == 0) {
|
|
|
|
throw e;
|
|
|
|
} else if(result == 1) { // No
|
|
|
|
this._removeCodeFields.push(i);
|
|
|
|
} else {
|
|
|
|
// Display reselect edit citation dialog
|
|
|
|
var added = this._session.editCitation(i, field.getNoteIndex());
|
|
|
|
if(added) {
|
|
|
|
this._doc.activate();
|
|
|
|
} else {
|
|
|
|
throw new Zotero.Integration.UserCancelledException();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
/**
|
|
|
|
* Loads existing citations and bibliographies out of a document, and creates or edits fields
|
|
|
|
*/
|
2009-08-31 04:50:22 +00:00
|
|
|
Zotero.Integration.Document.prototype._updateSession = function(newField, editField) {
|
2009-08-20 05:02:55 +00:00
|
|
|
var deleteKeys = {};
|
|
|
|
this._deleteFields = [];
|
|
|
|
this._removeCodeFields = [];
|
|
|
|
this._bibliographyFields = [];
|
|
|
|
var bibliographyData = "";
|
|
|
|
|
|
|
|
// first collect entire bibliography
|
|
|
|
this._getFields();
|
|
|
|
var editFieldIndex = false;
|
2009-08-31 04:50:22 +00:00
|
|
|
var collectFieldsTime = (new Date()).getTime();
|
2009-08-20 05:02:55 +00:00
|
|
|
for(var i in this._fields) {
|
|
|
|
var field = this._fields[i];
|
|
|
|
|
|
|
|
if(editField && field.equals(editField)) {
|
|
|
|
editFieldIndex = i;
|
2008-09-23 23:11:27 +00:00
|
|
|
} else {
|
2011-03-23 06:05:34 +00:00
|
|
|
try {
|
|
|
|
var fieldCode = field.getCode();
|
|
|
|
} catch(e) {
|
|
|
|
this._showCorruptFieldError(e, field, i);
|
|
|
|
}
|
2009-08-20 05:02:55 +00:00
|
|
|
|
|
|
|
if(fieldCode.substr(0, ITEM_CODE.length) == ITEM_CODE) {
|
2010-05-30 11:25:25 +00:00
|
|
|
var noteIndex = (this._session.styleClass == "note" ? field.getNoteIndex() : 0);
|
2009-08-20 05:02:55 +00:00
|
|
|
try {
|
2009-08-31 04:50:22 +00:00
|
|
|
this._session.addCitation(i, noteIndex, fieldCode.substr(ITEM_CODE.length+1));
|
2009-08-20 05:02:55 +00:00
|
|
|
} catch(e) {
|
|
|
|
if(e instanceof Zotero.Integration.MissingItemException) {
|
|
|
|
// First, check if we've already decided to remove field codes from these
|
|
|
|
var reselect = true;
|
|
|
|
for each(var reselectKey in e.reselectKeys) {
|
|
|
|
if(deleteKeys[reselectKey]) {
|
|
|
|
this._removeCodeFields.push(i);
|
|
|
|
reselect = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(reselect) {
|
|
|
|
// Ask user what to do with this item
|
|
|
|
if(e.citationLength == 1) {
|
|
|
|
var msg = Zotero.getString("integration.missingItem.single");
|
|
|
|
} else {
|
2009-09-21 07:18:25 +00:00
|
|
|
var msg = Zotero.getString("integration.missingItem.multiple", (e.citationIndex+1).toString());
|
2009-08-20 05:02:55 +00:00
|
|
|
}
|
|
|
|
msg += '\n\n'+Zotero.getString('integration.missingItem.description');
|
|
|
|
field.select();
|
|
|
|
var result = this._doc.displayAlert(msg, 1, 3);
|
|
|
|
if(result == 0) { // Cancel
|
2009-08-21 08:41:07 +00:00
|
|
|
throw new Zotero.Integration.UserCancelledException();
|
2009-08-20 05:02:55 +00:00
|
|
|
} else if(result == 1) { // No
|
|
|
|
for each(var reselectKey in e.reselectKeys) {
|
|
|
|
deleteKeys[reselectKey] = true;
|
|
|
|
}
|
|
|
|
this._removeCodeFields.push(i);
|
|
|
|
} else { // Yes
|
|
|
|
// Display reselect item dialog
|
|
|
|
Zotero.Integration.activate();
|
|
|
|
this._session.reselectItem(e);
|
|
|
|
// Now try again
|
2009-08-24 02:05:18 +00:00
|
|
|
this._session.addCitation(i, field.getNoteIndex(), fieldCode.substr(ITEM_CODE.length+1));
|
2009-08-20 05:02:55 +00:00
|
|
|
this._doc.activate();
|
|
|
|
}
|
|
|
|
}
|
2009-09-18 17:11:03 +00:00
|
|
|
} else if(e instanceof Zotero.Integration.CorruptFieldException) {
|
2011-03-23 06:05:34 +00:00
|
|
|
this._showCorruptFieldError(e, field, i);
|
2009-08-20 05:02:55 +00:00
|
|
|
} else {
|
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if(fieldCode.substr(0, BIBLIOGRAPHY_CODE.length) == BIBLIOGRAPHY_CODE) {
|
|
|
|
this._bibliographyFields.push(field);
|
|
|
|
if(!this._session.bibliographyData && !bibliographyData) {
|
2009-08-31 04:50:22 +00:00
|
|
|
bibliographyData = fieldCode.substr(BIBLIOGRAPHY_CODE.length+1);
|
|
|
|
}
|
|
|
|
} else if(fieldCode == "TEMP") {
|
|
|
|
if(newField) {
|
|
|
|
editFieldIndex = i;
|
|
|
|
editField = field;
|
|
|
|
} else {
|
|
|
|
this._deleteFields.push(i);
|
2009-08-20 05:02:55 +00:00
|
|
|
}
|
|
|
|
}
|
2008-07-10 11:05:43 +00:00
|
|
|
}
|
2009-08-20 05:02:55 +00:00
|
|
|
}
|
2009-08-31 04:50:22 +00:00
|
|
|
var endTime = (new Date()).getTime();
|
|
|
|
Zotero.debug("Collected "+this._fields.length+" fields in "+(endTime-collectFieldsTime)/1000+"; "+1000/((endTime-collectFieldsTime)/this._fields.length)+" fields/second");
|
2009-09-18 17:11:03 +00:00
|
|
|
|
|
|
|
// load uncited items from bibliography
|
|
|
|
if(bibliographyData && !this._session.bibliographyData) {
|
|
|
|
try {
|
|
|
|
this._session.loadBibliographyData(bibliographyData);
|
|
|
|
} catch(e) {
|
|
|
|
if(e instanceof Zotero.Integration.CorruptFieldException) {
|
|
|
|
var msg = Zotero.getString("integration.corruptBibliography")+'\n\n'+
|
|
|
|
Zotero.getString('integration.corruptBibliography.description');
|
|
|
|
var result = this._doc.displayAlert(msg,
|
|
|
|
Components.interfaces.zoteroIntegrationDocument.DIALOG_ICON_CAUTION,
|
|
|
|
Components.interfaces.zoteroIntegrationDocument.DIALOG_BUTTONS_OK_CANCEL);
|
|
|
|
if(result == 0) {
|
|
|
|
throw e;
|
|
|
|
} else {
|
|
|
|
bibliographyData = "";
|
|
|
|
this._session.bibliographyHasChanged = true;
|
|
|
|
this._session.bibliographyDataHasChanged = true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-05 17:49:04 +00:00
|
|
|
// if we are reloading this session, assume no item IDs to be updated except for edited items
|
|
|
|
if(this._reloadSession) {
|
2010-06-28 02:38:48 +00:00
|
|
|
//this._session.restoreProcessorState(); TODO doesn't appear to be working properly
|
|
|
|
this._session.updateUpdateIndices();
|
|
|
|
var deleteCitations = this._session.updateCitations();
|
|
|
|
this._deleteFields = this._deleteFields.concat([i for(i in deleteCitations)]);
|
2010-06-05 17:49:04 +00:00
|
|
|
this._session.updateIndices = {};
|
|
|
|
this._session.updateItemIDs = {};
|
|
|
|
this._session.bibliographyHasChanged = false;
|
|
|
|
}
|
2009-08-26 18:08:33 +00:00
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
// create new citation or edit existing citation
|
|
|
|
if(editFieldIndex) {
|
|
|
|
var editFieldCode = editField.getCode().substr(ITEM_CODE.length+1);
|
|
|
|
var editCitation = editFieldCode ? this._session.unserializeCitation(editFieldCode, editFieldIndex) : null;
|
2008-07-10 11:05:43 +00:00
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
Zotero.Integration.activate();
|
2009-08-24 02:05:18 +00:00
|
|
|
var editNoteIndex = editField.getNoteIndex();
|
|
|
|
var added = this._session.editCitation(editFieldIndex, editNoteIndex, editCitation);
|
2009-08-20 05:02:55 +00:00
|
|
|
this._doc.activate();
|
2008-07-10 11:05:43 +00:00
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
if(!added) {
|
|
|
|
if(editFieldCode) { // cancelled editing; just add as if nothing happened
|
2009-08-24 02:05:18 +00:00
|
|
|
this._session.addCitation(editFieldIndex, editNoteIndex, editCitation);
|
2009-08-20 05:02:55 +00:00
|
|
|
} else { // cancelled creation; delete the citation
|
|
|
|
this._session.deleteCitation(editFieldIndex);
|
|
|
|
}
|
|
|
|
}
|
2008-07-10 11:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2009-08-20 05:02:55 +00:00
|
|
|
* Updates bibliographies and fields within a document
|
|
|
|
*/
|
|
|
|
Zotero.Integration.Document.prototype._updateDocument = function(forceCitations, forceBibliography) {
|
|
|
|
// update citations
|
2010-08-16 08:52:13 +00:00
|
|
|
this._session.updateUpdateIndices(forceCitations);
|
2010-06-06 00:01:11 +00:00
|
|
|
var deleteCitations = this._session.updateCitations();
|
|
|
|
this._deleteFields = this._deleteFields.concat([i for(i in deleteCitations)]);
|
|
|
|
for(var i in this._session.updateIndices) {
|
2009-08-20 05:02:55 +00:00
|
|
|
citation = this._session.citationsByIndex[i];
|
2010-06-06 00:01:11 +00:00
|
|
|
if(!citation || deleteCitations[i]) continue;
|
2008-07-10 11:05:43 +00:00
|
|
|
|
2010-05-30 11:25:25 +00:00
|
|
|
var fieldCode = this._session.getCitationField(citation);
|
|
|
|
if(fieldCode != citation.properties.field) {
|
|
|
|
this._fields[citation.properties.index].setCode(ITEM_CODE+" "+fieldCode);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(citation.properties.custom) {
|
|
|
|
var citationText = citation.properties.custom;
|
2009-08-22 01:23:25 +00:00
|
|
|
} else {
|
2010-05-30 11:25:25 +00:00
|
|
|
var citationText = this._session.citationText[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
if(citationText.indexOf("\\") !== -1) {
|
|
|
|
// need to set text as RTF
|
|
|
|
this._fields[citation.properties.index].setText("{\\rtf "+citationText+"}", true);
|
|
|
|
} else {
|
|
|
|
// set text as plain
|
|
|
|
this._fields[citation.properties.index].setText(citationText, false);
|
2008-07-10 11:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-30 19:06:41 +00:00
|
|
|
// update bibliographies
|
|
|
|
if(this._bibliographyFields.length // if blbliography exists
|
|
|
|
&& (this._session.bibliographyHasChanged // and bibliography changed
|
|
|
|
|| forceBibliography)) { // or if we should generate regardless of changes
|
2010-06-28 02:38:48 +00:00
|
|
|
if(forceBibliography || this._session.bibliographyDataHasChanged) {
|
2010-05-30 19:06:41 +00:00
|
|
|
var bibliographyData = this._session.getBibliographyData();
|
|
|
|
for each(var field in this._bibliographyFields) {
|
|
|
|
field.setCode(BIBLIOGRAPHY_CODE+" "+bibliographyData);
|
|
|
|
}
|
|
|
|
}
|
2010-07-06 06:47:59 +00:00
|
|
|
|
|
|
|
// get bibliography and format as RTF
|
|
|
|
var bib = this._session.getBibliography();
|
|
|
|
|
2010-08-16 08:07:07 +00:00
|
|
|
var bibliographyText = "";
|
|
|
|
if(bib) {
|
|
|
|
bibliographyText = bib[0].bibstart+bib[1].join("\\\r\n")+"\\\r\n"+bib[0].bibend;
|
2010-07-06 06:47:59 +00:00
|
|
|
|
2010-08-16 08:07:07 +00:00
|
|
|
// if bibliography style not set, set it
|
2010-09-27 17:12:41 +00:00
|
|
|
if(!this._session.data.style.bibliographyStyleHasBeenSet) {
|
2010-08-16 08:07:07 +00:00
|
|
|
var bibStyle = Zotero.Cite.getBibliographyFormatParameters(bib);
|
|
|
|
|
|
|
|
// set bibliography style
|
|
|
|
this._doc.setBibliographyStyle(bibStyle.firstLineIndent, bibStyle.indent,
|
|
|
|
bibStyle.lineSpacing, bibStyle.entrySpacing, bibStyle.tabStops, bibStyle.tabStops.length);
|
|
|
|
|
|
|
|
// set bibliographyStyleHasBeenSet parameter to prevent further changes
|
2010-09-27 17:12:41 +00:00
|
|
|
this._session.data.style.bibliographyStyleHasBeenSet = true;
|
2010-08-16 08:07:07 +00:00
|
|
|
this._doc.setDocumentData(this._session.data.serializeXML());
|
|
|
|
}
|
2010-07-06 06:47:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// set bibliography text
|
2010-05-30 19:06:41 +00:00
|
|
|
for each(var field in this._bibliographyFields) {
|
|
|
|
if(bibliographyText) {
|
|
|
|
field.setText(bibliographyText, true);
|
|
|
|
} else {
|
|
|
|
field.setText("{Bibliography}", false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
// do this operations in reverse in case plug-ins care about order
|
2009-08-31 04:50:22 +00:00
|
|
|
this._deleteFields.sort();
|
2009-08-20 05:02:55 +00:00
|
|
|
for(var i=(this._deleteFields.length-1); i>=0; i--) {
|
|
|
|
this._fields[this._deleteFields[i]].delete();
|
|
|
|
}
|
2009-08-31 04:50:22 +00:00
|
|
|
this._removeCodeFields.sort();
|
2009-08-20 05:02:55 +00:00
|
|
|
for(var i=(this._removeCodeFields.length-1); i>=0; i--) {
|
|
|
|
this._fields[this._removeCodeFields[i]].removeCode();
|
|
|
|
}
|
2008-07-10 11:05:43 +00:00
|
|
|
}
|
2009-08-20 05:02:55 +00:00
|
|
|
|
2008-07-10 11:05:43 +00:00
|
|
|
/**
|
2009-08-20 05:02:55 +00:00
|
|
|
* Adds a citation to the current document.
|
|
|
|
*/
|
|
|
|
Zotero.Integration.Document.prototype.addCitation = function() {
|
2009-08-25 07:02:24 +00:00
|
|
|
this._getSession();
|
2008-07-10 11:05:43 +00:00
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
var field = this._addField(true);
|
|
|
|
if(!field) return;
|
2009-09-18 17:11:03 +00:00
|
|
|
field.setCode("TEMP");
|
2008-07-10 11:05:43 +00:00
|
|
|
|
2009-08-31 04:50:22 +00:00
|
|
|
this._updateSession(true);
|
2009-08-20 05:02:55 +00:00
|
|
|
this._updateDocument();
|
|
|
|
}
|
2008-07-10 11:05:43 +00:00
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
/**
|
|
|
|
* Edits the citation at the cursor position.
|
|
|
|
*/
|
|
|
|
Zotero.Integration.Document.prototype.editCitation = function() {
|
2009-08-25 07:02:24 +00:00
|
|
|
this._getSession(true);
|
2009-08-20 05:02:55 +00:00
|
|
|
|
|
|
|
var field = this._doc.cursorInField(this._session.data.prefs['fieldType'])
|
|
|
|
if(!field) {
|
2009-08-25 07:02:24 +00:00
|
|
|
throw new Zotero.Integration.DisplayException("notInCitation");
|
2008-07-10 11:05:43 +00:00
|
|
|
}
|
2009-08-20 05:02:55 +00:00
|
|
|
|
2009-08-31 04:50:22 +00:00
|
|
|
this._updateSession(false, field);
|
2009-08-20 05:02:55 +00:00
|
|
|
this._updateDocument(false, false);
|
2008-07-10 11:05:43 +00:00
|
|
|
}
|
|
|
|
|
2008-09-23 23:11:27 +00:00
|
|
|
/**
|
2009-08-20 05:02:55 +00:00
|
|
|
* Adds a bibliography to the current document.
|
|
|
|
*/
|
|
|
|
Zotero.Integration.Document.prototype.addBibliography = function() {
|
2009-08-25 07:02:24 +00:00
|
|
|
this._getSession(true);
|
2009-08-20 05:02:55 +00:00
|
|
|
|
|
|
|
// Make sure we can have a bibliography
|
2010-05-30 11:25:25 +00:00
|
|
|
if(!this._session.data.style.hasBibliography) {
|
2009-08-25 07:02:24 +00:00
|
|
|
throw new Zotero.Integration.DisplayException("noBibliography");
|
2009-08-20 05:02:55 +00:00
|
|
|
}
|
2008-09-23 23:11:27 +00:00
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
// Make sure we have some citations
|
2009-08-25 07:02:24 +00:00
|
|
|
this._getFields(true);
|
2008-09-23 23:11:27 +00:00
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
var field = this._addField();
|
|
|
|
if(!field) return;
|
|
|
|
var bibliographyData = this._session.getBibliographyData();
|
|
|
|
field.setCode(BIBLIOGRAPHY_CODE+" "+bibliographyData);
|
|
|
|
this._fields.push(field);
|
2008-09-23 23:11:27 +00:00
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
this._updateSession();
|
|
|
|
this._updateDocument(false, true);
|
2008-09-23 23:11:27 +00:00
|
|
|
}
|
|
|
|
|
2008-07-10 11:05:43 +00:00
|
|
|
/**
|
2009-08-20 05:02:55 +00:00
|
|
|
* Edits bibliography metadata.
|
|
|
|
*/
|
|
|
|
Zotero.Integration.Document.prototype.editBibliography = function() {
|
|
|
|
// Make sure we have a bibliography
|
2009-08-25 07:02:24 +00:00
|
|
|
this._getFields(true);
|
2009-08-20 05:02:55 +00:00
|
|
|
var haveBibliography = false;
|
2009-08-22 16:52:35 +00:00
|
|
|
for(var i=this._fields.length-1; i>=0; i--) {
|
2009-08-20 05:02:55 +00:00
|
|
|
if(this._fields[i].getCode().substr(0, BIBLIOGRAPHY_CODE.length) == BIBLIOGRAPHY_CODE) {
|
|
|
|
haveBibliography = true;
|
|
|
|
break;
|
2008-07-10 11:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
if(!haveBibliography) {
|
2009-08-25 07:02:24 +00:00
|
|
|
throw new Zotero.Integration.DisplayException("mustInsertBibliography");
|
2008-07-10 11:05:43 +00:00
|
|
|
}
|
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
this._updateSession();
|
|
|
|
Zotero.Integration.activate();
|
|
|
|
this._session.editBibliography();
|
|
|
|
this._doc.activate();
|
|
|
|
this._updateDocument(false, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Updates the citation data for all citations and bibliography entries.
|
|
|
|
*/
|
|
|
|
Zotero.Integration.Document.prototype.refresh = function() {
|
2009-08-25 07:02:24 +00:00
|
|
|
this._getFields(true);
|
2008-07-10 11:05:43 +00:00
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
// Send request, forcing update of citations and bibliography
|
|
|
|
this._updateSession();
|
|
|
|
this._updateDocument(true, true);
|
2008-07-10 11:05:43 +00:00
|
|
|
}
|
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
/**
|
|
|
|
* Deletes field codes.
|
|
|
|
*/
|
|
|
|
Zotero.Integration.Document.prototype.removeCodes = function() {
|
2009-08-25 07:02:24 +00:00
|
|
|
this._getFields(true);
|
2009-08-20 05:02:55 +00:00
|
|
|
|
|
|
|
var result = this._doc.displayAlert(Zotero.getString("integration.removeCodesWarning"),
|
|
|
|
Components.interfaces.zoteroIntegrationDocument.DIALOG_ICON_WARNING,
|
|
|
|
Components.interfaces.zoteroIntegrationDocument.DIALOG_BUTTONS_OK_CANCEL);
|
|
|
|
if(result) {
|
|
|
|
for(var i=this._fields.length-1; i>=0; i--) {
|
|
|
|
this._fields[i].removeCode();
|
2007-10-23 07:11:59 +00:00
|
|
|
}
|
2009-08-20 05:02:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Displays a dialog to set document preferences (style, footnotes/endnotes, etc.)
|
|
|
|
*/
|
|
|
|
Zotero.Integration.Document.prototype.setDocPrefs = function() {
|
2009-08-25 07:02:24 +00:00
|
|
|
this._getFields();
|
|
|
|
|
2009-08-24 03:26:17 +00:00
|
|
|
Zotero.Integration.activate();
|
2009-08-25 07:02:24 +00:00
|
|
|
try {
|
|
|
|
var oldData = this._session.setDocPrefs(this._app.primaryFieldType, this._app.secondaryFieldType);
|
|
|
|
} finally {
|
|
|
|
this._doc.activate();
|
|
|
|
}
|
2009-08-20 05:02:55 +00:00
|
|
|
if(oldData) {
|
|
|
|
this._doc.setDocumentData(this._session.data.serializeXML());
|
|
|
|
if(this._fields && this._fields.length) {
|
|
|
|
// if there are fields, we will have to convert some things; get a list of what we need to deal with
|
|
|
|
var convertBibliographies = oldData === true || oldData.prefs.fieldType != this._session.data.prefs.fieldType;
|
|
|
|
var convertItems = convertBibliographies || oldData.prefs.noteType != this._session.data.prefs.noteType;
|
|
|
|
var fieldsToConvert = new Array();
|
|
|
|
var fieldNoteTypes = new Array();
|
|
|
|
for each(var field in this._fields) {
|
|
|
|
var fieldCode = field.getCode();
|
|
|
|
|
|
|
|
if(convertItems && fieldCode.substr(0, ITEM_CODE.length) == ITEM_CODE) {
|
|
|
|
fieldsToConvert.push(field);
|
|
|
|
fieldNoteTypes.push(this._session.data.prefs.noteType);
|
|
|
|
} else if(convertBibliographies && fieldCode.substr(0, BIBLIOGRAPHY_CODE.length) == BIBLIOGRAPHY_CODE) {
|
|
|
|
fieldsToConvert.push(field);
|
|
|
|
fieldNoteTypes.push(0);
|
2006-09-10 17:38:17 +00:00
|
|
|
}
|
2006-09-04 04:13:12 +00:00
|
|
|
}
|
2009-08-20 05:02:55 +00:00
|
|
|
|
|
|
|
if(fieldsToConvert.length) {
|
|
|
|
// pass to conversion function
|
|
|
|
this._doc.convert(new Zotero.Integration.Document.JSEnumerator(fieldsToConvert),
|
|
|
|
this._session.data.prefs.fieldType, fieldNoteTypes, fieldNoteTypes.length);
|
|
|
|
|
|
|
|
// clear fields so that they will get collected again before refresh
|
|
|
|
this._fields = undefined;
|
2006-08-29 04:24:11 +00:00
|
|
|
}
|
2007-10-23 07:11:59 +00:00
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
// refresh contents
|
|
|
|
this.refresh();
|
2007-10-23 07:11:59 +00:00
|
|
|
}
|
2006-08-28 05:38:37 +00:00
|
|
|
}
|
2009-08-20 05:02:55 +00:00
|
|
|
}
|
Merged revisions 1986,1988-1990,1996,1998,2000-2004,2006,2008-2010,2013,2020-2028,2032-2034,2037,2039,2044-2049,2052-2056,2059,2065-2066,2068-2072,2075,2077-2079,2081,2083-2084,2086,2088-2094,2096,2099,2101,2103-2104,2107-2110,2115,2118,2120-2122,2126-2128,2131,2140,2142-2145,2149-2153,2155-2159,2165,2167-2168,2170-2171,2173-2176,2179-2183,2185-2186 via svnmerge from
https://www.zotero.org/svn/extension/branches/1.0
2008-01-30 09:53:19 +00:00
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
/**
|
|
|
|
* Cleans up any changes made before returning, even if an error occurred
|
|
|
|
*/
|
|
|
|
Zotero.Integration.Document.prototype.cleanup = function() {
|
|
|
|
this._doc.cleanup()
|
2006-09-10 17:38:17 +00:00
|
|
|
}
|
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
/**
|
|
|
|
* An exceedingly simple nsISimpleEnumerator implementation
|
|
|
|
*/
|
|
|
|
Zotero.Integration.Document.JSEnumerator = function(objArray) {
|
|
|
|
this.objArray = objArray;
|
|
|
|
}
|
|
|
|
Zotero.Integration.Document.JSEnumerator.prototype.hasMoreElements = function() {
|
|
|
|
return this.objArray.length;
|
|
|
|
}
|
|
|
|
Zotero.Integration.Document.JSEnumerator.prototype.getNext = function() {
|
|
|
|
return this.objArray.shift();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Keeps track of all session-specific variables
|
2007-10-23 07:11:59 +00:00
|
|
|
*/
|
|
|
|
Zotero.Integration.Session = function() {
|
|
|
|
// holds items not in document that should be in bibliography
|
|
|
|
this.uncitedItems = new Object();
|
2010-06-28 02:38:48 +00:00
|
|
|
this.omittedItems = new Object();
|
2010-05-30 11:25:25 +00:00
|
|
|
this.customBibliographyText = new Object();
|
2009-08-20 05:02:55 +00:00
|
|
|
this.reselectedItems = new Object();
|
2010-05-30 11:25:25 +00:00
|
|
|
this.citationIDs = new Object();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Resets per-request variables in the CitationSet
|
|
|
|
*/
|
2010-10-15 21:32:49 +00:00
|
|
|
Zotero.Integration.Session.prototype.resetRequest = function(doc) {
|
2010-05-30 11:25:25 +00:00
|
|
|
this.citationsByItemID = new Object();
|
|
|
|
this.citationsByIndex = new Array();
|
|
|
|
this.uriMap = new Zotero.Integration.URIMap(this);
|
|
|
|
|
|
|
|
this.regenerateAll = false;
|
|
|
|
this.bibliographyHasChanged = false;
|
|
|
|
this.bibliographyDataHasChanged = false;
|
|
|
|
this.updateItemIDs = new Object();
|
|
|
|
this.updateIndices = new Object();
|
|
|
|
this.newIndices = new Object();
|
|
|
|
|
|
|
|
this.oldCitationIDs = this.citationIDs;
|
|
|
|
this.citationIDs = new Object();
|
|
|
|
this.citationText = new Object();
|
2010-10-15 21:32:49 +00:00
|
|
|
|
|
|
|
this.doc = doc;
|
2006-09-10 17:38:17 +00:00
|
|
|
}
|
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
/**
|
|
|
|
* Changes the Session style and data
|
|
|
|
* @param data {Zotero.Integration.DocumentData}
|
2007-10-23 07:11:59 +00:00
|
|
|
*/
|
2009-08-20 05:02:55 +00:00
|
|
|
Zotero.Integration.Session.prototype.setData = function(data) {
|
|
|
|
var oldStyleID = (this.data && this.data.style.styleID ? this.data.style.styleID : false);
|
|
|
|
this.data = data;
|
|
|
|
if(data.style.styleID && oldStyleID != data.style.styleID) {
|
|
|
|
this.styleID = data.style.styleID;
|
2008-07-10 11:05:43 +00:00
|
|
|
try {
|
2010-05-30 11:25:25 +00:00
|
|
|
var getStyle = Zotero.Styles.get(data.style.styleID);
|
|
|
|
data.style.hasBibliography = getStyle.hasBibliography;
|
|
|
|
this.style = getStyle.csl;
|
|
|
|
this.style.setOutputFormat("rtf");
|
|
|
|
this.styleClass = getStyle.class;
|
2008-07-10 11:05:43 +00:00
|
|
|
this.dateModified = new Object();
|
|
|
|
} catch(e) {
|
|
|
|
Zotero.debug(e)
|
2009-08-20 05:02:55 +00:00
|
|
|
data.style.styleID = undefined;
|
2008-07-10 11:05:43 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2006-09-10 17:38:17 +00:00
|
|
|
}
|
|
|
|
|
2010-10-15 21:32:49 +00:00
|
|
|
/**
|
|
|
|
* Displays a dialog in a modal-like fashion without hanging the thread
|
|
|
|
*/
|
|
|
|
Zotero.Integration.Session.prototype._displayDialog = function(url, options, io) {
|
|
|
|
if(this.doc) this.doc.cleanup();
|
|
|
|
var window = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
|
|
|
|
.getService(Components.interfaces.nsIWindowWatcher)
|
2011-02-07 05:30:28 +00:00
|
|
|
.openWindow(null, url, '', 'chrome,centerscreen'+(options ? ','+options : ""), (io ? io : null));
|
2010-10-15 21:32:49 +00:00
|
|
|
while(!window.closed) Zotero.mainThread.processNextEvent(true);
|
|
|
|
}
|
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
/**
|
|
|
|
* Displays a dialog to set document preferences
|
|
|
|
*/
|
|
|
|
Zotero.Integration.Session.prototype.setDocPrefs = function(primaryFieldType, secondaryFieldType) {
|
|
|
|
var io = new function() {
|
|
|
|
this.wrappedJSObject = this;
|
|
|
|
};
|
|
|
|
|
|
|
|
if(this.data) {
|
|
|
|
io.style = this.data.style.styleID;
|
|
|
|
io.useEndnotes = this.data.prefs.noteType == 0 ? 0 : this.data.prefs.noteType-1;
|
|
|
|
io.fieldType = this.data.prefs.fieldType;
|
|
|
|
io.primaryFieldType = primaryFieldType;
|
|
|
|
io.secondaryFieldType = secondaryFieldType;
|
|
|
|
}
|
|
|
|
|
2010-10-15 21:32:49 +00:00
|
|
|
this._displayDialog('chrome://zotero/content/integration/integrationDocPrefs.xul', '', io);
|
2009-08-25 07:02:24 +00:00
|
|
|
if(!io.style) throw new Zotero.Integration.UserCancelledException();
|
2009-08-20 05:02:55 +00:00
|
|
|
|
|
|
|
// set data
|
|
|
|
var oldData = this.data;
|
|
|
|
var data = new Zotero.Integration.DocumentData();
|
|
|
|
data.sessionID = oldData.sessionID;
|
|
|
|
data.style.styleID = io.style;
|
|
|
|
data.prefs.fieldType = io.fieldType;
|
|
|
|
this.setData(data);
|
|
|
|
// need to do this after setting the data so that we know if it's a note style
|
2010-05-30 11:25:25 +00:00
|
|
|
this.data.prefs.noteType = this.style && this.styleClass == "note" ? io.useEndnotes+1 : 0;
|
2009-08-20 05:02:55 +00:00
|
|
|
|
|
|
|
if(!oldData || oldData.style.styleID != data.style.styleID
|
|
|
|
|| oldData.prefs.noteType != data.prefs.noteType
|
|
|
|
|| oldData.prefs.fieldType != data.prefs.fieldType) {
|
2010-05-30 19:06:41 +00:00
|
|
|
this.oldCitationIDs = {};
|
2009-08-20 05:02:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return oldData ? oldData : true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reselects an item to replace a deleted item
|
|
|
|
* @param exception {Zotero.Integration.MissingItemException}
|
|
|
|
*/
|
|
|
|
Zotero.Integration.Session.prototype.reselectItem = function(exception) {
|
|
|
|
var io = new function() {
|
|
|
|
this.wrappedJSObject = this;
|
|
|
|
};
|
|
|
|
io.addBorder = Zotero.isWin;
|
|
|
|
io.singleSelection = true;
|
|
|
|
|
2010-10-15 21:32:49 +00:00
|
|
|
this._displayDialog('chrome://zotero/content/selectItemsDialog.xul', 'resizable', io);
|
2009-08-20 05:02:55 +00:00
|
|
|
|
|
|
|
if(io.dataOut && io.dataOut.length) {
|
|
|
|
var itemID = io.dataOut[0];
|
|
|
|
|
|
|
|
// add reselected item IDs to hash, so they can be used
|
|
|
|
for each(var reselectKey in exception.reselectKeys) {
|
|
|
|
this.reselectedItems[reselectKey] = itemID;
|
|
|
|
}
|
|
|
|
// add old URIs to map, so that they will be included
|
|
|
|
if(exception.reselectKeyType == RESELECT_KEY_URI) {
|
|
|
|
this.uriMap.add(itemID, exception.reselectKeys.concat(this.uriMap.getURIsForItemID(itemID)));
|
|
|
|
}
|
|
|
|
// flag for update
|
|
|
|
this.updateItemIDs[itemID] = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates a field from a citation object
|
2007-10-23 07:11:59 +00:00
|
|
|
*/
|
|
|
|
Zotero.Integration.Session.prototype.getCitationField = function(citation) {
|
2010-08-16 08:46:07 +00:00
|
|
|
const saveProperties = ["custom", "unsorted"];
|
|
|
|
const saveCitationItems = ["locator", "label", "suppress-author", "author-only", "prefix", "suffix", "uri"];
|
|
|
|
|
2010-05-30 11:25:25 +00:00
|
|
|
var type;
|
|
|
|
var field = [];
|
2007-10-23 07:11:59 +00:00
|
|
|
|
2010-06-05 17:49:04 +00:00
|
|
|
field.push('"citationID":'+uneval(citation.citationID));
|
2010-08-16 08:46:07 +00:00
|
|
|
|
|
|
|
var properties = JSON.stringify(citation.properties, saveProperties);
|
|
|
|
if(properties != "{}") {
|
2010-11-04 17:09:09 +00:00
|
|
|
field.push('"properties":'+properties);
|
2007-10-23 07:11:59 +00:00
|
|
|
}
|
2010-08-16 08:46:07 +00:00
|
|
|
|
2010-05-30 11:25:25 +00:00
|
|
|
var citationItems = [];
|
2007-10-23 07:11:59 +00:00
|
|
|
for(var j=0; j<citation.citationItems.length; j++) {
|
2010-08-16 08:46:07 +00:00
|
|
|
var citationItem = citation.citationItems[j];
|
2009-05-24 04:38:57 +00:00
|
|
|
|
2010-08-16 08:46:07 +00:00
|
|
|
citationItem.uri = this.uriMap.getURIsForItemID(citation.citationItems[j].id);
|
|
|
|
citationItems.push(JSON.stringify(citationItem, saveCitationItems));
|
2007-10-23 07:11:59 +00:00
|
|
|
}
|
2010-05-30 11:25:25 +00:00
|
|
|
field.push('"citationItems":['+citationItems.join(",")+"]");
|
2007-10-23 07:11:59 +00:00
|
|
|
|
2010-05-30 11:25:25 +00:00
|
|
|
return "{"+field.join(",")+"}";
|
2007-10-23 07:11:59 +00:00
|
|
|
}
|
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
/**
|
|
|
|
* Adds a citation based on a serialized Word field
|
2007-10-23 07:11:59 +00:00
|
|
|
*/
|
|
|
|
Zotero.Integration._oldCitationLocatorMap = {
|
2010-05-30 11:25:25 +00:00
|
|
|
p:"page",
|
|
|
|
g:"paragraph",
|
|
|
|
l:"line"
|
2007-10-23 07:11:59 +00:00
|
|
|
};
|
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
/**
|
2010-05-30 11:25:25 +00:00
|
|
|
* Adds a citation to the arrays representing the document
|
2007-10-23 07:11:59 +00:00
|
|
|
*/
|
2010-05-30 11:25:25 +00:00
|
|
|
Zotero.Integration.Session.prototype.addCitation = function(index, noteIndex, arg) {
|
Merged revisions 1986,1988-1990,1996,1998,2000-2004,2006,2008-2010,2013,2020-2028,2032-2034,2037,2039,2044-2049,2052-2056,2059,2065-2066,2068-2072,2075,2077-2079,2081,2083-2084,2086,2088-2094,2096,2099,2101,2103-2104,2107-2110,2115,2118,2120-2122,2126-2128,2131,2140,2142-2145,2149-2153,2155-2159,2165,2167-2168,2170-2171,2173-2176,2179-2183,2185-2186 via svnmerge from
https://www.zotero.org/svn/extension/branches/1.0
2008-01-30 09:53:19 +00:00
|
|
|
var index = parseInt(index, 10);
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
if(typeof(arg) == "string") { // text field
|
|
|
|
if(arg == "!" || arg == "X") return;
|
|
|
|
|
Merged revisions 1986,1988-1990,1996,1998,2000-2004,2006,2008-2010,2013,2020-2028,2032-2034,2037,2039,2044-2049,2052-2056,2059,2065-2066,2068-2072,2075,2077-2079,2081,2083-2084,2086,2088-2094,2096,2099,2101,2103-2104,2107-2110,2115,2118,2120-2122,2126-2128,2131,2140,2142-2145,2149-2153,2155-2159,2165,2167-2168,2170-2171,2173-2176,2179-2183,2185-2186 via svnmerge from
https://www.zotero.org/svn/extension/branches/1.0
2008-01-30 09:53:19 +00:00
|
|
|
var citation = this.unserializeCitation(arg, index);
|
2007-10-23 07:11:59 +00:00
|
|
|
} else { // a citation already
|
|
|
|
var citation = arg;
|
|
|
|
}
|
|
|
|
|
2010-05-30 11:25:25 +00:00
|
|
|
// get items
|
2009-08-20 05:02:55 +00:00
|
|
|
for(var i=0; i<citation.citationItems.length; i++) {
|
|
|
|
var citationItem = citation.citationItems[i];
|
2006-09-10 17:38:17 +00:00
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
// get Zotero item
|
2009-05-24 04:38:57 +00:00
|
|
|
var zoteroItem = false;
|
|
|
|
if(citationItem.uri) {
|
2009-08-11 01:11:17 +00:00
|
|
|
[zoteroItem, needUpdate] = this.uriMap.getZoteroItemForURIs(citationItem.uri);
|
2010-05-30 11:25:25 +00:00
|
|
|
if(needUpdate) this.updateIndices[index] = true;
|
2008-07-24 22:25:03 +00:00
|
|
|
} else {
|
|
|
|
if(citationItem.key) {
|
|
|
|
zoteroItem = Zotero.Items.getByKey(citationItem.key);
|
2009-05-24 04:38:57 +00:00
|
|
|
} else if(citationItem.itemID) {
|
2008-07-24 22:25:03 +00:00
|
|
|
zoteroItem = Zotero.Items.get(citationItem.itemID);
|
2010-05-30 11:25:25 +00:00
|
|
|
} else if(citationItem.id) {
|
|
|
|
zoteroItem = Zotero.Items.get(citationItem.id);
|
2008-07-24 22:25:03 +00:00
|
|
|
}
|
2010-05-30 11:25:25 +00:00
|
|
|
if(zoteroItem) this.updateIndices[index] = true;
|
2009-05-24 04:38:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// if no item, check if it was already reselected and otherwise handle as a missing item
|
2009-08-20 05:02:55 +00:00
|
|
|
if(!zoteroItem) {
|
2009-05-24 04:38:57 +00:00
|
|
|
if(citationItem.uri) {
|
2009-08-20 05:02:55 +00:00
|
|
|
var reselectKeys = citationItem.uri;
|
|
|
|
var reselectKeyType = RESELECT_KEY_URI;
|
2009-05-24 04:38:57 +00:00
|
|
|
} else if(citationItem.key) {
|
2009-09-19 23:43:51 +00:00
|
|
|
var reselectKeys = [citationItem.key];
|
2009-08-20 05:02:55 +00:00
|
|
|
var reselectKeyType = RESELECT_KEY_ITEM_KEY;
|
2010-05-30 11:25:25 +00:00
|
|
|
} else if(citationItem.id) {
|
|
|
|
var reselectKeys = [citationItem.id];
|
|
|
|
var reselectKeyType = RESELECT_KEY_ITEM_ID;
|
2009-05-24 04:38:57 +00:00
|
|
|
} else {
|
2009-09-19 23:43:51 +00:00
|
|
|
var reselectKeys = [citationItem.itemID];
|
2009-08-20 05:02:55 +00:00
|
|
|
var reselectKeyType = RESELECT_KEY_ITEM_ID;
|
2009-05-24 04:38:57 +00:00
|
|
|
}
|
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
// look to see if item has already been reselected
|
|
|
|
for each(var reselectKey in reselectKeys) {
|
|
|
|
if(this.reselectedItems[reselectKey]) {
|
|
|
|
zoteroItem = Zotero.Items.get(this.reselectedItems[reselectKey]);
|
2010-05-30 11:25:25 +00:00
|
|
|
citationItem.id = zoteroItem.id;
|
|
|
|
this.updateIndices[index] = true;
|
2009-08-20 05:02:55 +00:00
|
|
|
break;
|
2009-05-24 04:38:57 +00:00
|
|
|
}
|
2009-08-20 05:02:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// if not already reselected, throw a MissingItemException
|
|
|
|
if(!zoteroItem) {
|
|
|
|
throw(new Zotero.Integration.MissingItemException(
|
2010-05-30 11:25:25 +00:00
|
|
|
reselectKeys, reselectKeyType, i, citation.citationItems.length));
|
2008-09-23 23:11:27 +00:00
|
|
|
}
|
2009-05-24 04:38:57 +00:00
|
|
|
}
|
|
|
|
|
2010-05-30 11:25:25 +00:00
|
|
|
citationItem.id = zoteroItem.id;
|
|
|
|
}
|
|
|
|
|
|
|
|
citation.properties.added = true;
|
|
|
|
citation.properties.index = index;
|
|
|
|
citation.properties.noteIndex = noteIndex;
|
|
|
|
this.citationsByIndex[index] = citation;
|
|
|
|
|
|
|
|
// add to citationsByItemID and citationsByIndex
|
|
|
|
for(var i=0; i<citation.citationItems.length; i++) {
|
|
|
|
var citationItem = citation.citationItems[i];
|
|
|
|
if(!this.citationsByItemID[citationItem.id]) {
|
|
|
|
this.citationsByItemID[citationItem.id] = [citation];
|
Merged revisions 1986,1988-1990,1996,1998,2000-2004,2006,2008-2010,2013,2020-2028,2032-2034,2037,2039,2044-2049,2052-2056,2059,2065-2066,2068-2072,2075,2077-2079,2081,2083-2084,2086,2088-2094,2096,2099,2101,2103-2104,2107-2110,2115,2118,2120-2122,2126-2128,2131,2140,2142-2145,2149-2153,2155-2159,2165,2167-2168,2170-2171,2173-2176,2179-2183,2185-2186 via svnmerge from
https://www.zotero.org/svn/extension/branches/1.0
2008-01-30 09:53:19 +00:00
|
|
|
this.bibliographyHasChanged = true;
|
2010-05-30 11:25:25 +00:00
|
|
|
} else {
|
|
|
|
var byItemID = this.citationsByItemID[citationItem.id];
|
|
|
|
if(byItemID[byItemID.length-1].properties.index < index) {
|
|
|
|
// if index is greater than the last index, add to end
|
|
|
|
byItemID.push(citation);
|
|
|
|
} else {
|
|
|
|
// otherwise, splice in at appropriate location
|
|
|
|
for(var j=0; byItemID[j].properties.index < index && j<byItemID.length-1; j++) {}
|
|
|
|
byItemID.splice(j++, 0, citation);
|
|
|
|
}
|
2007-10-23 07:11:59 +00:00
|
|
|
}
|
2006-09-11 01:05:26 +00:00
|
|
|
}
|
2009-05-24 04:38:57 +00:00
|
|
|
|
2010-06-05 17:49:04 +00:00
|
|
|
var needNewID = !citation.citationID || this.citationIDs[citation.citationID];
|
|
|
|
if(needNewID || !this.oldCitationIDs[citation.citationID]) {
|
|
|
|
if(needNewID) {
|
|
|
|
Zotero.debug("Zotero.Integration: "+citation.citationID+" ("+index+") needs new citationID");
|
|
|
|
citation.citationID = Zotero.randomString();
|
|
|
|
}
|
2010-05-30 11:25:25 +00:00
|
|
|
this.newIndices[index] = true;
|
|
|
|
this.updateIndices[index] = true;
|
|
|
|
}
|
2010-06-05 17:49:04 +00:00
|
|
|
Zotero.debug("Zotero.Integration: adding citationID "+citation.citationID);
|
2010-05-30 11:25:25 +00:00
|
|
|
this.citationIDs[citation.citationID] = true;
|
2006-09-11 01:05:26 +00:00
|
|
|
}
|
2009-08-20 05:02:55 +00:00
|
|
|
/**
|
|
|
|
* Unserializes a JSON citation into a citation object (sans items)
|
2006-09-11 01:05:26 +00:00
|
|
|
*/
|
Merged revisions 1986,1988-1990,1996,1998,2000-2004,2006,2008-2010,2013,2020-2028,2032-2034,2037,2039,2044-2049,2052-2056,2059,2065-2066,2068-2072,2075,2077-2079,2081,2083-2084,2086,2088-2094,2096,2099,2101,2103-2104,2107-2110,2115,2118,2120-2122,2126-2128,2131,2140,2142-2145,2149-2153,2155-2159,2165,2167-2168,2170-2171,2173-2176,2179-2183,2185-2186 via svnmerge from
https://www.zotero.org/svn/extension/branches/1.0
2008-01-30 09:53:19 +00:00
|
|
|
Zotero.Integration.Session.prototype.unserializeCitation = function(arg, index) {
|
2007-10-23 07:11:59 +00:00
|
|
|
if(arg[0] == "{") { // JSON field
|
Merged revisions 1986,1988-1990,1996,1998,2000-2004,2006,2008-2010,2013,2020-2028,2032-2034,2037,2039,2044-2049,2052-2056,2059,2065-2066,2068-2072,2075,2077-2079,2081,2083-2084,2086,2088-2094,2096,2099,2101,2103-2104,2107-2110,2115,2118,2120-2122,2126-2128,2131,2140,2142-2145,2149-2153,2155-2159,2165,2167-2168,2170-2171,2173-2176,2179-2183,2185-2186 via svnmerge from
https://www.zotero.org/svn/extension/branches/1.0
2008-01-30 09:53:19 +00:00
|
|
|
// fix for corrupted fields
|
|
|
|
var lastBracket = arg.lastIndexOf("}");
|
|
|
|
if(lastBracket+1 != arg.length) {
|
|
|
|
this.updateIndices[index] = true;
|
2010-05-30 11:25:25 +00:00
|
|
|
arg = arg.substr(0, lastBracket+1);
|
Merged revisions 1986,1988-1990,1996,1998,2000-2004,2006,2008-2010,2013,2020-2028,2032-2034,2037,2039,2044-2049,2052-2056,2059,2065-2066,2068-2072,2075,2077-2079,2081,2083-2084,2086,2088-2094,2096,2099,2101,2103-2104,2107-2110,2115,2118,2120-2122,2126-2128,2131,2140,2142-2145,2149-2153,2155-2159,2165,2167-2168,2170-2171,2173-2176,2179-2183,2185-2186 via svnmerge from
https://www.zotero.org/svn/extension/branches/1.0
2008-01-30 09:53:19 +00:00
|
|
|
}
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
// get JSON
|
2009-09-18 17:11:03 +00:00
|
|
|
try {
|
2010-06-06 00:57:47 +00:00
|
|
|
var citation = Zotero.JSON.unserialize(arg);
|
2009-09-18 17:11:03 +00:00
|
|
|
} catch(e) {
|
2010-11-05 02:52:14 +00:00
|
|
|
// fix for corrupted fields (corrupted by Word, somehow)
|
2009-09-18 17:11:03 +00:00
|
|
|
try {
|
2010-06-06 00:57:47 +00:00
|
|
|
var citation = Zotero.JSON.unserialize(arg.substr(0, arg.length-1));
|
2009-09-18 17:11:03 +00:00
|
|
|
} catch(e) {
|
2010-11-05 02:52:14 +00:00
|
|
|
// another fix for corrupted fields (corrupted by 2.1b1)
|
|
|
|
try {
|
|
|
|
var citation = Zotero.JSON.unserialize(arg.replace(/{{((?:\s*,?"unsorted":(?:true|false)|\s*,?"custom":"(?:(?:\\")?[^"]*\s*)*")*)}}/, "{$1}"));
|
|
|
|
} catch(e) {
|
|
|
|
throw new Zotero.Integration.CorruptFieldException(arg);
|
|
|
|
}
|
2009-09-18 17:11:03 +00:00
|
|
|
}
|
|
|
|
}
|
2007-10-23 07:11:59 +00:00
|
|
|
|
2010-05-30 11:25:25 +00:00
|
|
|
// fix for uppercase citation codes
|
2010-06-06 00:57:47 +00:00
|
|
|
if(citation.CITATIONITEMS) {
|
2010-05-30 11:25:25 +00:00
|
|
|
this.updateIndices[index] = true;
|
2010-06-06 00:57:47 +00:00
|
|
|
citation.citationItems = [];
|
|
|
|
for (var i=0; i<citation.CITATIONITEMS.length; i++) {
|
|
|
|
for (var j in citation.CITATIONITEMS[i]) {
|
2008-06-17 20:50:44 +00:00
|
|
|
switch (j) {
|
|
|
|
case 'ITEMID':
|
|
|
|
var field = 'itemID';
|
|
|
|
break;
|
|
|
|
|
|
|
|
// 'position', 'custom'
|
|
|
|
default:
|
|
|
|
var field = j.toLowerCase();
|
|
|
|
}
|
2010-06-06 00:57:47 +00:00
|
|
|
if (!citation.citationItems[i]) {
|
|
|
|
citation.citationItems[i] = {};
|
2008-06-17 20:50:44 +00:00
|
|
|
}
|
2010-06-06 00:57:47 +00:00
|
|
|
citation.citationItems[i][field] = citation.CITATIONITEMS[i][j];
|
2008-06-17 20:50:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-30 11:25:25 +00:00
|
|
|
if(!citation.properties) citation.properties = {};
|
2010-06-06 00:57:47 +00:00
|
|
|
|
|
|
|
// for upgrade from Zotero 2.0 or earlier
|
|
|
|
for each(var citationItem in citation.citationItems) {
|
|
|
|
if(citationItem.locatorType) {
|
2010-08-16 08:19:12 +00:00
|
|
|
const locatorTypeTerms = ["page", "book", "chapter", "column", "figure", "folio",
|
|
|
|
"issue", "line", "note", "opus", "paragraph", "part", "section", "sub verbo",
|
|
|
|
"volume", "verse"];
|
|
|
|
citationItem.label = locatorTypeTerms[citationItem.locatorType];
|
2010-06-06 00:57:47 +00:00
|
|
|
delete citationItem.locatorType;
|
|
|
|
} else if(citationItem.suppressAuthor) {
|
|
|
|
citationItem["suppress-author"] = citationItem["suppressAuthor"];
|
|
|
|
delete citationItem.suppressAuthor;
|
2007-10-23 07:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
2010-06-06 00:57:47 +00:00
|
|
|
if(citation.sort) {
|
|
|
|
citation.properties.unsorted = !citation.sort;
|
|
|
|
delete citation.sort;
|
|
|
|
}
|
2010-05-30 11:25:25 +00:00
|
|
|
|
|
|
|
if(!citation.citationID) citation.citationID = Zotero.randomString();
|
2010-06-06 00:57:47 +00:00
|
|
|
citation.properties.field = arg;
|
2007-10-23 07:11:59 +00:00
|
|
|
} else { // ye olde style field
|
|
|
|
var underscoreIndex = arg.indexOf("_");
|
|
|
|
var itemIDs = arg.substr(0, underscoreIndex).split("|");
|
|
|
|
|
|
|
|
var lastIndex = arg.lastIndexOf("_");
|
|
|
|
if(lastIndex != underscoreIndex+1) {
|
|
|
|
var locatorString = arg.substr(underscoreIndex+1, lastIndex-underscoreIndex-1);
|
|
|
|
var locators = locatorString.split("|");
|
|
|
|
}
|
|
|
|
|
|
|
|
var citationItems = new Array();
|
|
|
|
for(var i=0; i<itemIDs.length; i++) {
|
2010-05-30 11:25:25 +00:00
|
|
|
var citationItem = {id:itemIDs[i]};
|
2007-10-23 07:11:59 +00:00
|
|
|
if(locators) {
|
|
|
|
citationItem.locator = locators[i].substr(1);
|
2010-05-30 11:25:25 +00:00
|
|
|
citationItem.label = Zotero.Integration._oldCitationLocatorMap[locators[i][0]];
|
2007-10-23 07:11:59 +00:00
|
|
|
}
|
|
|
|
citationItems.push(citationItem);
|
|
|
|
}
|
|
|
|
|
2010-05-30 11:25:25 +00:00
|
|
|
var citation = {"citationItems":citationItems, properties:{}};
|
Merged revisions 1986,1988-1990,1996,1998,2000-2004,2006,2008-2010,2013,2020-2028,2032-2034,2037,2039,2044-2049,2052-2056,2059,2065-2066,2068-2072,2075,2077-2079,2081,2083-2084,2086,2088-2094,2096,2099,2101,2103-2104,2107-2110,2115,2118,2120-2122,2126-2128,2131,2140,2142-2145,2149-2153,2155-2159,2165,2167-2168,2170-2171,2173-2176,2179-2183,2185-2186 via svnmerge from
https://www.zotero.org/svn/extension/branches/1.0
2008-01-30 09:53:19 +00:00
|
|
|
this.updateIndices[index] = true;
|
2007-10-23 07:11:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return citation;
|
2006-09-11 01:05:26 +00:00
|
|
|
}
|
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
/**
|
2010-05-30 11:25:25 +00:00
|
|
|
* marks a citation for removal
|
2006-09-11 01:05:26 +00:00
|
|
|
*/
|
2009-05-24 04:38:57 +00:00
|
|
|
Zotero.Integration.Session.prototype.deleteCitation = function(index) {
|
2010-05-30 19:06:41 +00:00
|
|
|
var oldCitation = (this.citationsByIndex[index] ? this.citationsByIndex[index] : false);
|
2007-10-23 07:11:59 +00:00
|
|
|
this.citationsByIndex[index] = {properties:{"delete":true}};
|
|
|
|
|
2010-05-30 19:06:41 +00:00
|
|
|
if(oldCitation && oldCitation.citationItems & oldCitation.properties.added) {
|
2010-05-30 11:25:25 +00:00
|
|
|
// clear out old citations if necessary
|
|
|
|
for each(var citationItem in oldCitation.citationItems) {
|
|
|
|
if(this.citationsByItemID[citationItem.id]) {
|
|
|
|
var indexInItemID = this.citationsByItemID[citationItem.id].indexOf(oldCitation);
|
|
|
|
if(indexInItemID !== -1) {
|
|
|
|
this.citationsByItemID[citationItem.id] = this.citationsByItemID[citationItem.id].splice(indexInItemID, 1);
|
|
|
|
if(this.citationsByItemID[citationItem.id].length == 0) {
|
|
|
|
delete this.citationsByItemID[citationItem.id];
|
|
|
|
}
|
2009-05-24 04:38:57 +00:00
|
|
|
}
|
2008-08-21 21:30:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-06-05 17:49:04 +00:00
|
|
|
Zotero.debug("Zotero.Integration: deleting old citationID "+oldCitation.citationID);
|
|
|
|
if(oldCitation.citationID) delete this.citationIDs[oldCitation.citationID];
|
2008-08-21 21:30:36 +00:00
|
|
|
|
2010-05-30 11:25:25 +00:00
|
|
|
this.updateIndices[index] = true;
|
2006-09-10 17:38:17 +00:00
|
|
|
}
|
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
/**
|
2010-05-30 11:25:25 +00:00
|
|
|
* Gets integration bibliography
|
2006-09-10 17:38:17 +00:00
|
|
|
*/
|
2010-05-30 11:25:25 +00:00
|
|
|
Zotero.Integration.Session.prototype.getBibliography = function() {
|
2010-06-28 02:38:48 +00:00
|
|
|
this.updateUncitedItems();
|
2010-07-06 06:47:59 +00:00
|
|
|
|
|
|
|
// generate bibliography
|
|
|
|
var bib = this.style.makeBibliography();
|
|
|
|
|
2010-08-16 08:07:07 +00:00
|
|
|
if(bib) {
|
|
|
|
// omit items
|
|
|
|
Zotero.Cite.removeFromBibliography(bib, this.omittedItems);
|
|
|
|
|
|
|
|
// replace items with their custom counterpars
|
|
|
|
for(var i in bib[0].entry_ids) {
|
|
|
|
if(this.customBibliographyText[bib[0].entry_ids[i]]) {
|
|
|
|
bib[1][i] = this.customBibliographyText[bib[0].entry_ids[i]];
|
|
|
|
}
|
2010-07-06 06:47:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return bib;
|
2006-09-10 17:38:17 +00:00
|
|
|
}
|
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
/**
|
2010-05-30 19:06:41 +00:00
|
|
|
* Calls CSL.Engine.updateUncitedItems() to reconcile list of uncited items
|
2007-10-23 07:11:59 +00:00
|
|
|
*/
|
2010-05-30 19:06:41 +00:00
|
|
|
Zotero.Integration.Session.prototype.updateUncitedItems = function() {
|
2010-06-28 02:38:48 +00:00
|
|
|
// There appears to be a bug somewhere here.
|
|
|
|
Zotero.debug("UPDATING UNCITED ITEMS WITH "+this.uncitedItems.toSource());
|
2010-05-30 19:06:41 +00:00
|
|
|
this.style.updateUncitedItems([parseInt(i) for(i in this.uncitedItems)]);
|
2007-10-23 07:11:59 +00:00
|
|
|
}
|
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
/**
|
|
|
|
* Refreshes updateIndices variable to include fields for modified items
|
2007-10-23 07:11:59 +00:00
|
|
|
*/
|
2009-08-20 05:02:55 +00:00
|
|
|
Zotero.Integration.Session.prototype.updateUpdateIndices = function(regenerateAll) {
|
Merged revisions 1986,1988-1990,1996,1998,2000-2004,2006,2008-2010,2013,2020-2028,2032-2034,2037,2039,2044-2049,2052-2056,2059,2065-2066,2068-2072,2075,2077-2079,2081,2083-2084,2086,2088-2094,2096,2099,2101,2103-2104,2107-2110,2115,2118,2120-2122,2126-2128,2131,2140,2142-2145,2149-2153,2155-2159,2165,2167-2168,2170-2171,2173-2176,2179-2183,2185-2186 via svnmerge from
https://www.zotero.org/svn/extension/branches/1.0
2008-01-30 09:53:19 +00:00
|
|
|
if(regenerateAll || this.regenerateAll) {
|
2007-10-23 07:11:59 +00:00
|
|
|
// update all indices
|
2011-03-03 07:09:08 +00:00
|
|
|
for(var i in this.citationsByIndex) {
|
2010-05-30 19:06:41 +00:00
|
|
|
this.newIndices[i] = true;
|
2007-10-23 07:11:59 +00:00
|
|
|
this.updateIndices[i] = true;
|
2006-09-10 17:38:17 +00:00
|
|
|
}
|
2007-10-23 07:11:59 +00:00
|
|
|
} else {
|
|
|
|
// update only item IDs
|
|
|
|
for(var i in this.updateItemIDs) {
|
|
|
|
if(this.citationsByItemID[i] && this.citationsByItemID[i].length) {
|
|
|
|
for(var j=0; j<this.citationsByItemID[i].length; j++) {
|
|
|
|
this.updateIndices[this.citationsByItemID[i][j].properties.index] = true;
|
2006-09-04 04:13:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-10-23 07:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
- implement previewCitationCluster(), restoreProcessorState(), new "bibchange" flag in processCitationCluster() output, and new opt.sort_citations flag in word processor integration
- upgrade to citeproc-js 1.0.29
From Frank's 1.0.25 announcement:
Provide new command, previewCitationCluster(), that returns
string for hypothetical citation at specified position,
without affecting processor state.
Fix bug that would have cause appendCitationCluster() to
run updateItems() unnecessarily.
Provide for forced generation of citationID, for internal use
in previewing.
From Frank's 1.0.26 announcement:
Implement new command restoreProcessorState(), for use in,
er, restoring the processor state, when position variables
and citation sort keys are already known.
From Frank's 1.0.27 announcement:
This fixes a couple of obvious problems in the code of the new
restoreProcessorState() command.
From Frank's 1.0.28 announcement:
This version introduces a significant change to the return
value of processCitationCluster(). It is now an array with
two elements, the first being a JS object that serves as a
data segment, and the second the list of two-element arrays
representing insertion indexes and strings for insertion
(as previously documented). An API change of this scale
probably calls for some more visible sign in the version
numbering, but the original statement on versioning says
that the major and minor numbers will align with the CSL
schema, so we stay at level 1.0.
The data segment referred to above contains just one element
currently, "bibchange", which is true if processing the
citation results in any change affecting the bibliography.
This release also introduces one change and one addition to
style configuration flags. The flag at citation.opt["citation-number-sort"]
has been moved to opt.citation_number_sort, for clarity and
consistency. A new flag, opt.sort_citations, is true if
citations are sorted by the style in any way.
From Frank's 1.0.29 announcement:
Complete reimplementation of cite-level disambiguation.
The new code is more compact and maintainable, and
avoids thrashing behavior that afflicted the previous
code when a large number of cites required both
add-names and year-suffix disambiguation.
Suppress year suffix when fresh ambig keys are generated.
Inserts by a plugin affecting year suffixes should now be
correctly handled.
2010-06-13 22:53:57 +00:00
|
|
|
/**
|
|
|
|
* Returns citations before and after a given index
|
|
|
|
*/
|
|
|
|
Zotero.Integration.Session.prototype._getPrePost = function(index) {
|
|
|
|
var citationIndices = [];
|
|
|
|
var citationsPre = [];
|
|
|
|
for(var i=0; i<index; i++) {
|
|
|
|
if(this.citationsByIndex[i] && !this.newIndices[i] && !this.citationsByIndex[i].properties.delete) {
|
|
|
|
citationsPre.push([this.citationsByIndex[i].citationID, this.citationsByIndex[i].properties.noteIndex]);
|
|
|
|
citationIndices.push(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
citationIndices.push(index);
|
|
|
|
var citationsPost = [];
|
|
|
|
for(var i=index+1; i<this.citationsByIndex.length; i++) {
|
|
|
|
if(this.citationsByIndex[i] && !this.newIndices[i] && !this.citationsByIndex[i].properties.delete) {
|
|
|
|
citationsPost.push([this.citationsByIndex[i].citationID, this.citationsByIndex[i].properties.noteIndex]);
|
|
|
|
citationIndices.push(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return [citationsPre, citationsPost, citationIndices];
|
|
|
|
}
|
|
|
|
|
2010-05-30 11:25:25 +00:00
|
|
|
/**
|
|
|
|
* Returns a formatted citation
|
|
|
|
*/
|
|
|
|
Zotero.Integration.Session.prototype.formatCitation = function(index, citation) {
|
|
|
|
if(!this.citationText[index]) {
|
- implement previewCitationCluster(), restoreProcessorState(), new "bibchange" flag in processCitationCluster() output, and new opt.sort_citations flag in word processor integration
- upgrade to citeproc-js 1.0.29
From Frank's 1.0.25 announcement:
Provide new command, previewCitationCluster(), that returns
string for hypothetical citation at specified position,
without affecting processor state.
Fix bug that would have cause appendCitationCluster() to
run updateItems() unnecessarily.
Provide for forced generation of citationID, for internal use
in previewing.
From Frank's 1.0.26 announcement:
Implement new command restoreProcessorState(), for use in,
er, restoring the processor state, when position variables
and citation sort keys are already known.
From Frank's 1.0.27 announcement:
This fixes a couple of obvious problems in the code of the new
restoreProcessorState() command.
From Frank's 1.0.28 announcement:
This version introduces a significant change to the return
value of processCitationCluster(). It is now an array with
two elements, the first being a JS object that serves as a
data segment, and the second the list of two-element arrays
representing insertion indexes and strings for insertion
(as previously documented). An API change of this scale
probably calls for some more visible sign in the version
numbering, but the original statement on versioning says
that the major and minor numbers will align with the CSL
schema, so we stay at level 1.0.
The data segment referred to above contains just one element
currently, "bibchange", which is true if processing the
citation results in any change affecting the bibliography.
This release also introduces one change and one addition to
style configuration flags. The flag at citation.opt["citation-number-sort"]
has been moved to opt.citation_number_sort, for clarity and
consistency. A new flag, opt.sort_citations, is true if
citations are sorted by the style in any way.
From Frank's 1.0.29 announcement:
Complete reimplementation of cite-level disambiguation.
The new code is more compact and maintainable, and
avoids thrashing behavior that afflicted the previous
code when a large number of cites required both
add-names and year-suffix disambiguation.
Suppress year suffix when fresh ambig keys are generated.
Inserts by a plugin affecting year suffixes should now be
correctly handled.
2010-06-13 22:53:57 +00:00
|
|
|
var citationsPre, citationsPost, citationIndices;
|
|
|
|
[citationsPre, citationsPost, citationIndices] = this._getPrePost(index);
|
2010-09-27 17:12:41 +00:00
|
|
|
Zotero.debug("style.processCitationCluster("+citation.toSource()+", "+citationsPre.toSource()+", "+citationsPost.toSource());
|
2010-05-30 11:25:25 +00:00
|
|
|
var newCitations = this.style.processCitationCluster(citation, citationsPre, citationsPost);
|
- implement previewCitationCluster(), restoreProcessorState(), new "bibchange" flag in processCitationCluster() output, and new opt.sort_citations flag in word processor integration
- upgrade to citeproc-js 1.0.29
From Frank's 1.0.25 announcement:
Provide new command, previewCitationCluster(), that returns
string for hypothetical citation at specified position,
without affecting processor state.
Fix bug that would have cause appendCitationCluster() to
run updateItems() unnecessarily.
Provide for forced generation of citationID, for internal use
in previewing.
From Frank's 1.0.26 announcement:
Implement new command restoreProcessorState(), for use in,
er, restoring the processor state, when position variables
and citation sort keys are already known.
From Frank's 1.0.27 announcement:
This fixes a couple of obvious problems in the code of the new
restoreProcessorState() command.
From Frank's 1.0.28 announcement:
This version introduces a significant change to the return
value of processCitationCluster(). It is now an array with
two elements, the first being a JS object that serves as a
data segment, and the second the list of two-element arrays
representing insertion indexes and strings for insertion
(as previously documented). An API change of this scale
probably calls for some more visible sign in the version
numbering, but the original statement on versioning says
that the major and minor numbers will align with the CSL
schema, so we stay at level 1.0.
The data segment referred to above contains just one element
currently, "bibchange", which is true if processing the
citation results in any change affecting the bibliography.
This release also introduces one change and one addition to
style configuration flags. The flag at citation.opt["citation-number-sort"]
has been moved to opt.citation_number_sort, for clarity and
consistency. A new flag, opt.sort_citations, is true if
citations are sorted by the style in any way.
From Frank's 1.0.29 announcement:
Complete reimplementation of cite-level disambiguation.
The new code is more compact and maintainable, and
avoids thrashing behavior that afflicted the previous
code when a large number of cites required both
add-names and year-suffix disambiguation.
Suppress year suffix when fresh ambig keys are generated.
Inserts by a plugin affecting year suffixes should now be
correctly handled.
2010-06-13 22:53:57 +00:00
|
|
|
for each(var newCitation in newCitations[1]) {
|
2010-05-30 11:25:25 +00:00
|
|
|
this.citationText[citationIndices[newCitation[0]]] = newCitation[1];
|
2010-06-05 17:49:04 +00:00
|
|
|
this.updateIndices[citationIndices[newCitation[0]]] = true;
|
2010-05-30 11:25:25 +00:00
|
|
|
}
|
- implement previewCitationCluster(), restoreProcessorState(), new "bibchange" flag in processCitationCluster() output, and new opt.sort_citations flag in word processor integration
- upgrade to citeproc-js 1.0.29
From Frank's 1.0.25 announcement:
Provide new command, previewCitationCluster(), that returns
string for hypothetical citation at specified position,
without affecting processor state.
Fix bug that would have cause appendCitationCluster() to
run updateItems() unnecessarily.
Provide for forced generation of citationID, for internal use
in previewing.
From Frank's 1.0.26 announcement:
Implement new command restoreProcessorState(), for use in,
er, restoring the processor state, when position variables
and citation sort keys are already known.
From Frank's 1.0.27 announcement:
This fixes a couple of obvious problems in the code of the new
restoreProcessorState() command.
From Frank's 1.0.28 announcement:
This version introduces a significant change to the return
value of processCitationCluster(). It is now an array with
two elements, the first being a JS object that serves as a
data segment, and the second the list of two-element arrays
representing insertion indexes and strings for insertion
(as previously documented). An API change of this scale
probably calls for some more visible sign in the version
numbering, but the original statement on versioning says
that the major and minor numbers will align with the CSL
schema, so we stay at level 1.0.
The data segment referred to above contains just one element
currently, "bibchange", which is true if processing the
citation results in any change affecting the bibliography.
This release also introduces one change and one addition to
style configuration flags. The flag at citation.opt["citation-number-sort"]
has been moved to opt.citation_number_sort, for clarity and
consistency. A new flag, opt.sort_citations, is true if
citations are sorted by the style in any way.
From Frank's 1.0.29 announcement:
Complete reimplementation of cite-level disambiguation.
The new code is more compact and maintainable, and
avoids thrashing behavior that afflicted the previous
code when a large number of cites required both
add-names and year-suffix disambiguation.
Suppress year suffix when fresh ambig keys are generated.
Inserts by a plugin affecting year suffixes should now be
correctly handled.
2010-06-13 22:53:57 +00:00
|
|
|
return newCitations.bibchange;
|
2010-05-30 11:25:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Updates the list of citations to be serialized to the document
|
|
|
|
*/
|
2010-06-05 17:49:04 +00:00
|
|
|
Zotero.Integration.Session.prototype.updateCitations = function() {
|
|
|
|
/*var allUpdatesForced = false;
|
2010-05-30 19:06:41 +00:00
|
|
|
var forcedUpdates = {};
|
|
|
|
if(force) {
|
2010-06-03 22:30:32 +00:00
|
|
|
allUpdatesForced = true;
|
2010-05-30 19:06:41 +00:00
|
|
|
// make sure at least one citation gets updated
|
|
|
|
updateLoop: for each(var indexList in [this.newIndices, this.updateIndices]) {
|
|
|
|
for(var i in indexList) {
|
|
|
|
if(!this.citationsByIndex[i].properties.delete) {
|
2010-06-03 22:30:32 +00:00
|
|
|
allUpdatesForced = false;
|
2010-05-30 19:06:41 +00:00
|
|
|
break updateLoop;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-03 22:30:32 +00:00
|
|
|
if(allUpdatesForced) {
|
2010-05-30 19:06:41 +00:00
|
|
|
for(i in this.citationsByIndex) {
|
|
|
|
if(this.citationsByIndex[i] && !this.citationsByIndex[i].properties.delete) {
|
|
|
|
forcedUpdates[i] = true;
|
2010-06-03 22:30:32 +00:00
|
|
|
break;
|
2010-05-30 19:06:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-06-05 17:49:04 +00:00
|
|
|
}*/
|
2010-05-30 19:06:41 +00:00
|
|
|
|
2010-05-30 11:25:25 +00:00
|
|
|
Zotero.debug("Zotero.Integration: indices of new citations");
|
|
|
|
Zotero.debug([key for(key in this.newIndices)]);
|
|
|
|
Zotero.debug("Zotero.Integration: indices of updated citations");
|
|
|
|
Zotero.debug([key for(key in this.updateIndices)]);
|
2010-05-30 19:06:41 +00:00
|
|
|
|
2010-06-06 00:01:11 +00:00
|
|
|
var deleteCitations = {};
|
2010-06-05 17:49:04 +00:00
|
|
|
for each(var indexList in [this.newIndices, this.updateIndices]) {
|
2010-05-30 11:25:25 +00:00
|
|
|
for(var index in indexList) {
|
2010-05-30 19:06:41 +00:00
|
|
|
index = parseInt(index);
|
|
|
|
|
2010-05-30 11:25:25 +00:00
|
|
|
var citation = this.citationsByIndex[index];
|
|
|
|
if(citation.properties.delete) {
|
2010-06-06 00:01:11 +00:00
|
|
|
deleteCitations[index] = true;
|
2010-05-30 11:25:25 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if(this.formatCitation(index, citation)) {
|
|
|
|
this.bibliographyHasChanged = true;
|
|
|
|
}
|
|
|
|
if(!this.citationIDs[citation.citationID]) {
|
|
|
|
this.citationIDs[citation.citationID] = citation;
|
|
|
|
}
|
|
|
|
delete this.newIndices[index];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-05 17:49:04 +00:00
|
|
|
/*if(allUpdatesForced) {
|
2010-06-03 22:30:32 +00:00
|
|
|
this.newIndices = {};
|
|
|
|
this.updateIndices = {};
|
2010-06-05 17:49:04 +00:00
|
|
|
}*/
|
2010-06-03 22:30:32 +00:00
|
|
|
|
2010-05-30 11:25:25 +00:00
|
|
|
return deleteCitations;
|
2008-07-10 11:05:43 +00:00
|
|
|
}
|
|
|
|
|
- implement previewCitationCluster(), restoreProcessorState(), new "bibchange" flag in processCitationCluster() output, and new opt.sort_citations flag in word processor integration
- upgrade to citeproc-js 1.0.29
From Frank's 1.0.25 announcement:
Provide new command, previewCitationCluster(), that returns
string for hypothetical citation at specified position,
without affecting processor state.
Fix bug that would have cause appendCitationCluster() to
run updateItems() unnecessarily.
Provide for forced generation of citationID, for internal use
in previewing.
From Frank's 1.0.26 announcement:
Implement new command restoreProcessorState(), for use in,
er, restoring the processor state, when position variables
and citation sort keys are already known.
From Frank's 1.0.27 announcement:
This fixes a couple of obvious problems in the code of the new
restoreProcessorState() command.
From Frank's 1.0.28 announcement:
This version introduces a significant change to the return
value of processCitationCluster(). It is now an array with
two elements, the first being a JS object that serves as a
data segment, and the second the list of two-element arrays
representing insertion indexes and strings for insertion
(as previously documented). An API change of this scale
probably calls for some more visible sign in the version
numbering, but the original statement on versioning says
that the major and minor numbers will align with the CSL
schema, so we stay at level 1.0.
The data segment referred to above contains just one element
currently, "bibchange", which is true if processing the
citation results in any change affecting the bibliography.
This release also introduces one change and one addition to
style configuration flags. The flag at citation.opt["citation-number-sort"]
has been moved to opt.citation_number_sort, for clarity and
consistency. A new flag, opt.sort_citations, is true if
citations are sorted by the style in any way.
From Frank's 1.0.29 announcement:
Complete reimplementation of cite-level disambiguation.
The new code is more compact and maintainable, and
avoids thrashing behavior that afflicted the previous
code when a large number of cites required both
add-names and year-suffix disambiguation.
Suppress year suffix when fresh ambig keys are generated.
Inserts by a plugin affecting year suffixes should now be
correctly handled.
2010-06-13 22:53:57 +00:00
|
|
|
/**
|
2010-06-28 02:38:48 +00:00
|
|
|
* Restores processor state from document, without requesting citation updates
|
- implement previewCitationCluster(), restoreProcessorState(), new "bibchange" flag in processCitationCluster() output, and new opt.sort_citations flag in word processor integration
- upgrade to citeproc-js 1.0.29
From Frank's 1.0.25 announcement:
Provide new command, previewCitationCluster(), that returns
string for hypothetical citation at specified position,
without affecting processor state.
Fix bug that would have cause appendCitationCluster() to
run updateItems() unnecessarily.
Provide for forced generation of citationID, for internal use
in previewing.
From Frank's 1.0.26 announcement:
Implement new command restoreProcessorState(), for use in,
er, restoring the processor state, when position variables
and citation sort keys are already known.
From Frank's 1.0.27 announcement:
This fixes a couple of obvious problems in the code of the new
restoreProcessorState() command.
From Frank's 1.0.28 announcement:
This version introduces a significant change to the return
value of processCitationCluster(). It is now an array with
two elements, the first being a JS object that serves as a
data segment, and the second the list of two-element arrays
representing insertion indexes and strings for insertion
(as previously documented). An API change of this scale
probably calls for some more visible sign in the version
numbering, but the original statement on versioning says
that the major and minor numbers will align with the CSL
schema, so we stay at level 1.0.
The data segment referred to above contains just one element
currently, "bibchange", which is true if processing the
citation results in any change affecting the bibliography.
This release also introduces one change and one addition to
style configuration flags. The flag at citation.opt["citation-number-sort"]
has been moved to opt.citation_number_sort, for clarity and
consistency. A new flag, opt.sort_citations, is true if
citations are sorted by the style in any way.
From Frank's 1.0.29 announcement:
Complete reimplementation of cite-level disambiguation.
The new code is more compact and maintainable, and
avoids thrashing behavior that afflicted the previous
code when a large number of cites required both
add-names and year-suffix disambiguation.
Suppress year suffix when fresh ambig keys are generated.
Inserts by a plugin affecting year suffixes should now be
correctly handled.
2010-06-13 22:53:57 +00:00
|
|
|
*/
|
|
|
|
Zotero.Integration.Session.prototype.restoreProcessorState = function() {
|
|
|
|
var citations = [];
|
2011-03-03 07:09:08 +00:00
|
|
|
for(var i in this.citationsByIndex) {
|
- implement previewCitationCluster(), restoreProcessorState(), new "bibchange" flag in processCitationCluster() output, and new opt.sort_citations flag in word processor integration
- upgrade to citeproc-js 1.0.29
From Frank's 1.0.25 announcement:
Provide new command, previewCitationCluster(), that returns
string for hypothetical citation at specified position,
without affecting processor state.
Fix bug that would have cause appendCitationCluster() to
run updateItems() unnecessarily.
Provide for forced generation of citationID, for internal use
in previewing.
From Frank's 1.0.26 announcement:
Implement new command restoreProcessorState(), for use in,
er, restoring the processor state, when position variables
and citation sort keys are already known.
From Frank's 1.0.27 announcement:
This fixes a couple of obvious problems in the code of the new
restoreProcessorState() command.
From Frank's 1.0.28 announcement:
This version introduces a significant change to the return
value of processCitationCluster(). It is now an array with
two elements, the first being a JS object that serves as a
data segment, and the second the list of two-element arrays
representing insertion indexes and strings for insertion
(as previously documented). An API change of this scale
probably calls for some more visible sign in the version
numbering, but the original statement on versioning says
that the major and minor numbers will align with the CSL
schema, so we stay at level 1.0.
The data segment referred to above contains just one element
currently, "bibchange", which is true if processing the
citation results in any change affecting the bibliography.
This release also introduces one change and one addition to
style configuration flags. The flag at citation.opt["citation-number-sort"]
has been moved to opt.citation_number_sort, for clarity and
consistency. A new flag, opt.sort_citations, is true if
citations are sorted by the style in any way.
From Frank's 1.0.29 announcement:
Complete reimplementation of cite-level disambiguation.
The new code is more compact and maintainable, and
avoids thrashing behavior that afflicted the previous
code when a large number of cites required both
add-names and year-suffix disambiguation.
Suppress year suffix when fresh ambig keys are generated.
Inserts by a plugin affecting year suffixes should now be
correctly handled.
2010-06-13 22:53:57 +00:00
|
|
|
if(this.citationsByIndex[i] && !this.newIndices[i] && !this.citationsByIndex[i].properties.delete) {
|
|
|
|
citations.push(this.citationsByIndex[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this.style.restoreProcessorState(citations);
|
|
|
|
}
|
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
/**
|
|
|
|
* Loads document data from a JSON object
|
2007-10-23 07:11:59 +00:00
|
|
|
*/
|
2008-07-10 11:05:43 +00:00
|
|
|
Zotero.Integration.Session.prototype.loadBibliographyData = function(json) {
|
2009-09-18 17:11:03 +00:00
|
|
|
try {
|
|
|
|
var documentData = Zotero.JSON.unserialize(json);
|
|
|
|
} catch(e) {
|
|
|
|
try {
|
|
|
|
var documentData = Zotero.JSON.unserialize(json.substr(0, json.length-1));
|
|
|
|
} catch(e) {
|
|
|
|
throw new Zotero.Integration.CorruptFieldException(json);
|
|
|
|
}
|
|
|
|
}
|
2006-09-10 17:38:17 +00:00
|
|
|
|
2010-06-28 02:38:48 +00:00
|
|
|
var needUpdate;
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
// set uncited
|
|
|
|
if(documentData.uncited) {
|
2009-05-24 04:38:57 +00:00
|
|
|
if(documentData.uncited[0]) {
|
|
|
|
// new style array of arrays with URIs
|
2010-06-28 02:38:48 +00:00
|
|
|
let zoteroItem, needUpdate;
|
2009-05-24 04:38:57 +00:00
|
|
|
for each(var uris in documentData.uncited) {
|
2010-06-28 02:38:48 +00:00
|
|
|
[zoteroItem, update] = this.uriMap.getZoteroItemForURIs(uris);
|
|
|
|
if(zoteroItem && !this.citationsByItemID[zoteroItem.id]) {
|
|
|
|
this.uncitedItems[zoteroItem.id] = true;
|
|
|
|
} else {
|
|
|
|
needUpdate = true;
|
|
|
|
}
|
|
|
|
this.bibliographyDataHasChanged |= needUpdate;
|
2009-05-24 04:38:57 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for(var itemID in documentData.uncited) {
|
|
|
|
// if not yet in item set, add to item set
|
2009-08-24 01:09:47 +00:00
|
|
|
var zoteroItem = Zotero.Items.getByKey(itemID);
|
|
|
|
if(!zoteroItem) zoteroItem = Zotero.Items.get(itemID);
|
|
|
|
if(zoteroItem) this.uncitedItems[zoteroItem.id] = true;
|
2009-05-24 04:38:57 +00:00
|
|
|
}
|
|
|
|
this.bibliographyDataHasChanged = true;
|
|
|
|
}
|
2010-05-30 19:06:41 +00:00
|
|
|
|
|
|
|
this.updateUncitedItems();
|
2007-10-23 07:11:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// set custom bibliography entries
|
|
|
|
if(documentData.custom) {
|
2009-05-24 04:38:57 +00:00
|
|
|
if(documentData.custom[0]) {
|
|
|
|
// new style array of arrays with URIs
|
2009-08-11 01:11:17 +00:00
|
|
|
var zoteroItem, needUpdate;
|
2009-05-24 04:38:57 +00:00
|
|
|
for each(var custom in documentData.custom) {
|
2009-08-11 01:11:17 +00:00
|
|
|
[zoteroItem, needUpdate] = this.uriMap.getZoteroItemForURIs(custom[0]);
|
2009-05-24 04:38:57 +00:00
|
|
|
if(!zoteroItem) continue;
|
2009-08-11 01:11:17 +00:00
|
|
|
if(needUpdate) this.bibliographyDataHasChanged = true;
|
2009-05-24 04:38:57 +00:00
|
|
|
|
2010-05-30 11:25:25 +00:00
|
|
|
if(this.citationsByItemID[zoteroItem.id] || this.uncitedItems[zoteroItem.id]) {
|
|
|
|
this.customBibliographyText[zoteroItem.id] = custom[1];
|
|
|
|
}
|
2008-07-24 22:25:03 +00:00
|
|
|
}
|
2009-05-24 04:38:57 +00:00
|
|
|
} else {
|
|
|
|
// old style hash
|
|
|
|
for(var itemID in documentData.custom) {
|
2009-08-24 01:09:47 +00:00
|
|
|
var zoteroItem = Zotero.Items.getByKey(itemID);
|
|
|
|
if(!zoteroItem) zoteroItem = Zotero.Items.get(itemID);
|
|
|
|
if(!zoteroItem) continue;
|
|
|
|
|
2010-05-30 11:25:25 +00:00
|
|
|
if(this.citationsByItemID[zoteroItem.id] || this.uncitedItems[zoteroItem.id]) {
|
|
|
|
this.customBibliographyText[zoteroItem.id] = documentData.custom[itemID];
|
|
|
|
}
|
Merged revisions 2710-2712,2714-2716,2718-2728,2730-2731,2734,2736-2738,2740-2750,2752-2753,2755,2758-2768,2770-2779,2782,2789-2790,2794,2797-2802,2804,2808-2810,2812,2814-2824,2826-2832,2834-2835 via svnmerge from 1.0 branch
2008-06-11 08:55:59 +00:00
|
|
|
}
|
2009-05-24 04:38:57 +00:00
|
|
|
this.bibliographyDataHasChanged = true;
|
2006-09-10 17:38:17 +00:00
|
|
|
}
|
2007-10-23 07:11:59 +00:00
|
|
|
}
|
2009-08-20 05:02:55 +00:00
|
|
|
|
2010-06-28 02:38:48 +00:00
|
|
|
// set entries to be omitted from bibliography
|
|
|
|
if(documentData.omitted) {
|
|
|
|
let zoteroItem, needUpdate;
|
|
|
|
for each(var uris in documentData.omitted) {
|
|
|
|
[zoteroItem, update] = this.uriMap.getZoteroItemForURIs(uris);
|
|
|
|
if(zoteroItem && this.citationsByItemID[zoteroItem.id]) {
|
|
|
|
this.omittedItems[zoteroItem.id] = true;
|
|
|
|
} else {
|
|
|
|
needUpdate = true;
|
|
|
|
}
|
|
|
|
this.bibliographyDataHasChanged |= needUpdate;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
this.bibliographyData = json;
|
2007-10-23 07:11:59 +00:00
|
|
|
}
|
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
/**
|
|
|
|
* Saves document data from a JSON object
|
2007-10-23 07:11:59 +00:00
|
|
|
*/
|
2008-07-10 11:05:43 +00:00
|
|
|
Zotero.Integration.Session.prototype.getBibliographyData = function() {
|
|
|
|
var bibliographyData = {};
|
2006-09-10 17:38:17 +00:00
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
// add uncited if there is anything
|
2009-05-24 04:38:57 +00:00
|
|
|
for(var item in this.uncitedItems) {
|
2008-07-24 22:25:03 +00:00
|
|
|
if(item) {
|
2009-05-24 04:38:57 +00:00
|
|
|
if(!bibliographyData.uncited) bibliographyData.uncited = [];
|
|
|
|
bibliographyData.uncited.push(this.uriMap.getURIsForItemID(item));
|
2008-07-24 22:25:03 +00:00
|
|
|
}
|
2007-10-23 07:11:59 +00:00
|
|
|
}
|
2010-06-28 02:38:48 +00:00
|
|
|
for(var item in this.omittedItems) {
|
|
|
|
if(item) {
|
|
|
|
if(!bibliographyData.omitted) bibliographyData.omitted = [];
|
|
|
|
bibliographyData.omitted.push(this.uriMap.getURIsForItemID(item));
|
|
|
|
}
|
|
|
|
}
|
2006-09-10 17:38:17 +00:00
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
// look for custom bibliography entries
|
2010-05-30 11:25:25 +00:00
|
|
|
bibliographyData.custom = [[this.uriMap.getURIsForItemID(id), this.customBibliographyText[id]]
|
|
|
|
for(id in this.customBibliographyText)];
|
2006-09-10 17:38:17 +00:00
|
|
|
|
2008-07-10 11:05:43 +00:00
|
|
|
if(bibliographyData.uncited || bibliographyData.custom) {
|
|
|
|
return Zotero.JSON.serialize(bibliographyData);
|
2007-10-23 07:11:59 +00:00
|
|
|
} else {
|
2008-07-10 11:05:43 +00:00
|
|
|
return ""; // nothing
|
2007-10-23 07:11:59 +00:00
|
|
|
}
|
2006-09-10 17:38:17 +00:00
|
|
|
}
|
|
|
|
|
2010-05-30 11:25:25 +00:00
|
|
|
/**
|
|
|
|
* Returns a preview, given a citation object (whose citationItems lack item
|
|
|
|
* and position)
|
|
|
|
*/
|
|
|
|
Zotero.Integration.Session.prototype.previewCitation = function(citation) {
|
- implement previewCitationCluster(), restoreProcessorState(), new "bibchange" flag in processCitationCluster() output, and new opt.sort_citations flag in word processor integration
- upgrade to citeproc-js 1.0.29
From Frank's 1.0.25 announcement:
Provide new command, previewCitationCluster(), that returns
string for hypothetical citation at specified position,
without affecting processor state.
Fix bug that would have cause appendCitationCluster() to
run updateItems() unnecessarily.
Provide for forced generation of citationID, for internal use
in previewing.
From Frank's 1.0.26 announcement:
Implement new command restoreProcessorState(), for use in,
er, restoring the processor state, when position variables
and citation sort keys are already known.
From Frank's 1.0.27 announcement:
This fixes a couple of obvious problems in the code of the new
restoreProcessorState() command.
From Frank's 1.0.28 announcement:
This version introduces a significant change to the return
value of processCitationCluster(). It is now an array with
two elements, the first being a JS object that serves as a
data segment, and the second the list of two-element arrays
representing insertion indexes and strings for insertion
(as previously documented). An API change of this scale
probably calls for some more visible sign in the version
numbering, but the original statement on versioning says
that the major and minor numbers will align with the CSL
schema, so we stay at level 1.0.
The data segment referred to above contains just one element
currently, "bibchange", which is true if processing the
citation results in any change affecting the bibliography.
This release also introduces one change and one addition to
style configuration flags. The flag at citation.opt["citation-number-sort"]
has been moved to opt.citation_number_sort, for clarity and
consistency. A new flag, opt.sort_citations, is true if
citations are sorted by the style in any way.
From Frank's 1.0.29 announcement:
Complete reimplementation of cite-level disambiguation.
The new code is more compact and maintainable, and
avoids thrashing behavior that afflicted the previous
code when a large number of cites required both
add-names and year-suffix disambiguation.
Suppress year suffix when fresh ambig keys are generated.
Inserts by a plugin affecting year suffixes should now be
correctly handled.
2010-06-13 22:53:57 +00:00
|
|
|
var citationsPre, citationsPost, citationIndices;
|
|
|
|
[citationsPre, citationsPost, citationIndices] = this._getPrePost(citation.properties.index);
|
2010-05-30 19:06:41 +00:00
|
|
|
try {
|
- implement previewCitationCluster(), restoreProcessorState(), new "bibchange" flag in processCitationCluster() output, and new opt.sort_citations flag in word processor integration
- upgrade to citeproc-js 1.0.29
From Frank's 1.0.25 announcement:
Provide new command, previewCitationCluster(), that returns
string for hypothetical citation at specified position,
without affecting processor state.
Fix bug that would have cause appendCitationCluster() to
run updateItems() unnecessarily.
Provide for forced generation of citationID, for internal use
in previewing.
From Frank's 1.0.26 announcement:
Implement new command restoreProcessorState(), for use in,
er, restoring the processor state, when position variables
and citation sort keys are already known.
From Frank's 1.0.27 announcement:
This fixes a couple of obvious problems in the code of the new
restoreProcessorState() command.
From Frank's 1.0.28 announcement:
This version introduces a significant change to the return
value of processCitationCluster(). It is now an array with
two elements, the first being a JS object that serves as a
data segment, and the second the list of two-element arrays
representing insertion indexes and strings for insertion
(as previously documented). An API change of this scale
probably calls for some more visible sign in the version
numbering, but the original statement on versioning says
that the major and minor numbers will align with the CSL
schema, so we stay at level 1.0.
The data segment referred to above contains just one element
currently, "bibchange", which is true if processing the
citation results in any change affecting the bibliography.
This release also introduces one change and one addition to
style configuration flags. The flag at citation.opt["citation-number-sort"]
has been moved to opt.citation_number_sort, for clarity and
consistency. A new flag, opt.sort_citations, is true if
citations are sorted by the style in any way.
From Frank's 1.0.29 announcement:
Complete reimplementation of cite-level disambiguation.
The new code is more compact and maintainable, and
avoids thrashing behavior that afflicted the previous
code when a large number of cites required both
add-names and year-suffix disambiguation.
Suppress year suffix when fresh ambig keys are generated.
Inserts by a plugin affecting year suffixes should now be
correctly handled.
2010-06-13 22:53:57 +00:00
|
|
|
return this.style.previewCitationCluster(citation, citationsPre, citationsPost, "rtf");
|
2010-05-30 19:06:41 +00:00
|
|
|
} catch(e) {
|
|
|
|
Zotero.debug(e);
|
|
|
|
throw e;
|
|
|
|
}
|
2010-05-30 11:25:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Brings up the addCitationDialog, prepopulated if a citation is provided
|
|
|
|
*/
|
|
|
|
Zotero.Integration.Session.prototype.editCitation = function(index, noteIndex, citation) {
|
|
|
|
var me = this;
|
|
|
|
var io = new function() { this.wrappedJSObject = this; }
|
|
|
|
|
|
|
|
// if there's already a citation, make sure we have item IDs in addition to keys
|
|
|
|
if(citation) {
|
|
|
|
var zoteroItem;
|
|
|
|
for each(var citationItem in citation.citationItems) {
|
|
|
|
var item = false;
|
|
|
|
if(!citationItem.id) {
|
|
|
|
zoteroItem = false;
|
|
|
|
if(citationItem.uri) {
|
|
|
|
[zoteroItem, ] = this.uriMap.getZoteroItemForURIs(citationItem.uri);
|
|
|
|
} else if(citationItem.key) {
|
|
|
|
zoteroItem = Zotero.Items.getByKey(citationItem.key);
|
|
|
|
}
|
|
|
|
if(zoteroItem) citationItem.id = zoteroItem.id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// create object to hold citation
|
|
|
|
io.citation = (citation ? Zotero.JSON.unserialize(Zotero.JSON.serialize(citation)) : {"citationItems":{}, "properties":{}});
|
|
|
|
io.citation.properties.index = parseInt(index, 10);
|
|
|
|
io.citation.properties.noteIndex = parseInt(noteIndex, 10);
|
|
|
|
// assign preview function
|
|
|
|
io.previewFunction = function() {
|
|
|
|
return me.previewCitation(io.citation);
|
|
|
|
}
|
2010-06-06 00:57:47 +00:00
|
|
|
// determine whether citation is sortable in current style
|
- implement previewCitationCluster(), restoreProcessorState(), new "bibchange" flag in processCitationCluster() output, and new opt.sort_citations flag in word processor integration
- upgrade to citeproc-js 1.0.29
From Frank's 1.0.25 announcement:
Provide new command, previewCitationCluster(), that returns
string for hypothetical citation at specified position,
without affecting processor state.
Fix bug that would have cause appendCitationCluster() to
run updateItems() unnecessarily.
Provide for forced generation of citationID, for internal use
in previewing.
From Frank's 1.0.26 announcement:
Implement new command restoreProcessorState(), for use in,
er, restoring the processor state, when position variables
and citation sort keys are already known.
From Frank's 1.0.27 announcement:
This fixes a couple of obvious problems in the code of the new
restoreProcessorState() command.
From Frank's 1.0.28 announcement:
This version introduces a significant change to the return
value of processCitationCluster(). It is now an array with
two elements, the first being a JS object that serves as a
data segment, and the second the list of two-element arrays
representing insertion indexes and strings for insertion
(as previously documented). An API change of this scale
probably calls for some more visible sign in the version
numbering, but the original statement on versioning says
that the major and minor numbers will align with the CSL
schema, so we stay at level 1.0.
The data segment referred to above contains just one element
currently, "bibchange", which is true if processing the
citation results in any change affecting the bibliography.
This release also introduces one change and one addition to
style configuration flags. The flag at citation.opt["citation-number-sort"]
has been moved to opt.citation_number_sort, for clarity and
consistency. A new flag, opt.sort_citations, is true if
citations are sorted by the style in any way.
From Frank's 1.0.29 announcement:
Complete reimplementation of cite-level disambiguation.
The new code is more compact and maintainable, and
avoids thrashing behavior that afflicted the previous
code when a large number of cites required both
add-names and year-suffix disambiguation.
Suppress year suffix when fresh ambig keys are generated.
Inserts by a plugin affecting year suffixes should now be
correctly handled.
2010-06-13 22:53:57 +00:00
|
|
|
io.sortable = this.style.opt.sort_citations;
|
2010-05-30 11:25:25 +00:00
|
|
|
|
2010-10-15 21:32:49 +00:00
|
|
|
|
|
|
|
this._displayDialog('chrome://zotero/content/integration/addCitationDialog.xul', 'resizable', io);
|
2010-05-30 11:25:25 +00:00
|
|
|
|
|
|
|
if(io.citation.citationItems.length) { // we have an item
|
|
|
|
this.addCitation(index, noteIndex, io.citation);
|
|
|
|
this.updateIndices[index] = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return !!io.citation.citationItems.length;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Edits integration bibliography
|
|
|
|
*/
|
|
|
|
Zotero.Integration.Session.prototype.editBibliography = function() {
|
|
|
|
var bibliographyEditor = new Zotero.Integration.Session.BibliographyEditInterface(this);
|
|
|
|
var io = new function() { this.wrappedJSObject = bibliographyEditor; }
|
|
|
|
|
|
|
|
this.bibliographyDataHasChanged = this.bibliographyHasChanged = true;
|
|
|
|
|
2010-10-15 21:32:49 +00:00
|
|
|
this._displayDialog('chrome://zotero/content/integration/editBibliographyDialog.xul', 'resizable', io);
|
2010-05-30 11:25:25 +00:00
|
|
|
}
|
|
|
|
|
2008-09-11 21:29:05 +00:00
|
|
|
/**
|
|
|
|
* @class Interface for bibliography editor to alter document bibliography
|
|
|
|
* @constructor
|
|
|
|
* Creates a new bibliography editor interface
|
2010-07-06 06:47:59 +00:00
|
|
|
* @param session {Zotero.Integration.Session}
|
2007-10-23 07:11:59 +00:00
|
|
|
*/
|
|
|
|
Zotero.Integration.Session.BibliographyEditInterface = function(session) {
|
|
|
|
this.session = session;
|
2010-06-28 02:38:48 +00:00
|
|
|
|
|
|
|
this._changed = {
|
|
|
|
"customBibliographyText":{},
|
|
|
|
"uncitedItems":{},
|
|
|
|
"omittedItems":{}
|
|
|
|
}
|
|
|
|
for(var list in this._changed) {
|
|
|
|
for(var key in this.session[list]) {
|
|
|
|
this._changed[list][key] = this.session[list][key];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-30 11:25:25 +00:00
|
|
|
this._update();
|
2007-10-23 07:11:59 +00:00
|
|
|
}
|
|
|
|
|
2008-09-11 21:29:05 +00:00
|
|
|
/**
|
2010-05-30 11:25:25 +00:00
|
|
|
* Updates stored bibliography
|
2008-09-11 21:29:05 +00:00
|
|
|
*/
|
2010-05-30 11:25:25 +00:00
|
|
|
Zotero.Integration.Session.BibliographyEditInterface.prototype._update = function() {
|
2010-05-30 19:06:41 +00:00
|
|
|
this.session.updateUncitedItems();
|
2010-05-30 11:25:25 +00:00
|
|
|
this.session.style.setOutputFormat("rtf");
|
|
|
|
this.bibliography = this.session.style.makeBibliography();
|
2010-06-28 02:38:48 +00:00
|
|
|
Zotero.Cite.removeFromBibliography(this.bibliography, this.session.omittedItems);
|
|
|
|
|
2010-05-30 11:25:25 +00:00
|
|
|
for(var i in this.bibliography[0].entry_ids) {
|
2010-06-28 02:38:48 +00:00
|
|
|
if(this.bibliography[0].entry_ids[i].length != 1) continue;
|
|
|
|
var itemID = this.bibliography[0].entry_ids[i][0];
|
|
|
|
if(this.session.customBibliographyText[itemID]) {
|
|
|
|
this.bibliography[1][i] = this.session.customBibliographyText[itemID];
|
2010-05-30 11:25:25 +00:00
|
|
|
}
|
|
|
|
}
|
2007-10-23 07:11:59 +00:00
|
|
|
}
|
|
|
|
|
2008-09-11 21:29:05 +00:00
|
|
|
/**
|
2010-06-28 02:38:48 +00:00
|
|
|
* Reverts the text of an individual bibliography entry
|
|
|
|
*/
|
|
|
|
Zotero.Integration.Session.BibliographyEditInterface.prototype.revert = function(itemID) {
|
|
|
|
delete this.session.customBibliographyText[itemID];
|
|
|
|
this._update();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reverts bibliography to condition in which no edits have been made
|
|
|
|
*/
|
|
|
|
Zotero.Integration.Session.BibliographyEditInterface.prototype.revertAll = function() {
|
|
|
|
for(var list in this._changed) {
|
|
|
|
this.session[list] = {};
|
|
|
|
}
|
|
|
|
this._update();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reverts bibliography to condition before BibliographyEditInterface was opened
|
|
|
|
* Does not run _update automatically, since this will usually only happen with a cancel request
|
|
|
|
*/
|
|
|
|
Zotero.Integration.Session.BibliographyEditInterface.prototype.cancel = function() {
|
|
|
|
for(var list in this._changed) {
|
|
|
|
this.session[list] = this._changed[list];
|
|
|
|
}
|
|
|
|
this.session.updateUncitedItems();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks whether a given reference is cited within the main document text
|
2008-09-11 21:29:05 +00:00
|
|
|
*/
|
2007-10-23 07:11:59 +00:00
|
|
|
Zotero.Integration.Session.BibliographyEditInterface.prototype.isCited = function(item) {
|
2010-05-30 11:25:25 +00:00
|
|
|
if(this.session.citationsByItemID[item]) return true;
|
2010-06-28 02:38:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks whether an item ID is cited in the bibliography being edited
|
|
|
|
*/
|
|
|
|
Zotero.Integration.Session.BibliographyEditInterface.prototype.isEdited = function(itemID) {
|
|
|
|
if(this.session.customBibliographyText[itemID]) return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks whether any citations in the bibliography have been edited
|
|
|
|
*/
|
|
|
|
Zotero.Integration.Session.BibliographyEditInterface.prototype.isAnyEdited = function() {
|
|
|
|
for(var list in this._changed) {
|
|
|
|
for(var a in this.session[list]) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2007-10-23 07:11:59 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-09-11 21:29:05 +00:00
|
|
|
/**
|
2010-05-30 11:25:25 +00:00
|
|
|
* Adds an item to the bibliography
|
2008-09-11 21:29:05 +00:00
|
|
|
*/
|
2010-05-30 11:25:25 +00:00
|
|
|
Zotero.Integration.Session.BibliographyEditInterface.prototype.add = function(itemID) {
|
2010-06-28 02:38:48 +00:00
|
|
|
if(this.session.omittedItems[itemID]) {
|
|
|
|
delete this.session.omittedItems[itemID];
|
|
|
|
} else {
|
|
|
|
this.session.uncitedItems[itemID] = true;
|
|
|
|
}
|
2010-05-30 11:25:25 +00:00
|
|
|
this._update();
|
2007-10-23 07:11:59 +00:00
|
|
|
}
|
|
|
|
|
2008-09-11 21:29:05 +00:00
|
|
|
/**
|
|
|
|
* Removes an item from the bibliography being edited
|
|
|
|
*/
|
2010-05-30 11:25:25 +00:00
|
|
|
Zotero.Integration.Session.BibliographyEditInterface.prototype.remove = function(itemID) {
|
2010-06-28 02:38:48 +00:00
|
|
|
if(this.session.uncitedItems[itemID]) {
|
|
|
|
delete this.session.uncitedItems[itemID];
|
|
|
|
} else {
|
|
|
|
this.session.omittedItems[itemID] = true;
|
2006-09-10 17:38:17 +00:00
|
|
|
}
|
2010-05-30 11:25:25 +00:00
|
|
|
this._update();
|
2006-09-10 17:38:17 +00:00
|
|
|
}
|
|
|
|
|
2008-09-11 21:29:05 +00:00
|
|
|
/**
|
2010-05-30 11:25:25 +00:00
|
|
|
* Sets custom bibliography text for a given item
|
2008-09-11 21:29:05 +00:00
|
|
|
*/
|
2010-05-30 11:25:25 +00:00
|
|
|
Zotero.Integration.Session.BibliographyEditInterface.prototype.setCustomText = function(itemID, text) {
|
|
|
|
this.session.customBibliographyText[itemID] = text;
|
|
|
|
this._update();
|
2009-05-24 04:38:57 +00:00
|
|
|
}
|
|
|
|
|
2009-08-20 05:02:55 +00:00
|
|
|
/**
|
|
|
|
* A class for parsing and passing around document-specific data
|
|
|
|
*/
|
|
|
|
Zotero.Integration.DocumentData = function(string) {
|
|
|
|
this.style = {};
|
|
|
|
this.prefs = {};
|
|
|
|
this.sessionID = null;
|
|
|
|
if(string) {
|
|
|
|
this.unserialize(string);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Serializes document-specific data as XML
|
|
|
|
*/
|
|
|
|
Zotero.Integration.DocumentData.prototype.serializeXML = function() {
|
2010-09-27 17:34:39 +00:00
|
|
|
var xmlData = <data data-version={DATA_VERSION} zotero-version={Zotero.version}>
|
2010-07-06 06:47:59 +00:00
|
|
|
<session id={this.sessionID} />
|
|
|
|
<style id={this.style.styleID} hasBibliography={this.style.hasBibliography ? 1 : 0}
|
2010-09-27 17:12:41 +00:00
|
|
|
bibliographyStyleHasBeenSet={this.style.bibliographyStyleHasBeenSet ? 1 : 0}/>
|
2010-07-06 06:47:59 +00:00
|
|
|
<prefs/>
|
2009-08-20 05:02:55 +00:00
|
|
|
</data>;
|
|
|
|
|
|
|
|
for(var pref in this.prefs) {
|
|
|
|
xmlData.prefs.pref += <pref name={pref} value={this.prefs[pref]}/>
|
|
|
|
}
|
|
|
|
|
|
|
|
XML.prettyPrinting = false;
|
|
|
|
var output = xmlData.toXMLString().replace("\n", "", "g");
|
|
|
|
XML.prettyPrinting = true;
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Unserializes document-specific XML
|
|
|
|
*/
|
|
|
|
Zotero.Integration.DocumentData.prototype.unserializeXML = function(xmlData) {
|
|
|
|
if(typeof xmlData == "string") {
|
|
|
|
var xmlData = new XML(xmlData);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.sessionID = xmlData.session.@id.toString();
|
|
|
|
this.style = {"styleID":xmlData.style.@id.toString(),
|
2010-07-06 06:47:59 +00:00
|
|
|
"hasBibliography":(xmlData.style.@hasBibliography.toString() == 1),
|
|
|
|
"bibliographyStyleHasBeenSet":(xmlData.style.@bibliographyStyleHasBeenSet.toString() == 1)};
|
2009-08-20 05:02:55 +00:00
|
|
|
this.prefs = {};
|
|
|
|
for each(var pref in xmlData.prefs.children()) {
|
|
|
|
this.prefs[pref.@name.toString()] = pref.@value.toString();
|
|
|
|
}
|
2010-05-30 11:25:25 +00:00
|
|
|
this.zoteroVersion = xmlData["@zotero-version"].length() ? xmlData["@zotero-version"].toString() : "2.0";
|
|
|
|
this.dataVersion = xmlData["@data-version"].length() ? xmlData["@data-version"].toString() : 2;
|
2009-08-20 05:02:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Unserializes document-specific data, either as XML or as the string form used previously
|
|
|
|
*/
|
|
|
|
Zotero.Integration.DocumentData.prototype.unserialize = function(input) {
|
2009-08-21 08:41:07 +00:00
|
|
|
if(input[0] == "<") {
|
2009-08-20 05:02:55 +00:00
|
|
|
this.unserializeXML(input);
|
|
|
|
} else {
|
2009-09-28 06:42:39 +00:00
|
|
|
const splitRe = /(^|[^:]):(?!:)/;
|
2009-08-20 05:02:55 +00:00
|
|
|
|
2009-08-21 08:41:07 +00:00
|
|
|
var splitOutput = input.split(splitRe);
|
2009-09-28 06:42:39 +00:00
|
|
|
var prefParameters = [];
|
|
|
|
for(var i=0; i<splitOutput.length; i+=2) {
|
|
|
|
prefParameters.push((splitOutput[i]+(splitOutput[i+1] ? splitOutput[i+1] : "")).replace("::", ":", "g"));
|
2009-08-20 05:02:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
this.sessionID = prefParameters[0];
|
|
|
|
this.style = {"styleID":prefParameters[1],
|
2010-07-06 06:47:59 +00:00
|
|
|
"hasBibliography":(prefParameters[3] == "1" || prefParameters[3] == "True"),
|
|
|
|
"bibliographyStyleHasBeenSet":false};
|
2009-08-20 05:02:55 +00:00
|
|
|
this.prefs = {"fieldType":((prefParameters[5] == "1" || prefParameters[5] == "True") ? "Bookmark" : "Field")};
|
|
|
|
if(prefParameters[2] == "note") {
|
|
|
|
if(prefParameters[4] == "1" || prefParameters[4] == "True") {
|
|
|
|
this.prefs.noteType = Components.interfaces.zoteroIntegrationDocument.NOTE_ENDNOTE;
|
|
|
|
} else {
|
|
|
|
this.prefs.noteType = Components.interfaces.zoteroIntegrationDocument.NOTE_FOOTNOTE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
this.prefs.noteType = 0;
|
|
|
|
}
|
2010-05-30 11:25:25 +00:00
|
|
|
|
|
|
|
this.zoteroVersion = "2.0b6 or earlier";
|
|
|
|
this.dataVersion = 1;
|
2009-08-20 05:02:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-24 04:38:57 +00:00
|
|
|
/**
|
|
|
|
* Handles mapping of item IDs to URIs
|
|
|
|
*/
|
|
|
|
Zotero.Integration.URIMap = function(session) {
|
|
|
|
this.itemIDURIs = {};
|
|
|
|
this.session = session;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds a given mapping to the URI map
|
|
|
|
*/
|
|
|
|
Zotero.Integration.URIMap.prototype.add = function(id, uris) {
|
|
|
|
this.itemIDURIs[id] = uris;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets URIs for a given item ID, and adds to map
|
|
|
|
*/
|
|
|
|
Zotero.Integration.URIMap.prototype.getURIsForItemID = function(id) {
|
|
|
|
if(!this.itemIDURIs[id]) {
|
|
|
|
this.itemIDURIs[id] = [Zotero.URI.getItemURI(Zotero.Items.get(id))];
|
|
|
|
}
|
|
|
|
return this.itemIDURIs[id];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets Zotero item for a given set of URIs
|
|
|
|
*/
|
|
|
|
Zotero.Integration.URIMap.prototype.getZoteroItemForURIs = function(uris) {
|
|
|
|
var zoteroItem = false;
|
2009-08-11 01:11:17 +00:00
|
|
|
var needUpdate = false;
|
|
|
|
|
|
|
|
for(var i in uris) {
|
2009-05-24 04:38:57 +00:00
|
|
|
try {
|
2009-08-11 01:11:17 +00:00
|
|
|
zoteroItem = Zotero.URI.getURIItem(uris[i]);
|
2009-05-24 04:38:57 +00:00
|
|
|
if(zoteroItem) break;
|
|
|
|
} catch(e) {}
|
|
|
|
}
|
2009-08-11 01:11:17 +00:00
|
|
|
|
|
|
|
if(zoteroItem) {
|
|
|
|
// make sure URI is up to date (in case user just began synching)
|
|
|
|
var newURI = Zotero.URI.getItemURI(zoteroItem);
|
|
|
|
if(newURI != uris[i]) {
|
|
|
|
uris[i] = newURI;
|
|
|
|
needUpdate = true;
|
|
|
|
}
|
|
|
|
// cache uris
|
|
|
|
this.itemIDURIs[zoteroItem.id] = uris;
|
|
|
|
}
|
|
|
|
|
|
|
|
return [zoteroItem, needUpdate];
|
2011-03-01 05:31:20 +00:00
|
|
|
}
|