commit 08c8c4dfbd56be3180c57b5dae436640aecbc45f
parent f71ad877b1cd245d5c4b18d515a60bebb98a5a2a
Author: Simon Kornblith <simon@simonster.com>
Date: Thu, 15 Sep 2011 07:57:06 +0000
Use asynchronous APIs for collecting fields. This currently has the side effect of breaking the editor.
Diffstat:
5 files changed, 673 insertions(+), 483 deletions(-)
diff --git a/chrome/content/zotero/integration/addCitationDialog.js b/chrome/content/zotero/integration/addCitationDialog.js
@@ -492,7 +492,7 @@ var Zotero_Citation_Dialog = new function () {
// run preview function to re-sort, if it hasn't already been
// run
- io.previewFunction();
+ io.sort();
// add items back to list
scrollToItem = null;
@@ -588,22 +588,16 @@ var Zotero_Citation_Dialog = new function () {
if(isCustom) {
var citation = document.getElementById('editor').value;
- } else {
- var citation = (io.citation.citationItems.length ? io.previewFunction() : "");
- }
- Zotero.debug("verified not custom");
-
- if(Zotero.Utilities.trim(citation) == "") {
- var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
- .getService(Components.interfaces.nsIPromptService);
- var insert = promptService.confirm(window,
- Zotero.getString("integration.emptyCitationWarning.title"),
- Zotero.getString("integration.emptyCitationWarning.body"));
- if(!insert) return false;
+ if(Zotero.Utilities.trim(citation) == "") {
+ var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
+ .getService(Components.interfaces.nsIPromptService);
+ var insert = promptService.confirm(window,
+ Zotero.getString("integration.emptyCitationWarning.title"),
+ Zotero.getString("integration.emptyCitationWarning.body"));
+ if(!insert) return false;
+ }
+ io.citation.properties.custom = citation;
}
- Zotero.debug("verified not empty");
-
- if(isCustom) io.citation.properties.custom = citation;
return true;
}
diff --git a/chrome/content/zotero/integration/quickFormat.js b/chrome/content/zotero/integration/quickFormat.js
@@ -573,7 +573,7 @@ var Zotero_QuickFormat = new function () {
if(!shouldKeepSorted && !editorShowing) return;
_updateCitationObject();
- io.previewFunction();
+ io.sort();
if(shouldKeepSorted) {
// means we need to resort citations
_clearCitation();
@@ -653,11 +653,25 @@ var Zotero_QuickFormat = new function () {
}
/**
+ * Called when progress changes
+ */
+ function _onProgress(percent) {
+ var meter = document.getElementById("quick-format-progress-meter");
+ if(percent === null) {
+ meter.mode = "undetermined";
+ } else {
+ meter.mode = "determined";
+ meter.value = Math.round(percent);
+ }
+ }
+
+ /**
* Accepts current selection and adds citation
*/
function _accept() {
_updateCitationObject();
- window.close();
+ document.getElementById("quick-format-deck").selectedIndex = 1;
+ io.accept(_onProgress);
}
/**
@@ -667,7 +681,7 @@ var Zotero_QuickFormat = new function () {
var keyCode = event.keyCode;
if(keyCode === event.DOM_VK_ESCAPE) {
io.citation.citationItems = [];
- window.close();
+ io.accept();
}
}
diff --git a/chrome/content/zotero/integration/quickFormat.xul b/chrome/content/zotero/integration/quickFormat.xul
@@ -43,22 +43,27 @@
<script src="quickFormat.js"/>
<windowdragbox orient="horizontal" id="quick-format-entry">
- <hbox id="quick-format-search" flex="1" align="start">
- <toolbarbutton id="zotero-icon" type="menu">
- <menupopup>
- <menuitem id="keep-sorted" label="&zotero.citation.keepSorted.label;"
- oncommand="Zotero_QuickFormat.onKeepSortedCommand()" type="checkbox"
- hidden="true"/>
- <menuitem id="show-editor" label="&zotero.integration.showEditor.label;"
- oncommand="Zotero_QuickFormat.onShowEditorCommand()" type="checkbox"
- hidden="true"/>
- <menuitem id="classic-view" label="&zotero.integration.classicView.label;"
- oncommand="Zotero_QuickFormat.onClassicViewCommand()"/>
- </menupopup>
- </toolbarbutton>
- <iframe id="quick-format-iframe" ondragstart="event.stopPropagation()" src="data:application/xhtml+xml,%3C!DOCTYPE%20html%20PUBLIC%20%22-//W3C//DTD%20XHTML%201.0%20Strict//EN%22%20%22http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd%22%3E%3Chtml%20xmlns=%22http://www.w3.org/1999/xhtml%22%3E%3Chead%3E%3Clink%20rel=%22stylesheet%22%20type=%22text/css%22%20href=%22chrome://zotero/skin/integration.css%22/%3E%3Clink%20rel=%22stylesheet%22%20type=%22text/css%22%20href=%22chrome://zotero-platform/content/integration.css%22/%3E%3C/head%3E%3Cbody%20contenteditable=%22true%22%20id=%22quick-format-editor%22/%3E%3C/html%3E"
- tabindex="1" flex="1"/>
- </hbox>
+ <deck id="quick-format-deck" selectedIndex="0" flex="1">
+ <hbox id="quick-format-search" flex="1" align="start">
+ <hbox flex="1">
+ <toolbarbutton id="zotero-icon" type="menu">
+ <menupopup>
+ <menuitem id="keep-sorted" label="&zotero.citation.keepSorted.label;"
+ oncommand="Zotero_QuickFormat.onKeepSortedCommand()" type="checkbox"
+ hidden="true"/>
+ <menuitem id="show-editor" label="&zotero.integration.showEditor.label;"
+ oncommand="Zotero_QuickFormat.onShowEditorCommand()" type="checkbox"
+ hidden="true"/>
+ <menuitem id="classic-view" label="&zotero.integration.classicView.label;"
+ oncommand="Zotero_QuickFormat.onClassicViewCommand()"/>
+ </menupopup>
+ </toolbarbutton>
+ <iframe id="quick-format-iframe" ondragstart="event.stopPropagation()" src="data:application/xhtml+xml,%3C!DOCTYPE%20html%20PUBLIC%20%22-//W3C//DTD%20XHTML%201.0%20Strict//EN%22%20%22http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd%22%3E%3Chtml%20xmlns=%22http://www.w3.org/1999/xhtml%22%3E%3Chead%3E%3Clink%20rel=%22stylesheet%22%20type=%22text/css%22%20href=%22chrome://zotero/skin/integration.css%22/%3E%3Clink%20rel=%22stylesheet%22%20type=%22text/css%22%20href=%22chrome://zotero-platform/content/integration.css%22/%3E%3C/head%3E%3Cbody%20contenteditable=%22true%22%20id=%22quick-format-editor%22/%3E%3C/html%3E"
+ tabindex="1" flex="1"/>
+ </hbox>
+ </hbox>
+ <progressmeter id="quick-format-progress-meter" mode="undetermined" value="0" flex="1"/>
+ </deck>
</windowdragbox>
<panel id="quick-format-reference-panel" noautofocus="true" norestorefocus="true" noautohide="true">
<richlistbox id="quick-format-reference-list" flex="1"/>
diff --git a/chrome/content/zotero/xpcom/integration.js b/chrome/content/zotero/xpcom/integration.js
@@ -23,6 +23,8 @@
***** END LICENSE BLOCK *****
*/
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
const RESELECT_KEY_URI = 1;
const RESELECT_KEY_ITEM_KEY = 2;
const RESELECT_KEY_ITEM_ID = 3;
@@ -37,12 +39,13 @@ Zotero.Integration = new function() {
var _tmpFile = null;
var _osascriptFile;
- var _inProgress = false;
var _integrationVersionsOK = null;
// these need to be global because of GC
var _updateTimer;
+ var _inProgress = false;
+ this.currentWindow = false;
this.sessions = {};
/**
@@ -189,6 +192,9 @@ Zotero.Integration = new function() {
this.execCommand = function execCommand(agent, command, docId) {
if(_inProgress) {
Zotero.Integration.activate();
+ if(Zotero.Integration.currentWindow && !Zotero.Integration.currentWindow.closed) {
+ Zotero.Integration.currentWindow.focus();
+ }
Zotero.debug("Integration: Request already in progress; not executing "+agent+" "+command);
return;
}
@@ -198,7 +204,7 @@ Zotero.Integration = new function() {
if(_checkPluginVersions()) {
_callIntegration(agent, command, docId);
} else {
- inProgress = false;
+ _inProgress = false;
}
}
@@ -248,71 +254,8 @@ Zotero.Integration = new function() {
document = (application.getDocument && docId ? application.getDocument(docId) : application.getActiveDocument());
integration = new Zotero.Integration.Document(application, document);
integration[command]();
- integration.cleanup();
} catch(e) {
- if(integration) {
- try {
- integration.cleanup();
- } catch(e) {
- Components.utils.reportError(e);
- }
- }
-
- if(!(e instanceof Zotero.Integration.UserCancelledException)) {
- 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"))
- }
- }
- }
-
- 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);
- }
-
- 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 {
- throw e;
- }
- }
- } finally {
- _inProgress = false;
+ Zotero.Integration.handleError(e, document);
}
}
@@ -371,6 +314,86 @@ Zotero.Integration = new function() {
}
/**
+ * Show appropriate dialogs for an integration error
+ */
+ this.handleError = function(e, document) {
+ if(!(e instanceof Zotero.Integration.UserCancelledException)) {
+ 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"))
+ }
+ }
+ }
+
+ if(!message && typeof(e) == "object") message = "\n\n"+e.toString();
+
+ if(message != "\n\nExceptionAlreadyDisplayed") {
+ displayError = Zotero.getString("integration.error.generic")+message;
+ }
+ Zotero.debug(e);
+ }
+
+ if(displayError) {
+ if(document) {
+ document.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 {
+ Zotero.logError(e);
+ }
+ }
+
+ this.complete(document);
+ }
+
+ /**
+ * Called when integration is complete
+ */
+ this.complete = function(doc) {
+ if(doc) {
+ try {
+ doc.cleanup();
+ doc.activate();
+ } catch(e) {
+ Zotero.logError(e);
+ }
+ }
+
+ if(Zotero.Integration.currentWindow && !Zotero.Integration.currentWindow.closed) {
+ Zotero.Integration.currentWindow.close();
+ }
+ _inProgress = Zotero.Integration.currentWindow = false;
+ }
+
+ /**
* Runs an AppleScript on OS X
*
* @param script {String}
@@ -447,27 +470,6 @@ Zotero.Integration.Document = function(app, doc) {
}
/**
- * Gets the type of the field
- */
-Zotero.Integration.Document.prototype._getCodeTypeAndContent = function(rawCode) {
- for each(var code in ["ITEM", "CITATION"]) {
- if(rawCode.substr(0, code.length) === code) {
- return [INTEGRATION_TYPE_ITEM, rawCode.substr(code.length+1)];
- }
- }
-
- if(rawCode.substr(0, 4) === "BIBL") {
- return [INTEGRATION_TYPE_BIBLIOGRAPHY, rawCode.substr(5)];
- }
-
- if(rawCode.substr(0, 4) === "TEMP") {
- return [INTEGRATION_TYPE_TEMP, rawCode.substr(5)];
- }
-
- return [null, rawCode];
-}
-
-/**
* Creates a new session
* @param data {Zotero.Integration.DocumentData} Document data for new session
*/
@@ -485,7 +487,6 @@ Zotero.Integration.Document.prototype._createNewSession = function(data) {
* preferences exist
*/
Zotero.Integration.Document.prototype._getSession = function(require, dontRunSetDocPrefs) {
- this._reloadSession = false;
var dataString = this._doc.getDocumentData();
if(!dataString) {
var haveFields = false;
@@ -525,7 +526,7 @@ Zotero.Integration.Document.prototype._getSession = function(require, dontRunSet
this._doc.setDocumentData(this._session.data.serializeXML());
if(haveFields) {
- this._reloadSession = true;
+ this._session.reload = true;
}
} else {
var data = new Zotero.Integration.DocumentData(dataString);
@@ -570,49 +571,228 @@ Zotero.Integration.Document.prototype._getSession = function(require, dontRunSet
}
this._doc.setDocumentData(this._session.data.serializeXML());
- this._reloadSession = true;
+ this._session.reload = true;
}
}
- this._session.resetRequest(this);
return !!dataString;
}
/**
- * Gets all fields for a document
- * @param require {Boolean} Whether an error should be thrown if no fields exist
- * @param dontRunSetDocPrefs {Boolean} Whether to show the Set Document Preferences window if no
- * preferences exist
+ * Adds a citation to the current document.
*/
-Zotero.Integration.Document.prototype._getFields = function(require, dontRunSetDocPrefs) {
- if(this._fields) return;
- if(!this._session && !this._getSession(require, dontRunSetDocPrefs)) return;
+Zotero.Integration.Document.prototype.addCitation = function() {
+ this._getSession();
- var getFieldsTime = (new Date()).getTime();
- var fields = this._doc.getFields(this._session.data.prefs['fieldType']);
- this._fields = [];
- while(fields.hasMoreElements()) {
- this._fields.push(fields.getNext().QueryInterface(Components.interfaces.zoteroIntegrationField));
+ var fieldGetter = new Zotero.Integration.Fields(this._session, this._doc),
+ me = this;
+ fieldGetter.addEditCitation(null, function() {
+ Zotero.Integration.complete(me._doc);
+ });
+}
+
+/**
+ * Edits the citation at the cursor position.
+ */
+Zotero.Integration.Document.prototype.editCitation = function() {
+ this._getSession(true);
+
+ var field = this._doc.cursorInField(this._session.data.prefs['fieldType'])
+ if(!field) {
+ throw new Zotero.Integration.DisplayException("notInCitation");
}
- var endTime = (new Date()).getTime();
- if(Zotero.Debug.enabled) {
- Zotero.debug("Integration: got "+this._fields.length+" fields in "+
- (endTime-getFieldsTime)/1000+"; "+
- 1000/((endTime-getFieldsTime)/this._fields.length)+" fields/second");
+
+ var fieldGetter = new Zotero.Integration.Fields(this._session, this._doc),
+ me = this;
+ fieldGetter.addEditCitation(field, function() {
+ Zotero.Integration.complete(me._doc);
+ });
+}
+
+/**
+ * Adds a bibliography to the current document.
+ */
+Zotero.Integration.Document.prototype.addBibliography = function() {
+ this._getSession(true);
+
+ // Make sure we can have a bibliography
+ if(!this._session.data.style.hasBibliography) {
+ throw new Zotero.Integration.DisplayException("noBibliography");
}
- if(require && !this._fields.length) {
- throw new Zotero.Integration.DisplayException("mustInsertCitation");
+ var fieldGetter = new Zotero.Integration.Fields(this._session, this._doc),
+ field = fieldGetter.addField(),
+ me = this;
+ field.setCode("BIBL");
+ fieldGetter.updateSession(function() {
+ fieldGetter.updateDocument(false, true);
+ Zotero.Integration.complete(me._doc);
+ });
+}
+
+/**
+ * Edits bibliography metadata.
+ */
+Zotero.Integration.Document.prototype.editBibliography = function() {
+ // Make sure we have a bibliography
+ this._getSession(true);
+
+ var fieldGetter = new Zotero.Integration.Fields(this._session, this._doc),
+ me = this;
+ fieldGetter.get(function(fields) {
+ var haveBibliography = false;
+ for(var i=fields.length-1; i>=0; i--) {
+ var code = fields[i].getCode();
+ var [type, content] = fieldGetter.getCodeTypeAndContent(code);
+ if(type == INTEGRATION_TYPE_BIBLIOGRAPHY) {
+ haveBibliography = true;
+ break;
+ }
+ }
+
+ if(!haveBibliography) {
+ throw new Zotero.Integration.DisplayException("mustInsertBibliography");
+ }
+
+ fieldGetter.updateSession();
+ me._session.editBibliography();
+ me._doc.activate();
+ fieldGetter.updateDocument(false, true);
+
+ Zotero.Integration.complete(me._doc);
+ });
+}
+
+/**
+ * Updates the citation data for all citations and bibliography entries.
+ */
+Zotero.Integration.Document.prototype.refresh = function() {
+ this._getSession(true);
+
+ // Send request, forcing update of citations and bibliography
+ var fieldGetter = new Zotero.Integration.Fields(this._session, this._doc),
+ me = this;
+ fieldGetter.updateSession(function() {
+ fieldGetter.updateDocument(true, true);
+ Zotero.Integration.complete(me._doc);
+ });
+}
+
+/**
+ * Deletes field codes.
+ */
+Zotero.Integration.Document.prototype.removeCodes = function() {
+ this._getSession(true);
+
+ var fieldGetter = new Zotero.Integration.Fields(this._session, this._doc),
+ me = this;
+ fieldGetter.get(function(fields) {
+ var result = me._doc.displayAlert(Zotero.getString("integration.removeCodesWarning"),
+ Components.interfaces.zoteroIntegrationDocument.DIALOG_ICON_WARNING,
+ Components.interfaces.zoteroIntegrationDocument.DIALOG_BUTTONS_OK_CANCEL);
+ if(result) {
+ for(var i=fields.length-1; i>=0; i--) {
+ fields[i].removeCode();
+ }
+ }
+
+ Zotero.Integration.complete(me._doc);
+ });
+}
+
+/**
+ * Displays a dialog to set document preferences (style, footnotes/endnotes, etc.)
+ */
+Zotero.Integration.Document.prototype.setDocPrefs = function() {
+ this._getSession(false, true);
+
+ var fieldGetter = new Zotero.Integration.Fields(this._session, this._doc);
+ fieldGetter.get();
+
+ try {
+ var oldData = this._session.setDocPrefs(this._app.primaryFieldType, this._app.secondaryFieldType);
+ } finally {
+ this._doc.activate();
}
- return;
+ if(oldData) {
+ this._doc.setDocumentData(this._session.data.serializeXML());
+
+ var me = this;
+ fieldGetter.get(function(fields) {
+ if(fields && 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 != me._session.data.prefs.fieldType;
+ var convertItems = convertBibliographies || oldData.prefs.noteType != me._session.data.prefs.noteType;
+ var fieldsToConvert = new Array();
+ var fieldNoteTypes = new Array();
+ for(var i=0, n=fields.length; i<n; i++) {
+ var field = fields[i],
+ fieldCode = field.getCode(),
+ [type, content] = fieldGetter.getCodeTypeAndContent(fieldCode);
+
+ if(convertItems && type === INTEGRATION_TYPE_ITEM) {
+ var citation = me._session.unserializeCitation(fieldCode);
+ if(!citation.properties.dontUpdate) {
+ fieldsToConvert.push(field);
+ fieldNoteTypes.push(me._session.data.prefs.noteType);
+ }
+ } else if(convertBibliographies && type === INTEGRATION_TYPE_BIBLIOGRAPHY) {
+ fieldsToConvert.push(field);
+ fieldNoteTypes.push(0);
+ }
+ }
+
+ if(fieldsToConvert.length) {
+ // pass to conversion function
+ me._doc.convert(new Zotero.Integration.Document.JSEnumerator(fieldsToConvert),
+ me._session.data.prefs.fieldType, fieldNoteTypes, fieldNoteTypes.length);
+
+ // clear fields so that they will get collected again before refresh
+ me._fields = undefined;
+ }
+
+ // refresh contents
+ fieldGetter = new Zotero.Integration.Fields(me._session, me._doc);
+ fieldGetter.updateSession(function() {
+ fieldGetter.updateDocument(true, true, true);
+ Zotero.Integration.complete(me._doc);
+ });
+ }
+ });
+ } else {
+ Zotero.Integration.complete(this._doc);
+ }
+}
+
+/**
+ * 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();
+}
+
+/**
+ * Methods for retrieving fields from a document
+ * @constructor
+ */
+Zotero.Integration.Fields = function(session, doc) {
+ this._session = session;
+ this._doc = doc;
+ this._callbacks = [];
}
/**
* Checks that it is appropriate to add fields to the current document at the current
* positon, then adds one.
*/
-Zotero.Integration.Document.prototype._addField = function(note) {
+Zotero.Integration.Fields.prototype.addField = function(note) {
// Get citation types if necessary
if(!this._doc.canInsertField(this._session.data.prefs['fieldType'])) {
throw new Zotero.Integration.DisplayException("cannotInsertHere");
@@ -635,12 +815,100 @@ Zotero.Integration.Document.prototype._addField = function(note) {
}
/**
+ * Gets the type and content of a field object
+ */
+Zotero.Integration.Fields.prototype.getCodeTypeAndContent = function(rawCode) {
+ for each(var code in ["ITEM", "CITATION"]) {
+ if(rawCode.substr(0, code.length) === code) {
+ return [INTEGRATION_TYPE_ITEM, rawCode.substr(code.length+1)];
+ }
+ }
+
+ if(rawCode.substr(0, 4) === "BIBL") {
+ return [INTEGRATION_TYPE_BIBLIOGRAPHY, rawCode.substr(5)];
+ }
+
+ if(rawCode.substr(0, 4) === "TEMP") {
+ return [INTEGRATION_TYPE_TEMP, rawCode.substr(5)];
+ }
+
+ return [null, rawCode];
+}
+
+/**
+ * Gets all fields for a document
+ */
+Zotero.Integration.Fields.prototype.get = function(callback) {
+ if(this._fields) {
+ try {
+ if(callback) {
+ callback(this._fields);
+ }
+ } catch(e) {
+ Zotero.Integration.handleError(e, this._doc);
+ throw e;
+ }
+ return;
+ }
+
+ if(callback) {
+ this._callbacks.push(callback);
+ }
+ this._retrieveFields();
+}
+
+/**
+ * Actually do the work of retrieving fields
+ */
+Zotero.Integration.Fields.prototype._retrieveFields = function() {
+ if(this._retrievingFields) return;
+
+ this._retrievingFields = true;
+ var getFieldsTime = (new Date()).getTime();
+ var me = this;
+ this._doc.getFieldsAsync(this._session.data.prefs['fieldType'], {"observe":function(subject, topic, data) {
+ if(topic === "fields-available") {
+ if(me._progressCallback) me._progressCallback(75);
+
+ // Add fields to fields array
+ var fieldsEnumerator = subject.QueryInterface(Components.interfaces.nsISimpleEnumerator);
+ var fields = me._fields = [];
+ while(fieldsEnumerator.hasMoreElements()) {
+ fields.push(fieldsEnumerator.getNext().QueryInterface(Components.interfaces.zoteroIntegrationField));
+ }
+
+ if(Zotero.Debug.enabled) {
+ var endTime = (new Date()).getTime();
+ Zotero.debug("Integration: Retrieved "+fields.length+" fields in "+
+ (endTime-getFieldsTime)/1000+"; "+
+ 1000/((endTime-getFieldsTime)/fields.length)+" fields/second");
+ }
+
+ // Run callbacks
+ try {
+ for(var i=0, n=me._callbacks.length; i<n; i++) {
+ me._callbacks[i](fields);
+ }
+ } catch(e) {
+ Zotero.logError(e);
+ Zotero.Integration.handleError(e, me._doc);
+ }
+ } else if(topic === "fields-progress" && me._progressCallback) {
+ me._progressCallback((data ? parseInt(data, 10)*(3/4) : null));
+ } else if(topic === "fields-error") {
+ Zotero.logError(data);
+ Zotero.Integration.handleError(data, me._doc);
+ }
+ }, QueryInterface:XPCOMUtils.generateQI([Components.interfaces.nsIObserver, Components.interfaces.nsISupports])});
+}
+
+/**
* 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) {
+Zotero.Integration.Fields.prototype._showCorruptFieldError = function(e, field, i) {
var msg = Zotero.getString("integration.corruptField")+'\n\n'+
Zotero.getString('integration.corruptField.description');
field.select();
@@ -654,7 +922,7 @@ Zotero.Integration.Document.prototype._showCorruptFieldError = function(e, field
this._removeCodeFields.push(i);
} else {
// Display reselect edit citation dialog
- var added = this._session.editCitation(i, field.getNoteIndex());
+ var added = this.addEditCitation(field);
if(added) {
this._doc.activate();
} else {
@@ -664,99 +932,98 @@ Zotero.Integration.Document.prototype._showCorruptFieldError = function(e, field
}
/**
- * Loads existing citations and bibliographies out of a document, and creates or edits fields
+ * Updates Zotero.Integration.Session attached to Zotero.Integration.Fields in line with document
*/
-Zotero.Integration.Document.prototype._updateSession = function(newField, editField) {
+Zotero.Integration.Fields.prototype.updateSession = function(callback) {
+ var me = this;
+ this.get(function(fields) {
+ me._updateSession(fields);
+ if(callback) callback(this._session);
+ });
+}
+
+/**
+ * Callback for Zotero.Integration.Fields.get()
+ */
+Zotero.Integration.Fields.prototype._updateSession = function(fields) {
+ this._session.resetRequest(this._doc);
+
var deleteKeys = {};
this._deleteFields = [];
this._removeCodeFields = [];
this._bibliographyFields = [];
var bibliographyData = "";
- // first collect entire bibliography
- this._getFields();
- var editFieldIndex = false;
var collectFieldsTime = (new Date()).getTime();
- for(var i in this._fields) {
- var field = this._fields[i];
+ for(var i=0, n=fields.length; i<n; i++) {
+ var field = fields[i];
- if(editField && field.equals(editField)) {
- editFieldIndex = i;
- } else {
+ try {
+ var fieldCode = field.getCode();
+ } catch(e) {
+ this._showCorruptFieldError(e, field, i);
+ }
+
+ var [type, content] = this.getCodeTypeAndContent(fieldCode);
+ if(type === INTEGRATION_TYPE_ITEM) {
+ var noteIndex = field.getNoteIndex();
try {
- var fieldCode = field.getCode();
+ this._session.addCitation(i, noteIndex, content);
} catch(e) {
- this._showCorruptFieldError(e, field, i);
- }
-
- var [type, content] = this._getCodeTypeAndContent(fieldCode);
- if(type === INTEGRATION_TYPE_ITEM) {
- var noteIndex = (this._session.styleClass == "note" ? field.getNoteIndex() : 0);
- try {
- this._session.addCitation(i, noteIndex, content);
- } 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(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 {
- var msg = Zotero.getString("integration.missingItem.multiple", (e.citationIndex+1).toString());
- }
- msg += '\n\n'+Zotero.getString('integration.missingItem.description');
- field.select();
- var result = this._doc.displayAlert(msg, 1, 3);
- if(result == 0) { // Cancel
- throw new Zotero.Integration.UserCancelledException();
- } 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
- this._session.reselectItem(e);
- // Now try again
- this._session.addCitation(i, field.getNoteIndex(), content);
- this._doc.activate();
+ }
+
+ if(reselect) {
+ // Ask user what to do with this item
+ if(e.citationLength == 1) {
+ var msg = Zotero.getString("integration.missingItem.single");
+ } else {
+ var msg = Zotero.getString("integration.missingItem.multiple", (e.citationIndex+1).toString());
+ }
+ msg += '\n\n'+Zotero.getString('integration.missingItem.description');
+ field.select();
+ var result = this._doc.displayAlert(msg, 1, 3);
+ if(result == 0) { // Cancel
+ throw new Zotero.Integration.UserCancelledException();
+ } 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
+ this._session.reselectItem(e);
+ // Now try again
+ this._session.addCitation(i, field.getNoteIndex(), content);
+ this._doc.activate();
}
- } else if(e instanceof Zotero.Integration.CorruptFieldException) {
- this._showCorruptFieldError(e, field, i);
- } else {
- throw e;
}
- }
- } else if(type === INTEGRATION_TYPE_BIBLIOGRAPHY) {
- this._bibliographyFields.push(field);
- if(!this._session.bibliographyData && !bibliographyData) {
- bibliographyData = content;
- }
- } else if(type === INTEGRATION_TYPE_TEMP) {
- if(newField && newField.equals(field)) {
- editFieldIndex = i;
- editField = field;
+ } else if(e instanceof Zotero.Integration.CorruptFieldException) {
+ this._showCorruptFieldError(e, field, i);
} else {
- this._deleteFields.push(i);
+ throw e;
}
}
+ } else if(type === INTEGRATION_TYPE_BIBLIOGRAPHY) {
+ this._bibliographyFields.push(field);
+ if(!this._session.bibliographyData && !bibliographyData) {
+ bibliographyData = content;
+ }
}
}
var endTime = (new Date()).getTime();
if(Zotero.Debug.enabled) {
- Zotero.debug("Integration: collected "+this._fields.length+" fields in "+
+ Zotero.debug("Integration: Updated session data for "+fields.length+" fields in "+
(endTime-collectFieldsTime)/1000+"; "+
- 1000/((endTime-collectFieldsTime)/this._fields.length)+" fields/second");
+ 1000/((endTime-collectFieldsTime)/fields.length)+" fields/second");
}
// load uncited items from bibliography
@@ -784,7 +1051,7 @@ Zotero.Integration.Document.prototype._updateSession = function(newField, editFi
}
// if we are reloading this session, assume no item IDs to be updated except for edited items
- if(this._reloadSession) {
+ if(this._session.reload) {
//this._session.restoreProcessorState(); TODO doesn't appear to be working properly
this._session.updateUpdateIndices();
var deleteCitations = this._session.updateCitations();
@@ -792,24 +1059,7 @@ Zotero.Integration.Document.prototype._updateSession = function(newField, editFi
this._session.updateIndices = {};
this._session.updateItemIDs = {};
this._session.bibliographyHasChanged = false;
- }
-
- // create new citation or edit existing citation
- if(editFieldIndex) {
- var [type, editFieldCode] = this._getCodeTypeAndContent(editField.getCode());
- var editCitation = editFieldCode ? this._session.unserializeCitation(editFieldCode, editFieldIndex) : null;
-
- var editNoteIndex = editField.getNoteIndex();
- var added = this._session.editCitation(editFieldIndex, editNoteIndex, editCitation);
- this._doc.activate();
-
- if(!added) {
- if(editFieldCode) { // cancelled editing; just add as if nothing happened
- this._session.addCitation(editFieldIndex, editNoteIndex, editCitation);
- } else { // cancelled creation; delete the citation
- this._session.deleteCitation(editFieldIndex);
- }
- }
+ delete this._session.reload;
}
}
@@ -820,13 +1070,27 @@ Zotero.Integration.Document.prototype._updateSession = function(newField, editFi
* @param {Boolean} [ignoreCitationChanges] Whether to ignore changes to citations that have been
* modified since they were created, instead of showing a warning
*/
-Zotero.Integration.Document.prototype._updateDocument = function(forceCitations, forceBibliography,
+Zotero.Integration.Fields.prototype.updateDocument = function(forceCitations, forceBibliography,
ignoreCitationChanges) {
// update citations
this._session.updateUpdateIndices(forceCitations);
var deleteCitations = this._session.updateCitations();
this._deleteFields = this._deleteFields.concat([i for(i in deleteCitations)]);
+
+ if(this._progressCallback) {
+ var nFieldUpdates = [i for(i in this._session.updateIndices)].length;
+ if(this._session.bibliographyHasChanged || forceBibliography) {
+ nFieldUpdates += this._bibliographyFields.length*5;
+ }
+ }
+
+ var nUpdated=0;
for(var i in this._session.updateIndices) {
+ if(this._progressCallback && nUpdated % 10 == 0) {
+ this._progressCallback(75+(nUpdated/nFieldUpdates)*25);
+ Zotero.wait();
+ }
+
var citation = this._session.citationsByIndex[i];
var field = this._fields[i];
@@ -883,15 +1147,19 @@ Zotero.Integration.Document.prototype._updateDocument = function(forceCitations,
field.setText(formattedCitation, isRich);
}
}
+ nUpdated++;
}
// update bibliographies
- if(this._bibliographyFields.length // if blbliography exists
+ if(this._bibliographyFields.length // if bibliography exists
&& (this._session.bibliographyHasChanged // and bibliography changed
- || forceBibliography)) { // or if we should generate regardless of changes
+ || forceBibliography)) { // or if we should generate regardless of
+ // changes
+ var bibliographyFields = this._bibliographyFields;
+
if(forceBibliography || this._session.bibliographyDataHasChanged) {
var bibliographyData = this._session.getBibliographyData();
- for each(var field in this._bibliographyFields) {
+ for each(var field in bibliographyFields) {
field.setCode("BIBL "+bibliographyData
+(this._session.data.prefs.storeReferences ? " CSL_BIBLIOGRAPHY" : ""));
}
@@ -919,12 +1187,18 @@ Zotero.Integration.Document.prototype._updateDocument = function(forceCitations,
}
// set bibliography text
- for each(var field in this._bibliographyFields) {
+ for each(var field in bibliographyFields) {
+ if(this._progressCallback) {
+ this._progressCallback(75+(nUpdated/nFieldUpdates)*25);
+ Zotero.wait();
+ }
+
if(bibliographyText) {
field.setText(bibliographyText, true);
} else {
field.setText("{Bibliography}", false);
}
+ nUpdated += 5;
}
}
@@ -940,186 +1214,117 @@ Zotero.Integration.Document.prototype._updateDocument = function(forceCitations,
}
/**
- * Adds a citation to the current document.
- */
-Zotero.Integration.Document.prototype.addCitation = function() {
- this._getSession();
-
- var field = this._addField(true);
- if(!field) return;
- field.setCode("TEMP");
-
- this._updateSession(field);
- this._updateDocument();
-}
-
-/**
- * Edits the citation at the cursor position.
- */
-Zotero.Integration.Document.prototype.editCitation = function() {
- this._getSession(true);
-
- var field = this._doc.cursorInField(this._session.data.prefs['fieldType'])
- if(!field) {
- throw new Zotero.Integration.DisplayException("notInCitation");
- }
-
- this._updateSession(false, field);
- this._updateDocument(false, false);
-}
-
-/**
- * Adds a bibliography to the current document.
+ * Brings up the addCitationDialog, prepopulated if a citation is provided
*/
-Zotero.Integration.Document.prototype.addBibliography = function() {
- this._getSession(true);
-
- // Make sure we can have a bibliography
- if(!this._session.data.style.hasBibliography) {
- throw new Zotero.Integration.DisplayException("noBibliography");
- }
-
- // Make sure we have some citations
- this._getFields(true);
+Zotero.Integration.Fields.prototype.addEditCitation = function(field, callback) {
+ var newField, citation,
+ session = this._session,
+ me = this,
+ io = new function() { this.wrappedJSObject = this; }
- var field = this._addField();
- if(!field) return;
- var bibliographyData = this._session.getBibliographyData();
- field.setCode("BIBL "+bibliographyData
- +(this._session.data.prefs.storeReferences ? " CSL_BIBLIOGRAPHY" : ""));
- this._fields.push(field);
-
- this._updateSession();
- this._updateDocument(false, true);
-}
-
-/**
- * Edits bibliography metadata.
- */
-Zotero.Integration.Document.prototype.editBibliography = function() {
- // Make sure we have a bibliography
- this._getFields(true);
- var haveBibliography = false;
- for(var i=this._fields.length-1; i>=0; i--) {
- var code = this._fields[i].getCode();
- var [type, content] = this._getCodeTypeAndContent(code);
- if(type == INTEGRATION_TYPE_BIBLIOGRAPHY) {
- haveBibliography = true;
- break;
+ // if there's already a citation, make sure we have item IDs in addition to keys
+ if(field) {
+ var code = field.getCode();
+ [type, content] = this.getCodeTypeAndContent(code);
+ if(type != INTEGRATION_TYPE_ITEM) {
+ throw new Zotero.Integration.DisplayException("notInCitation");
}
+
+ citation = io.citation = session.unserializeCitation(content);
+
+ var zoteroItem;
+ for each(var citationItem in citation.citationItems) {
+ var item = false;
+ if(!citationItem.id) {
+ zoteroItem = false;
+ if(citationItem.uris) {
+ [zoteroItem, ] = session.uriMap.getZoteroItemForURIs(citationItem.uris);
+ } else if(citationItem.key) {
+ zoteroItem = Zotero.Items.getByKey(citationItem.key);
+ }
+ if(zoteroItem) citationItem.id = zoteroItem.id;
+ }
+ }
+
+ if(citation.properties.dontUpdate) {
+ if(!this._doc.displayAlert(Zotero.getString("integration.citationChanged.edit"),
+ Components.interfaces.zoteroIntegrationDocument.DIALOG_ICON_WARNING,
+ Components.interfaces.zoteroIntegrationDocument.DIALOG_BUTTONS_OK_CANCEL)) {
+ throw new Zotero.Integration.UserCancelledException;
+ }
+ }
+
+ // make sure it's going to get updated
+ delete citation.properties["formattedCitation"];
+ delete citation.properties["plainCitation"];
+ delete citation.properties["dontUpdate"];
+ } else {
+ newField = true;
+ var field = this.addField(true);
+ field.setCode("TEMP");
+
+ citation = io.citation = {"citationItems":{}, "properties":{}};
}
- if(!haveBibliography) {
- throw new Zotero.Integration.DisplayException("mustInsertBibliography");
- }
-
- this._updateSession();
- 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() {
- this._getFields(true);
-
- // Send request, forcing update of citations and bibliography
- this._updateSession();
- this._updateDocument(true, true);
-}
-
-/**
- * Deletes field codes.
- */
-Zotero.Integration.Document.prototype.removeCodes = function() {
- this._getFields(true);
-
- 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();
+ // assign preview function
+ io.previewFunction = function() {
+ throw "Not yet implemented";
+ citation.properties.zoteroIndex = parseInt(index, 10);
+ citation.properties.noteIndex = parseInt(noteIndex, 10);
+ return me._session.previewCitation(io.citation);
+ }
+ // assign sort function
+ io.sort = function() {
+ me._session.previewCitation(io.citation);
+ }
+ // assign accept function
+ io.accept = function(progressCallback) {
+ me._progressCallback = progressCallback;
+
+ if(io.citation.citationItems.length) {
+ // Citation added
+ me.get(function() {
+ me.updateSession();
+ if(fieldIndex !== undefined) {
+ session.addCitation(fieldIndex, field.getNoteIndex(), io.citation);
+ }
+ session.updateIndices[fieldIndex] = true;
+ me.updateDocument();
+
+ callback();
+ });
+ } else if(newField) {
+ // New citation was cancelled
+ field.delete();
+ callback();
}
}
-}
-
-
-/**
- * Displays a dialog to set document preferences (style, footnotes/endnotes, etc.)
- */
-Zotero.Integration.Document.prototype.setDocPrefs = function() {
- this._getFields(false, true);
+ // determine whether citation is sortable in current style
+ io.sortable = session.style.opt.sort_citations;
- try {
- var oldData = this._session.setDocPrefs(this._app.primaryFieldType, this._app.secondaryFieldType);
- } finally {
- this._doc.activate();
- }
- 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();
- var [type, content] = this._getCodeTypeAndContent(fieldCode);
-
- if(convertItems && type === INTEGRATION_TYPE_ITEM) {
- var citation = this._session.unserializeCitation(fieldCode);
- if(!citation.properties.dontUpdate) {
- fieldsToConvert.push(field);
- fieldNoteTypes.push(this._session.data.prefs.noteType);
- }
- } else if(convertBibliographies && type === INTEGRATION_TYPE_BIBLIOGRAPHY) {
- fieldsToConvert.push(field);
- fieldNoteTypes.push(0);
- }
- }
-
- 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;
+ // citeproc-js style object for use of third-party extension
+ io.style = session.style;
+
+ // Find this citation
+ var fieldIndex;
+ this.get(function(fields) {
+ for(var i=0, n=fields.length; i<n; i++) {
+ if(fields[i].equals(field)) {
+ fieldIndex = i;
}
-
- // refresh contents
- this._getFields(true);
- this._updateSession();
- this._updateDocument(true, true, true);
}
+ });
+
+ if(Zotero.Prefs.get("integration.useClassicAddCitationDialog")) {
+ session.displayDialog('chrome://zotero/content/integration/addCitationDialog.xul', 'alwaysRaised,resizable', io, true);
+ } else {
+ var mode = (!Zotero.isMac && Zotero.Prefs.get('integration.keepAddCitationDialogRaised')
+ ? 'popup' : 'alwaysRaised')
+ session.displayDialog('chrome://zotero/content/integration/quickFormat.xul', mode, io, true);
}
}
/**
- * Cleans up any changes made before returning, even if an error occurred
- */
-Zotero.Integration.Document.prototype.cleanup = function() {
- this._doc.cleanup()
-}
-
-/**
- * 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
*/
Zotero.Integration.Session = function() {
@@ -1128,15 +1333,13 @@ Zotero.Integration.Session = function() {
this.omittedItems = {};
this.customBibliographyText = {};
this.reselectedItems = {};
- this.citationIDs = {};
+ this.resetRequest();
}
/**
* Resets per-request variables in the CitationSet
*/
Zotero.Integration.Session.prototype.resetRequest = function(doc) {
- this.citationsByItemID = {};
- this.citationsByIndex = [];
this.embeddedItems = {};
this.embeddedItemsByURI = {};
this.uriMap = new Zotero.Integration.URIMap(this);
@@ -1149,6 +1352,9 @@ Zotero.Integration.Session.prototype.resetRequest = function(doc) {
this.newIndices = {};
this.oldCitationIDs = this.citationIDs;
+
+ this.citationsByItemID = {};
+ this.citationsByIndex = [];
this.citationIDs = {};
this.citationText = {};
@@ -1184,8 +1390,14 @@ Zotero.Integration.Session.prototype.setData = function(data) {
/**
* Displays a dialog in a modal-like fashion without hanging the thread
+ * @param {String} url The chrome:// URI of the window
+ * @param {String} [options] Options to pass to the window
+ * @param {String} [io] Data to pass to the window
+ * @param {Function|Boolean} [async] Function to call when window is closed. If not specified,
+ * function waits to return until the window has been closed. If "true", the function returns
+ * immediately.
*/
-Zotero.Integration.Session.prototype._displayDialog = function(url, options, io) {
+Zotero.Integration.Session.prototype.displayDialog = function(url, options, io, async) {
if(this.doc) this.doc.cleanup();
var allOptions = 'chrome,centerscreen';
@@ -1196,10 +1408,33 @@ Zotero.Integration.Session.prototype._displayDialog = function(url, options, io)
var window = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
.getService(Components.interfaces.nsIWindowWatcher)
.openWindow(null, url, '', allOptions, (io ? io : null));
+ Zotero.Integration.currentWindow = window;
Zotero.Integration.activate(window);
- while(!window.closed) {
- Zotero.mainThread.processNextEvent(true);
- if(window.newWindow) window = window.newWindow;
+
+ if(async) {
+ var listener = function() {
+ if(window.location.toString() === "about:blank") return;
+
+ if(window.newWindow) {
+ window = window.newWindow;
+ Zotero.Integration.currentWindow = window;
+ window.addEventListener("unload", listener, false);
+ return;
+ }
+
+ Zotero.Integration.currentWindow = false;
+ if(async instanceof Function) async();
+ }
+ window.addEventListener("unload", listener, false);
+ } else {
+ while(!window.closed) {
+ Zotero.mainThread.processNextEvent(true);
+ if(window.newWindow) {
+ window = window.newWindow;
+ Zotero.Integration.currentWindow = window;
+ }
+ }
+ Zotero.Integration.currentWindow = false;
}
}
@@ -1220,7 +1455,7 @@ Zotero.Integration.Session.prototype.setDocPrefs = function(primaryFieldType, se
io.storeReferences = this.data.prefs.storeReferences;
}
- this._displayDialog('chrome://zotero/content/integration/integrationDocPrefs.xul', '', io);
+ this.displayDialog('chrome://zotero/content/integration/integrationDocPrefs.xul', '', io);
if(!io.style) throw new Zotero.Integration.UserCancelledException();
// set data
@@ -1254,7 +1489,7 @@ Zotero.Integration.Session.prototype.reselectItem = function(exception) {
io.addBorder = Zotero.isWin;
io.singleSelection = true;
- this._displayDialog('chrome://zotero/content/selectItemsDialog.xul', 'resizable', io);
+ this.displayDialog('chrome://zotero/content/selectItemsDialog.xul', 'resizable', io);
if(io.dataOut && io.dataOut.length) {
var itemID = io.dataOut[0];
@@ -1481,9 +1716,10 @@ Zotero.Integration.Session.prototype.addCitation = function(index, noteIndex, ar
this.newIndices[index] = true;
this.updateIndices[index] = true;
}
- Zotero.debug("Integration: adding citationID "+citation.citationID);
+ Zotero.debug("Integration: Adding citationID "+citation.citationID);
this.citationIDs[citation.citationID] = true;
}
+
/**
* Unserializes a JSON citation into a citation object (sans items)
*/
@@ -1495,7 +1731,7 @@ Zotero.Integration.Session.prototype.unserializeCitation = function(arg, index)
// fix for corrupted fields
var lastBracket = arg.lastIndexOf("}");
if(lastBracket+1 != arg.length) {
- this.updateIndices[index] = true;
+ if(index) this.updateIndices[index] = true;
arg = arg.substr(0, lastBracket+1);
}
@@ -1518,7 +1754,7 @@ Zotero.Integration.Session.prototype.unserializeCitation = function(arg, index)
// fix for uppercase citation codes
if(citation.CITATIONITEMS) {
- this.updateIndices[index] = true;
+ if(index) this.updateIndices[index] = true;
citation.citationItems = [];
for (var i=0; i<citation.CITATIONITEMS.length; i++) {
for (var j in citation.CITATIONITEMS[i]) {
@@ -1599,7 +1835,7 @@ Zotero.Integration.Session.prototype.unserializeCitation = function(arg, index)
}
var citation = {"citationItems":citationItems, properties:{}};
- this.updateIndices[index] = true;
+ if(index) this.updateIndices[index] = true;
}
return citation;
@@ -1941,66 +2177,6 @@ Zotero.Integration.Session.prototype.previewCitation = function(citation) {
Zotero.debug(e);
throw e;
}
-}
-
-/**
- * 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.uris) {
- [zoteroItem, ] = this.uriMap.getZoteroItemForURIs(citationItem.uris);
- } else if(citationItem.key) {
- zoteroItem = Zotero.Items.getByKey(citationItem.key);
- }
- if(zoteroItem) citationItem.id = zoteroItem.id;
- }
- }
- }
-
- // create object to hold citation
- io.citation = (citation ? JSON.parse(JSON.stringify(citation)) : {"citationItems":{}, "properties":{}});
-
- delete io.citation.properties["formattedCitation"];
- delete io.citation.properties["plainCitation"];
- delete io.citation.properties["dontUpdate"];
-
- io.citation.properties.zoteroIndex = parseInt(index, 10);
- io.citation.properties.noteIndex = parseInt(noteIndex, 10);
- // assign preview function
- io.previewFunction = function() {
- return me.previewCitation(io.citation);
- }
- // determine whether citation is sortable in current style
- io.sortable = this.style.opt.sort_citations;
-
- // citeproc-js style object for use of third-party extension
- io.style = this.style;
-
-
- if(Zotero.Prefs.get("integration.useClassicAddCitationDialog")) {
- this._displayDialog('chrome://zotero/content/integration/addCitationDialog.xul', 'alwaysRaised,resizable', io);
- } else {
- var mode = (!Zotero.isMac && Zotero.Prefs.get('integration.keepAddCitationDialogRaised')
- ? 'popup' : 'alwaysRaised')
- this._displayDialog('chrome://zotero/content/integration/quickFormat.xul', mode, io);
- }
-
- if(io.citation.citationItems.length) { // we have an item
- this.addCitation(index, noteIndex, io.citation);
- this.updateIndices[index] = true;
- }
-
- return !!io.citation.citationItems.length;
}
/**
@@ -2012,7 +2188,7 @@ Zotero.Integration.Session.prototype.editBibliography = function() {
this.bibliographyDataHasChanged = this.bibliographyHasChanged = true;
- this._displayDialog('chrome://zotero/content/integration/editBibliographyDialog.xul', 'resizable', io);
+ this.displayDialog('chrome://zotero/content/integration/editBibliographyDialog.xul', 'resizable', io);
}
/**
diff --git a/chrome/locale/en-US/zotero/zotero.properties b/chrome/locale/en-US/zotero/zotero.properties
@@ -611,6 +611,7 @@ integration.corruptBibliography = The Zotero field code for your bibliography
integration.corruptBibliography.description = All items cited in the text will appear in the new bibliography, but modifications you made in the "Edit Bibliography" dialog will be lost.
integration.citationChanged = You have modified this citation since Zotero generated it. Do you want to keep your modifications and prevent future updates?
integration.citationChanged.description = Clicking "Yes" will prevent Zotero from updating this citation if you add additional citations, switch styles, or modify the reference to which it refers. Clicking "No" will erase your changes.
+integration.citationChanged.edit = You have modified this citation since Zotero generated it. Editing will clear your modifications. Do you want to continue?
styles.installStyle = Install style "%1$S" from %2$S?
styles.updateStyle = Update existing style "%1$S" with "%2$S" from %3$S?