Merge pull request #1242 from adomasven/feature/delay-updating-citatations
Refactor integration and delay citation updates
This commit is contained in:
commit
0cd50b5560
|
@ -167,11 +167,24 @@ var Zotero_File_Interface_Bibliography = new function() {
|
||||||
document.getElementById("automaticJournalAbbreviations-checkbox").checked = true;
|
document.getElementById("automaticJournalAbbreviations-checkbox").checked = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (document.getElementById("delayCitationUpdates-checkbox")) {
|
||||||
|
if (_io.delayCitationUpdates) {
|
||||||
|
document.getElementById("delayCitationUpdates-checkbox").checked = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// set style to false, in case this is cancelled
|
// set style to false, in case this is cancelled
|
||||||
_io.style = false;
|
_io.style = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.openHelpLink = function() {
|
||||||
|
var url = "https://www.zotero.org/support/word_processor_plugin_usage";
|
||||||
|
var win = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
||||||
|
.getService(Components.interfaces.nsIWindowMediator)
|
||||||
|
.getMostRecentWindow("navigator:browser");
|
||||||
|
Zotero.launchURL(url);
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called when locale is changed
|
* Called when locale is changed
|
||||||
*/
|
*/
|
||||||
|
@ -211,6 +224,13 @@ var Zotero_File_Interface_Bibliography = new function() {
|
||||||
document.getElementById("automaticJournalAbbreviations-vbox").hidden =
|
document.getElementById("automaticJournalAbbreviations-vbox").hidden =
|
||||||
!selectedStyleObj.usesAbbreviation;
|
!selectedStyleObj.usesAbbreviation;
|
||||||
}
|
}
|
||||||
|
// Hide the delayCitationUpdates checkbox before the prompt is shown
|
||||||
|
document.getElementById("delayCitationUpdates-vbox").hidden = _io.dontAskDelayCitationUpdates == undefined;
|
||||||
|
// Highlight delay citations checkbox after displaying the alert
|
||||||
|
// NOTE: Currently unused
|
||||||
|
if (_io.highlightDelayCitations) {
|
||||||
|
document.getElementById("delayCitationUpdates-vbox").style.border = "1px dashed #e52e2e"
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// For bibliography.xul
|
// For bibliography.xul
|
||||||
|
@ -266,6 +286,7 @@ var Zotero_File_Interface_Bibliography = new function() {
|
||||||
}
|
}
|
||||||
_io.useEndnotes = document.getElementById("displayAs").selectedIndex;
|
_io.useEndnotes = document.getElementById("displayAs").selectedIndex;
|
||||||
_io.fieldType = (document.getElementById("formatUsing").selectedIndex == 0 ? _io.primaryFieldType : _io.secondaryFieldType);
|
_io.fieldType = (document.getElementById("formatUsing").selectedIndex == 0 ? _io.primaryFieldType : _io.secondaryFieldType);
|
||||||
|
_io.delayCitationUpdates = document.getElementById("delayCitationUpdates-checkbox").checked;
|
||||||
}
|
}
|
||||||
|
|
||||||
// remember style and locale if user selected these explicitly
|
// remember style and locale if user selected these explicitly
|
||||||
|
@ -283,8 +304,7 @@ var Zotero_File_Interface_Bibliography = new function() {
|
||||||
document.documentElement.getButton('cancel').click();
|
document.documentElement.getButton('cancel').click();
|
||||||
var win = Zotero.Utilities.Internal.openPreferences('zotero-prefpane-cite', { tab: 'styles-tab' });
|
var win = Zotero.Utilities.Internal.openPreferences('zotero-prefpane-cite', { tab: 'styles-tab' });
|
||||||
if (isDocPrefs) {
|
if (isDocPrefs) {
|
||||||
// TODO: Move activate() code elsewhere
|
Zotero.Utilities.Internal.activate(win);
|
||||||
Zotero.Integration.activate(win);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,10 +59,8 @@ var Zotero_Citation_Dialog = new function () {
|
||||||
this.listItemSelected = listItemSelected;
|
this.listItemSelected = listItemSelected;
|
||||||
this.up = up;
|
this.up = up;
|
||||||
this.down = down;
|
this.down = down;
|
||||||
this.add = add;
|
|
||||||
this.remove = remove;
|
this.remove = remove;
|
||||||
this.setSortToggle = setSortToggle;
|
this.setSortToggle = setSortToggle;
|
||||||
this.citationSortUnsort = citationSortUnsort;
|
|
||||||
this.confirmRegenerate = confirmRegenerate;
|
this.confirmRegenerate = confirmRegenerate;
|
||||||
this.accept = accept;
|
this.accept = accept;
|
||||||
this.cancel = cancel;
|
this.cancel = cancel;
|
||||||
|
@ -373,13 +371,13 @@ var Zotero_Citation_Dialog = new function () {
|
||||||
/*
|
/*
|
||||||
* Adds an item to the multipleSources list
|
* Adds an item to the multipleSources list
|
||||||
*/
|
*/
|
||||||
function add(first_item) {
|
this.add = Zotero.Promise.coroutine(function* (first_item) {
|
||||||
|
|
||||||
var pos, len;
|
var pos, len;
|
||||||
var item = itemsView.getSelectedItems()[0]; // treeview from xpcom/itemTreeView.js
|
var item = itemsView.getSelectedItems()[0]; // treeview from xpcom/itemTreeView.js
|
||||||
|
|
||||||
if (!item) {
|
if (!item) {
|
||||||
sortCitation();
|
yield sortCitation();
|
||||||
_updateAccept();
|
_updateAccept();
|
||||||
_updatePreview();
|
_updatePreview();
|
||||||
return;
|
return;
|
||||||
|
@ -412,11 +410,11 @@ var Zotero_Citation_Dialog = new function () {
|
||||||
_citationList.ensureElementIsVisible(selectionNode);
|
_citationList.ensureElementIsVisible(selectionNode);
|
||||||
|
|
||||||
// allow user to press OK
|
// allow user to press OK
|
||||||
selectionNode = sortCitation(selectionNode);
|
selectionNode = yield sortCitation(selectionNode);
|
||||||
_citationList.selectItem(selectionNode);
|
_citationList.selectItem(selectionNode);
|
||||||
_updateAccept();
|
_updateAccept();
|
||||||
_updatePreview();
|
_updatePreview();
|
||||||
}
|
});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Deletes a citation from the multipleSources list
|
* Deletes a citation from the multipleSources list
|
||||||
|
@ -446,11 +444,11 @@ var Zotero_Citation_Dialog = new function () {
|
||||||
/*
|
/*
|
||||||
* Sorts preview citations, if preview is open.
|
* Sorts preview citations, if preview is open.
|
||||||
*/
|
*/
|
||||||
function citationSortUnsort() {
|
this.citationSortUnsort = Zotero.Promise.coroutine(function* () {
|
||||||
setSortToggle();
|
setSortToggle();
|
||||||
sortCitation();
|
yield sortCitation();
|
||||||
_updatePreview();
|
_updatePreview();
|
||||||
}
|
});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sets the current sort toggle state persistently on the citation.
|
* Sets the current sort toggle state persistently on the citation.
|
||||||
|
@ -468,7 +466,7 @@ var Zotero_Citation_Dialog = new function () {
|
||||||
/*
|
/*
|
||||||
* Sorts the list of citations
|
* Sorts the list of citations
|
||||||
*/
|
*/
|
||||||
function sortCitation(scrollToItem) {
|
var sortCitation = Zotero.Promise.coroutine(function* (scrollToItem) {
|
||||||
if(!_sortCheckbox) return scrollToItem;
|
if(!_sortCheckbox) return scrollToItem;
|
||||||
if(!_sortCheckbox.checked) {
|
if(!_sortCheckbox.checked) {
|
||||||
io.citation.properties.unsorted = true;
|
io.citation.properties.unsorted = true;
|
||||||
|
@ -485,7 +483,7 @@ var Zotero_Citation_Dialog = new function () {
|
||||||
|
|
||||||
// run preview function to re-sort, if it hasn't already been
|
// run preview function to re-sort, if it hasn't already been
|
||||||
// run
|
// run
|
||||||
io.sort();
|
yield io.sort();
|
||||||
|
|
||||||
// add items back to list
|
// add items back to list
|
||||||
scrollToItem = null;
|
scrollToItem = null;
|
||||||
|
@ -502,7 +500,7 @@ var Zotero_Citation_Dialog = new function () {
|
||||||
|
|
||||||
if(scrollToItem) _citationList.ensureElementIsVisible(scrollToItem);
|
if(scrollToItem) _citationList.ensureElementIsVisible(scrollToItem);
|
||||||
return scrollToItem;
|
return scrollToItem;
|
||||||
}
|
});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ask whether to modifiy the preview
|
* Ask whether to modifiy the preview
|
||||||
|
|
|
@ -74,8 +74,8 @@ var Zotero_Bibliography_Dialog = new function () {
|
||||||
if(selectedItemIDs.length) {
|
if(selectedItemIDs.length) {
|
||||||
for (let itemID of selectedItemIDs) {
|
for (let itemID of selectedItemIDs) {
|
||||||
var itemIndexToSelect = false;
|
var itemIndexToSelect = false;
|
||||||
for(var i in bibEditInterface.bibliography[0].entry_ids) {
|
for(var i in bibEditInterface.bib[0].entry_ids) {
|
||||||
if(bibEditInterface.bibliography[0].entry_ids[i].indexOf(itemID) !== -1) {
|
if(bibEditInterface.bib[0].entry_ids[i].indexOf(itemID) !== -1) {
|
||||||
itemIndexToSelect = i;
|
itemIndexToSelect = i;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -254,7 +254,7 @@ var Zotero_Bibliography_Dialog = new function () {
|
||||||
*/
|
*/
|
||||||
function _getSelectedListItemIDs() {
|
function _getSelectedListItemIDs() {
|
||||||
return Array.from(_itemList.selectedItems)
|
return Array.from(_itemList.selectedItems)
|
||||||
.map(item => bibEditInterface.bibliography[0].entry_ids[item.value][0]);
|
.map(item => bibEditInterface.bib[0].entry_ids[item.value][0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -287,8 +287,8 @@ var Zotero_Bibliography_Dialog = new function () {
|
||||||
|
|
||||||
editor.readonly = index === undefined;
|
editor.readonly = index === undefined;
|
||||||
if(index !== undefined) {
|
if(index !== undefined) {
|
||||||
var itemID = bibEditInterface.bibliography[0].entry_ids[index];
|
var itemID = bibEditInterface.bib[0].entry_ids[index];
|
||||||
editor.value = bibEditInterface.bibliography[1][index];
|
editor.value = bibEditInterface.bib[1][index];
|
||||||
_lastSelectedIndex = index;
|
_lastSelectedIndex = index;
|
||||||
_lastSelectedItemID = itemID;
|
_lastSelectedItemID = itemID;
|
||||||
_lastSelectedValue = editor.value;
|
_lastSelectedValue = editor.value;
|
||||||
|
@ -304,7 +304,7 @@ var Zotero_Bibliography_Dialog = new function () {
|
||||||
* loads items from itemSet
|
* loads items from itemSet
|
||||||
*/
|
*/
|
||||||
function _loadItems() {
|
function _loadItems() {
|
||||||
var itemIDs = bibEditInterface.bibliography[0].entry_ids;
|
var itemIDs = bibEditInterface.bib[0].entry_ids;
|
||||||
var items = itemIDs.map(itemID => Zotero.Cite.getItem(itemID[0]));
|
var items = itemIDs.map(itemID => Zotero.Cite.getItem(itemID[0]));
|
||||||
|
|
||||||
// delete all existing items from list
|
// delete all existing items from list
|
||||||
|
|
|
@ -31,10 +31,11 @@
|
||||||
<dialog
|
<dialog
|
||||||
id="zotero-doc-prefs-dialog"
|
id="zotero-doc-prefs-dialog"
|
||||||
orient="vertical"
|
orient="vertical"
|
||||||
buttons="accept,cancel"
|
buttons="accept,cancel,help"
|
||||||
title="&zotero.integration.docPrefs.title;"
|
title="&zotero.integration.docPrefs.title;"
|
||||||
onload="Zotero_File_Interface_Bibliography.init();"
|
onload="Zotero_File_Interface_Bibliography.init();"
|
||||||
ondialogaccept="Zotero_File_Interface_Bibliography.acceptSelection();"
|
ondialogaccept="Zotero_File_Interface_Bibliography.acceptSelection();"
|
||||||
|
ondialoghelp="Zotero_File_Interface_Bibliography.openHelpLink();"
|
||||||
onclose="document.documentElement.cancelDialog(); event.preventDefault(); event.stopPropagation();"
|
onclose="document.documentElement.cancelDialog(); event.preventDefault(); event.stopPropagation();"
|
||||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||||
persist="screenX screenY"
|
persist="screenX screenY"
|
||||||
|
@ -84,5 +85,10 @@
|
||||||
<checkbox id="automaticJournalAbbreviations-checkbox" label="&zotero.integration.prefs.automaticJournalAbbeviations.label;"/>
|
<checkbox id="automaticJournalAbbreviations-checkbox" label="&zotero.integration.prefs.automaticJournalAbbeviations.label;"/>
|
||||||
<description class="radioDescription">&zotero.integration.prefs.automaticJournalAbbeviations.caption;</description>
|
<description class="radioDescription">&zotero.integration.prefs.automaticJournalAbbeviations.caption;</description>
|
||||||
</vbox>
|
</vbox>
|
||||||
|
|
||||||
|
<vbox id="delayCitationUpdates-vbox">
|
||||||
|
<checkbox id="delayCitationUpdates-checkbox" label="&zotero.integration.prefs.delayCitationUpdates.label;" tooltiptext="&zotero.integration.prefs.delayCitationUpdates.tooltip;"/>
|
||||||
|
<description class="radioDescription">&zotero.integration.prefs.delayCitationUpdates.description;</description>
|
||||||
|
</vbox>
|
||||||
</vbox>
|
</vbox>
|
||||||
</dialog>
|
</dialog>
|
|
@ -711,7 +711,7 @@ var Zotero_QuickFormat = new function () {
|
||||||
/**
|
/**
|
||||||
* Converts the selected item to a bubble
|
* Converts the selected item to a bubble
|
||||||
*/
|
*/
|
||||||
function _bubbleizeSelected() {
|
var _bubbleizeSelected = Zotero.Promise.coroutine(function* () {
|
||||||
if(!referenceBox.hasChildNodes() || !referenceBox.selectedItem) return false;
|
if(!referenceBox.hasChildNodes() || !referenceBox.selectedItem) return false;
|
||||||
|
|
||||||
var citationItem = {"id":referenceBox.selectedItem.getAttribute("zotero-item")};
|
var citationItem = {"id":referenceBox.selectedItem.getAttribute("zotero-item")};
|
||||||
|
@ -734,11 +734,11 @@ var Zotero_QuickFormat = new function () {
|
||||||
node.nodeValue = "";
|
node.nodeValue = "";
|
||||||
var bubble = _insertBubble(citationItem, node);
|
var bubble = _insertBubble(citationItem, node);
|
||||||
_clearEntryList();
|
_clearEntryList();
|
||||||
_previewAndSort();
|
yield _previewAndSort();
|
||||||
_refocusQfe();
|
_refocusQfe();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ignores clicks (for use on separators in the rich list box)
|
* Ignores clicks (for use on separators in the rich list box)
|
||||||
|
@ -902,13 +902,13 @@ var Zotero_QuickFormat = new function () {
|
||||||
/**
|
/**
|
||||||
* Generates the preview and sorts citations
|
* Generates the preview and sorts citations
|
||||||
*/
|
*/
|
||||||
function _previewAndSort() {
|
var _previewAndSort = Zotero.Promise.coroutine(function* () {
|
||||||
var shouldKeepSorted = keepSorted.hasAttribute("checked"),
|
var shouldKeepSorted = keepSorted.hasAttribute("checked"),
|
||||||
editorShowing = showEditor.hasAttribute("checked");
|
editorShowing = showEditor.hasAttribute("checked");
|
||||||
if(!shouldKeepSorted && !editorShowing) return;
|
if(!shouldKeepSorted && !editorShowing) return;
|
||||||
|
|
||||||
_updateCitationObject();
|
_updateCitationObject();
|
||||||
io.sort();
|
yield io.sort();
|
||||||
if(shouldKeepSorted) {
|
if(shouldKeepSorted) {
|
||||||
// means we need to resort citations
|
// means we need to resort citations
|
||||||
_clearCitation();
|
_clearCitation();
|
||||||
|
@ -920,7 +920,7 @@ var Zotero_QuickFormat = new function () {
|
||||||
|
|
||||||
_moveCursorToEnd();
|
_moveCursorToEnd();
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows the citation properties panel for a given bubble
|
* Shows the citation properties panel for a given bubble
|
||||||
|
@ -1071,7 +1071,7 @@ var Zotero_QuickFormat = new function () {
|
||||||
/**
|
/**
|
||||||
* Handle return or escape
|
* Handle return or escape
|
||||||
*/
|
*/
|
||||||
function _onQuickSearchKeyPress(event) {
|
var _onQuickSearchKeyPress = Zotero.Promise.coroutine(function* (event) {
|
||||||
// Prevent hang if another key is pressed after Enter
|
// Prevent hang if another key is pressed after Enter
|
||||||
// https://forums.zotero.org/discussion/59157/
|
// https://forums.zotero.org/discussion/59157/
|
||||||
if (accepted) {
|
if (accepted) {
|
||||||
|
@ -1083,7 +1083,7 @@ var Zotero_QuickFormat = new function () {
|
||||||
var keyCode = event.keyCode;
|
var keyCode = event.keyCode;
|
||||||
if (keyCode === event.DOM_VK_RETURN) {
|
if (keyCode === event.DOM_VK_RETURN) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if(!_bubbleizeSelected() && !_getEditorContent()) {
|
if(!(yield _bubbleizeSelected()) && !_getEditorContent()) {
|
||||||
_accept();
|
_accept();
|
||||||
}
|
}
|
||||||
} else if(keyCode === event.DOM_VK_TAB || event.charCode === 59 /* ; */) {
|
} else if(keyCode === event.DOM_VK_TAB || event.charCode === 59 /* ; */) {
|
||||||
|
@ -1162,7 +1162,7 @@ var Zotero_QuickFormat = new function () {
|
||||||
} else {
|
} else {
|
||||||
_resetSearchTimer();
|
_resetSearchTimer();
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a dummy element to make dragging work
|
* Adds a dummy element to make dragging work
|
||||||
|
@ -1190,7 +1190,7 @@ var Zotero_QuickFormat = new function () {
|
||||||
/**
|
/**
|
||||||
* Replaces the dummy element with a node to make dropping work
|
* Replaces the dummy element with a node to make dropping work
|
||||||
*/
|
*/
|
||||||
function _onBubbleDrop(event) {
|
var _onBubbleDrop = Zotero.Promise.coroutine(function* (event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
|
@ -1208,9 +1208,9 @@ var Zotero_QuickFormat = new function () {
|
||||||
keepSorted.removeAttribute("checked");
|
keepSorted.removeAttribute("checked");
|
||||||
}
|
}
|
||||||
|
|
||||||
_previewAndSort();
|
yield _previewAndSort();
|
||||||
_moveCursorToEnd();
|
_moveCursorToEnd();
|
||||||
}
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle a click on a bubble
|
* Handle a click on a bubble
|
||||||
|
@ -1333,7 +1333,7 @@ var Zotero_QuickFormat = new function () {
|
||||||
pane.selectItem(id);
|
pane.selectItem(id);
|
||||||
|
|
||||||
// Pull window to foreground
|
// Pull window to foreground
|
||||||
Zotero.Integration.activate(pane.document.defaultView);
|
Zotero.Utilities.Internal.activate(pane.document.defaultView);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -16,13 +16,13 @@ Zotero.Cite = {
|
||||||
* Remove specified item IDs in-place from a citeproc-js bibliography object returned
|
* Remove specified item IDs in-place from a citeproc-js bibliography object returned
|
||||||
* by makeBibliography()
|
* by makeBibliography()
|
||||||
* @param {bib} citeproc-js bibliography object
|
* @param {bib} citeproc-js bibliography object
|
||||||
* @param {Array} itemsToRemove Array of items to remove
|
* @param {Set} itemsToRemove Set of items to remove
|
||||||
*/
|
*/
|
||||||
"removeFromBibliography":function(bib, itemsToRemove) {
|
"removeFromBibliography":function(bib, itemsToRemove) {
|
||||||
var removeItems = [];
|
var removeItems = [];
|
||||||
for(let i in bib[0].entry_ids) {
|
for(let i in bib[0].entry_ids) {
|
||||||
for(let j in bib[0].entry_ids[i]) {
|
for(let j in bib[0].entry_ids[i]) {
|
||||||
if(itemsToRemove[bib[0].entry_ids[i][j]]) {
|
if(itemsToRemove.has(`${bib[0].entry_ids[i][j]}`)) {
|
||||||
removeItems.push(i);
|
removeItems.push(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -303,7 +303,7 @@ Zotero.Cite = {
|
||||||
session = Zotero.Integration.sessions[sessionID],
|
session = Zotero.Integration.sessions[sessionID],
|
||||||
item;
|
item;
|
||||||
if(session) {
|
if(session) {
|
||||||
item = session.embeddedZoteroItems[id.substr(slashIndex+1)];
|
item = session.embeddedItems[id.substr(slashIndex+1)];
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!item) {
|
if(!item) {
|
||||||
|
@ -526,7 +526,7 @@ Zotero.Cite.System.prototype = {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!zoteroItem) {
|
if(!zoteroItem) {
|
||||||
throw "Zotero.Cite.System.retrieveItem called on non-item "+item;
|
throw new Error("Zotero.Cite.System.retrieveItem called on non-item "+item);
|
||||||
}
|
}
|
||||||
|
|
||||||
var cslItem = Zotero.Utilities.itemToCSLJSON(zoteroItem);
|
var cslItem = Zotero.Utilities.itemToCSLJSON(zoteroItem);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -884,7 +884,7 @@ Zotero.Server.Connector.IncompatibleVersion.prototype = {
|
||||||
sendResponseCallback(404);
|
sendResponseCallback(404);
|
||||||
if(Zotero.Server.Connector.IncompatibleVersion._errorShown) return;
|
if(Zotero.Server.Connector.IncompatibleVersion._errorShown) return;
|
||||||
|
|
||||||
Zotero.Integration.activate();
|
Zotero.Utilities.Internal.activate();
|
||||||
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].
|
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].
|
||||||
createInstance(Components.interfaces.nsIPromptService);
|
createInstance(Components.interfaces.nsIPromptService);
|
||||||
ps.alert(null,
|
ps.alert(null,
|
||||||
|
|
|
@ -1266,6 +1266,382 @@ Zotero.Utilities.Internal = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs an AppleScript on OS X
|
||||||
|
*
|
||||||
|
* @param script {String}
|
||||||
|
* @param block {Boolean} Whether the script should block until the process is finished.
|
||||||
|
*/
|
||||||
|
Zotero.Utilities.Internal.executeAppleScript = new function() {
|
||||||
|
var _osascriptFile;
|
||||||
|
|
||||||
|
return function(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);
|
||||||
|
try {
|
||||||
|
proc.run(!!block, ['-e', script], 2);
|
||||||
|
} catch(e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activates Firefox
|
||||||
|
*/
|
||||||
|
Zotero.Utilities.Internal.activate = new function() {
|
||||||
|
// For Carbon and X11
|
||||||
|
var _carbon, ProcessSerialNumber, SetFrontProcessWithOptions;
|
||||||
|
var _x11, _x11Display, _x11RootWindow, XClientMessageEvent, XFetchName, XFree, XQueryTree,
|
||||||
|
XOpenDisplay, XCloseDisplay, XFlush, XDefaultRootWindow, XInternAtom, XSendEvent,
|
||||||
|
XMapRaised, XGetWindowProperty, X11Atom, X11Bool, X11Display, X11Window, X11Status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bring a window to the foreground by interfacing directly with X11
|
||||||
|
*/
|
||||||
|
function _X11BringToForeground(win, intervalID) {
|
||||||
|
var windowTitle = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
|
.getInterface(Ci.nsIWebNavigation).QueryInterface(Ci.nsIBaseWindow).title;
|
||||||
|
|
||||||
|
var x11Window = _X11FindWindow(_x11RootWindow, windowTitle);
|
||||||
|
if(!x11Window) return;
|
||||||
|
win.clearInterval(intervalID);
|
||||||
|
|
||||||
|
var event = new XClientMessageEvent();
|
||||||
|
event.type = 33; /* ClientMessage*/
|
||||||
|
event.serial = 0;
|
||||||
|
event.send_event = 1;
|
||||||
|
event.message_type = XInternAtom(_x11Display, "_NET_ACTIVE_WINDOW", 0);
|
||||||
|
event.display = _x11Display;
|
||||||
|
event.window = x11Window;
|
||||||
|
event.format = 32;
|
||||||
|
event.l0 = 2;
|
||||||
|
var mask = 1<<20 /* SubstructureRedirectMask */ | 1<<19 /* SubstructureNotifyMask */;
|
||||||
|
|
||||||
|
if(XSendEvent(_x11Display, _x11RootWindow, 0, mask, event.address())) {
|
||||||
|
XMapRaised(_x11Display, x11Window);
|
||||||
|
XFlush(_x11Display);
|
||||||
|
Zotero.debug("Integration: Activated successfully");
|
||||||
|
} else {
|
||||||
|
Zotero.debug("Integration: An error occurred activating the window");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find an X11 window given a name
|
||||||
|
*/
|
||||||
|
function _X11FindWindow(w, searchName) {
|
||||||
|
Components.utils.import("resource://gre/modules/ctypes.jsm");
|
||||||
|
|
||||||
|
var res = _X11GetProperty(w, "_NET_CLIENT_LIST", 33 /** XA_WINDOW **/)
|
||||||
|
|| _X11GetProperty(w, "_WIN_CLIENT_LIST", 6 /** XA_CARDINAL **/);
|
||||||
|
if(!res) return false;
|
||||||
|
|
||||||
|
var nClients = res[1],
|
||||||
|
clientList = ctypes.cast(res[0], X11Window.array(nClients).ptr).contents,
|
||||||
|
foundName = new ctypes.char.ptr();
|
||||||
|
for(var i=0; i<nClients; i++) {
|
||||||
|
if(XFetchName(_x11Display, clientList.addressOfElement(i).contents,
|
||||||
|
foundName.address())) {
|
||||||
|
var foundNameString = undefined;
|
||||||
|
try {
|
||||||
|
foundNameString = foundName.readString();
|
||||||
|
} catch(e) {}
|
||||||
|
XFree(foundName);
|
||||||
|
if(foundNameString === searchName) return clientList.addressOfElement(i).contents;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XFree(res[0]);
|
||||||
|
|
||||||
|
return foundWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a property from an X11 window
|
||||||
|
*/
|
||||||
|
function _X11GetProperty(win, propertyName, propertyType) {
|
||||||
|
Components.utils.import("resource://gre/modules/ctypes.jsm");
|
||||||
|
|
||||||
|
var returnType = new X11Atom(),
|
||||||
|
returnFormat = new ctypes.int(),
|
||||||
|
nItemsReturned = new ctypes.unsigned_long(),
|
||||||
|
nBytesAfterReturn = new ctypes.unsigned_long(),
|
||||||
|
data = new ctypes.char.ptr();
|
||||||
|
if(!XGetWindowProperty(_x11Display, win, XInternAtom(_x11Display, propertyName, 0), 0, 1024,
|
||||||
|
0, propertyType, returnType.address(), returnFormat.address(),
|
||||||
|
nItemsReturned.address(), nBytesAfterReturn.address(), data.address())) {
|
||||||
|
var nElements = ctypes.cast(nItemsReturned, ctypes.unsigned_int).value;
|
||||||
|
if(nElements) return [data, nElements];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return function(win) {
|
||||||
|
if (Zotero.isMac) {
|
||||||
|
const BUNDLE_IDS = {
|
||||||
|
"Zotero":"org.zotero.zotero",
|
||||||
|
"Firefox":"org.mozilla.firefox",
|
||||||
|
"Aurora":"org.mozilla.aurora",
|
||||||
|
"Nightly":"org.mozilla.nightly"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (win) {
|
||||||
|
Components.utils.import("resource://gre/modules/ctypes.jsm");
|
||||||
|
win.focus();
|
||||||
|
|
||||||
|
if(!_carbon) {
|
||||||
|
_carbon = ctypes.open("/System/Library/Frameworks/Carbon.framework/Carbon");
|
||||||
|
/*
|
||||||
|
* struct ProcessSerialNumber {
|
||||||
|
* unsigned long highLongOfPSN;
|
||||||
|
* unsigned long lowLongOfPSN;
|
||||||
|
* };
|
||||||
|
*/
|
||||||
|
ProcessSerialNumber = new ctypes.StructType("ProcessSerialNumber",
|
||||||
|
[{"highLongOfPSN":ctypes.uint32_t}, {"lowLongOfPSN":ctypes.uint32_t}]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* OSStatus SetFrontProcessWithOptions (
|
||||||
|
* const ProcessSerialNumber *inProcess,
|
||||||
|
* OptionBits inOptions
|
||||||
|
* );
|
||||||
|
*/
|
||||||
|
SetFrontProcessWithOptions = _carbon.declare("SetFrontProcessWithOptions",
|
||||||
|
ctypes.default_abi, ctypes.int32_t, ProcessSerialNumber.ptr,
|
||||||
|
ctypes.uint32_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
var psn = new ProcessSerialNumber();
|
||||||
|
psn.highLongOfPSN = 0;
|
||||||
|
psn.lowLongOfPSN = 2 // kCurrentProcess
|
||||||
|
|
||||||
|
win.addEventListener("load", function() {
|
||||||
|
var res = SetFrontProcessWithOptions(
|
||||||
|
psn.address(),
|
||||||
|
1 // kSetFrontProcessFrontWindowOnly = (1 << 0)
|
||||||
|
);
|
||||||
|
}, false);
|
||||||
|
} else {
|
||||||
|
Zotero.Utilities.Internal.executeAppleScript('tell application id "'+BUNDLE_IDS[Zotero.appName]+'" to activate');
|
||||||
|
}
|
||||||
|
} else if(!Zotero.isWin && win) {
|
||||||
|
Components.utils.import("resource://gre/modules/ctypes.jsm");
|
||||||
|
|
||||||
|
if(_x11 === false) return;
|
||||||
|
if(!_x11) {
|
||||||
|
try {
|
||||||
|
_x11 = ctypes.open("libX11.so.6");
|
||||||
|
} catch(e) {
|
||||||
|
try {
|
||||||
|
var libName = ctypes.libraryName("X11");
|
||||||
|
} catch(e) {
|
||||||
|
_x11 = false;
|
||||||
|
Zotero.debug("Integration: Could not get libX11 name; not activating");
|
||||||
|
Zotero.logError(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
_x11 = ctypes.open(libName);
|
||||||
|
} catch(e) {
|
||||||
|
_x11 = false;
|
||||||
|
Zotero.debug("Integration: Could not open "+libName+"; not activating");
|
||||||
|
Zotero.logError(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
X11Atom = ctypes.unsigned_long;
|
||||||
|
X11Bool = ctypes.int;
|
||||||
|
X11Display = new ctypes.StructType("Display");
|
||||||
|
X11Window = ctypes.unsigned_long;
|
||||||
|
X11Status = ctypes.int;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* typedef struct {
|
||||||
|
* int type;
|
||||||
|
* unsigned long serial; / * # of last request processed by server * /
|
||||||
|
* Bool send_event; / * true if this came from a SendEvent request * /
|
||||||
|
* Display *display; / * Display the event was read from * /
|
||||||
|
* Window window;
|
||||||
|
* Atom message_type;
|
||||||
|
* int format;
|
||||||
|
* union {
|
||||||
|
* char b[20];
|
||||||
|
* short s[10];
|
||||||
|
* long l[5];
|
||||||
|
* } data;
|
||||||
|
* } XClientMessageEvent;
|
||||||
|
*/
|
||||||
|
XClientMessageEvent = new ctypes.StructType("XClientMessageEvent",
|
||||||
|
[
|
||||||
|
{"type":ctypes.int},
|
||||||
|
{"serial":ctypes.unsigned_long},
|
||||||
|
{"send_event":X11Bool},
|
||||||
|
{"display":X11Display.ptr},
|
||||||
|
{"window":X11Window},
|
||||||
|
{"message_type":X11Atom},
|
||||||
|
{"format":ctypes.int},
|
||||||
|
{"l0":ctypes.long},
|
||||||
|
{"l1":ctypes.long},
|
||||||
|
{"l2":ctypes.long},
|
||||||
|
{"l3":ctypes.long},
|
||||||
|
{"l4":ctypes.long}
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Status XFetchName(
|
||||||
|
* Display* display,
|
||||||
|
* Window w,
|
||||||
|
* char** window_name_return
|
||||||
|
* );
|
||||||
|
*/
|
||||||
|
XFetchName = _x11.declare("XFetchName", ctypes.default_abi, X11Status,
|
||||||
|
X11Display.ptr, X11Window, ctypes.char.ptr.ptr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Status XQueryTree(
|
||||||
|
* Display* display,
|
||||||
|
* Window w,
|
||||||
|
* Window* root_return,
|
||||||
|
* Window* parent_return,
|
||||||
|
* Window** children_return,
|
||||||
|
* unsigned int* nchildren_return
|
||||||
|
* );
|
||||||
|
*/
|
||||||
|
XQueryTree = _x11.declare("XQueryTree", ctypes.default_abi, X11Status,
|
||||||
|
X11Display.ptr, X11Window, X11Window.ptr, X11Window.ptr, X11Window.ptr.ptr,
|
||||||
|
ctypes.unsigned_int.ptr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* int XFree(
|
||||||
|
* void* data
|
||||||
|
* );
|
||||||
|
*/
|
||||||
|
XFree = _x11.declare("XFree", ctypes.default_abi, ctypes.int, ctypes.voidptr_t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Display *XOpenDisplay(
|
||||||
|
* _Xconst char* display_name
|
||||||
|
* );
|
||||||
|
*/
|
||||||
|
XOpenDisplay = _x11.declare("XOpenDisplay", ctypes.default_abi, X11Display.ptr,
|
||||||
|
ctypes.char.ptr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* int XCloseDisplay(
|
||||||
|
* Display* display
|
||||||
|
* );
|
||||||
|
*/
|
||||||
|
XCloseDisplay = _x11.declare("XCloseDisplay", ctypes.default_abi, ctypes.int,
|
||||||
|
X11Display.ptr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* int XFlush(
|
||||||
|
* Display* display
|
||||||
|
* );
|
||||||
|
*/
|
||||||
|
XFlush = _x11.declare("XFlush", ctypes.default_abi, ctypes.int, X11Display.ptr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Window XDefaultRootWindow(
|
||||||
|
* Display* display
|
||||||
|
* );
|
||||||
|
*/
|
||||||
|
XDefaultRootWindow = _x11.declare("XDefaultRootWindow", ctypes.default_abi,
|
||||||
|
X11Window, X11Display.ptr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Atom XInternAtom(
|
||||||
|
* Display* display,
|
||||||
|
* _Xconst char* atom_name,
|
||||||
|
* Bool only_if_exists
|
||||||
|
* );
|
||||||
|
*/
|
||||||
|
XInternAtom = _x11.declare("XInternAtom", ctypes.default_abi, X11Atom,
|
||||||
|
X11Display.ptr, ctypes.char.ptr, X11Bool);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Status XSendEvent(
|
||||||
|
* Display* display,
|
||||||
|
* Window w,
|
||||||
|
* Bool propagate,
|
||||||
|
* long event_mask,
|
||||||
|
* XEvent* event_send
|
||||||
|
* );
|
||||||
|
*/
|
||||||
|
XSendEvent = _x11.declare("XSendEvent", ctypes.default_abi, X11Status,
|
||||||
|
X11Display.ptr, X11Window, X11Bool, ctypes.long, XClientMessageEvent.ptr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* int XMapRaised(
|
||||||
|
* Display* display,
|
||||||
|
* Window w
|
||||||
|
* );
|
||||||
|
*/
|
||||||
|
XMapRaised = _x11.declare("XMapRaised", ctypes.default_abi, ctypes.int,
|
||||||
|
X11Display.ptr, X11Window);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* extern int XGetWindowProperty(
|
||||||
|
* Display* display,
|
||||||
|
* Window w,
|
||||||
|
* Atom property,
|
||||||
|
* long long_offset,
|
||||||
|
* long long_length,
|
||||||
|
* Bool delete,
|
||||||
|
* Atom req_type,
|
||||||
|
* Atom* actual_type_return,
|
||||||
|
* int* actual_format_return,
|
||||||
|
* unsigned long* nitems_return,
|
||||||
|
* unsigned long* bytes_after_return,
|
||||||
|
* unsigned char** prop_return
|
||||||
|
* );
|
||||||
|
*/
|
||||||
|
XGetWindowProperty = _x11.declare("XGetWindowProperty", ctypes.default_abi,
|
||||||
|
ctypes.int, X11Display.ptr, X11Window, X11Atom, ctypes.long, ctypes.long,
|
||||||
|
X11Bool, X11Atom, X11Atom.ptr, ctypes.int.ptr, ctypes.unsigned_long.ptr,
|
||||||
|
ctypes.unsigned_long.ptr, ctypes.char.ptr.ptr);
|
||||||
|
|
||||||
|
|
||||||
|
_x11Display = XOpenDisplay(null);
|
||||||
|
if(!_x11Display) {
|
||||||
|
Zotero.debug("Integration: Could not open display; not activating");
|
||||||
|
_x11 = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Zotero.addShutdownListener(function() {
|
||||||
|
XCloseDisplay(_x11Display);
|
||||||
|
});
|
||||||
|
|
||||||
|
_x11RootWindow = XDefaultRootWindow(_x11Display);
|
||||||
|
if(!_x11RootWindow) {
|
||||||
|
Zotero.debug("Integration: Could not get root window; not activating");
|
||||||
|
_x11 = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
win.addEventListener("load", function() {
|
||||||
|
var intervalID;
|
||||||
|
intervalID = win.setInterval(function() {
|
||||||
|
_X11BringToForeground(win, intervalID);
|
||||||
|
}, 50);
|
||||||
|
}, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base64 encode / decode
|
* Base64 encode / decode
|
||||||
* From http://www.webtoolkit.info/
|
* From http://www.webtoolkit.info/
|
||||||
|
|
|
@ -231,6 +231,10 @@
|
||||||
<!ENTITY zotero.integration.prefs.bookmarks.label "Bookmarks">
|
<!ENTITY zotero.integration.prefs.bookmarks.label "Bookmarks">
|
||||||
<!ENTITY zotero.integration.prefs.bookmarks.caption "Bookmarks can be shared between Word and LibreOffice, but may cause errors if accidentally modified and cannot be inserted into footnotes.">
|
<!ENTITY zotero.integration.prefs.bookmarks.caption "Bookmarks can be shared between Word and LibreOffice, but may cause errors if accidentally modified and cannot be inserted into footnotes.">
|
||||||
|
|
||||||
|
<!ENTITY zotero.integration.prefs.delayCitationUpdates.label "Delay citation updates until manual refresh">
|
||||||
|
<!ENTITY zotero.integration.prefs.delayCitationUpdates.tooltip "Citations with pending updates are visually highlighted">
|
||||||
|
<!ENTITY zotero.integration.prefs.delayCitationUpdates.description "Delaying updates can speed up citation insertion in large documents.">
|
||||||
|
|
||||||
|
|
||||||
<!ENTITY zotero.integration.prefs.automaticJournalAbbeviations.label "Use MEDLINE journal abbreviations">
|
<!ENTITY zotero.integration.prefs.automaticJournalAbbeviations.label "Use MEDLINE journal abbreviations">
|
||||||
<!ENTITY zotero.integration.prefs.automaticJournalAbbeviations.caption "The “Journal Abbr” field will be ignored.">
|
<!ENTITY zotero.integration.prefs.automaticJournalAbbeviations.caption "The “Journal Abbr” field will be ignored.">
|
||||||
|
|
|
@ -870,6 +870,8 @@ integration.corruptBibliography.description = All items cited in the text will a
|
||||||
integration.citationChanged = You have modified this citation since Zotero generated it. Do you want to keep your modifications and prevent future updates?
|
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 item to which it refers. Clicking "No" will erase your changes.
|
integration.citationChanged.description = Clicking "Yes" will prevent Zotero from updating this citation if you add additional citations, switch styles, or modify the item 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?
|
integration.citationChanged.edit = You have modified this citation since Zotero generated it. Editing will clear your modifications. Do you want to continue?
|
||||||
|
integration.delayCitationUpdates.alert = Updating citations in this document is taking a long time. Would you like to delay citation updates until manual refresh?\n\nYou can change this setting later in the document preferences.
|
||||||
|
integration.delayCitationUpdates.bibliography = Delayed citing mode is enabled. To see the bibliography click Refresh in Zotero plugin.
|
||||||
|
|
||||||
styles.install.title = Install Style
|
styles.install.title = Install Style
|
||||||
styles.install.unexpectedError = An unexpected error occurred while installing "%1$S"
|
styles.install.unexpectedError = An unexpected error occurred while installing "%1$S"
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
describe("Zotero.Integration", function () {
|
describe("Zotero.Integration", function () {
|
||||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
const INTEGRATION_TYPE_ITEM = 1;
|
||||||
|
const INTEGRATION_TYPE_BIBLIOGRAPHY = 2;
|
||||||
|
const INTEGRATION_TYPE_TEMP = 3;
|
||||||
/**
|
/**
|
||||||
* To be used as a reference for Zotero-Word Integration plugins
|
* To be used as a reference for Zotero-Word Integration plugins
|
||||||
*/
|
*/
|
||||||
|
@ -235,6 +238,7 @@ describe("Zotero.Integration", function () {
|
||||||
if (typeof docID === "undefined") {
|
if (typeof docID === "undefined") {
|
||||||
throw new Error(`docID cannot be undefined`)
|
throw new Error(`docID cannot be undefined`)
|
||||||
}
|
}
|
||||||
|
Zotero.debug(`execCommand '${command}': ${docID}`, 2);
|
||||||
return Zotero.Integration.execCommand("dummy", command, docID);
|
return Zotero.Integration.execCommand("dummy", command, docID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,21 +277,13 @@ describe("Zotero.Integration", function () {
|
||||||
|
|
||||||
function setAddEditItems(items) {
|
function setAddEditItems(items) {
|
||||||
if (items.length == undefined) items = [items];
|
if (items.length == undefined) items = [items];
|
||||||
dialogResults.quickFormat = function(doc, dialogName) {
|
dialogResults.quickFormat = function(dialogName, io) {
|
||||||
var citationItems = items.map((i) => {return {id: i.id} });
|
io.citation.citationItems = items.map(function(item) {
|
||||||
var field = doc.insertField("Field", 0);
|
item = Zotero.Cite.getItem(item.id);
|
||||||
field.setCode('TEMP');
|
return {id: item.id, uris: item.cslURIs, itemData: item.cslItemData};
|
||||||
var integrationDoc = addEditCitationSpy.lastCall.thisValue;
|
});
|
||||||
var fieldGetter = new Zotero.Integration.Fields(integrationDoc._session, integrationDoc._doc, () => 0);
|
io._acceptDeferred.resolve(() => {});
|
||||||
var io = new Zotero.Integration.CitationEditInterface(
|
};
|
||||||
{ citationItems, properties: {} },
|
|
||||||
field,
|
|
||||||
fieldGetter,
|
|
||||||
integrationDoc._session
|
|
||||||
);
|
|
||||||
io._acceptDeferred.resolve();
|
|
||||||
return io;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
before(function* () {
|
before(function* () {
|
||||||
|
@ -296,7 +292,10 @@ describe("Zotero.Integration", function () {
|
||||||
|
|
||||||
testItems = [];
|
testItems = [];
|
||||||
for (let i = 0; i < 5; i++) {
|
for (let i = 0; i < 5; i++) {
|
||||||
testItems.push(yield createDataObject('item', {libraryID: Zotero.Libraries.userLibraryID}));
|
let testItem = yield createDataObject('item', {libraryID: Zotero.Libraries.userLibraryID});
|
||||||
|
testItem.setField('title', `title${1}`);
|
||||||
|
testItem.setCreator(0, {creatorType: 'author', name: `Author No${i}`});
|
||||||
|
testItems.push(testItem);
|
||||||
}
|
}
|
||||||
setAddEditItems(testItems[0]);
|
setAddEditItems(testItems[0]);
|
||||||
|
|
||||||
|
@ -313,16 +312,18 @@ describe("Zotero.Integration", function () {
|
||||||
// possible bug that reset() erases callsFake.
|
// possible bug that reset() erases callsFake.
|
||||||
// @NOTE: https://github.com/sinonjs/sinon/issues/1341
|
// @NOTE: https://github.com/sinonjs/sinon/issues/1341
|
||||||
// displayDialogStub.callsFake(function(doc, dialogName, prefs, io) {
|
// displayDialogStub.callsFake(function(doc, dialogName, prefs, io) {
|
||||||
function(doc, dialogName, prefs, io) {
|
function(dialogName, prefs, io) {
|
||||||
|
Zotero.debug(`Display dialog: ${dialogName}`, 2);
|
||||||
var ioResult = dialogResults[dialogName.substring(dialogName.lastIndexOf('/')+1, dialogName.length-4)];
|
var ioResult = dialogResults[dialogName.substring(dialogName.lastIndexOf('/')+1, dialogName.length-4)];
|
||||||
if (typeof ioResult == 'function') {
|
if (typeof ioResult == 'function') {
|
||||||
ioResult = ioResult(doc, dialogName);
|
ioResult(dialogName, io);
|
||||||
|
} else {
|
||||||
|
Object.assign(io, ioResult);
|
||||||
}
|
}
|
||||||
Object.assign(io, ioResult);
|
|
||||||
return Zotero.Promise.resolve();
|
return Zotero.Promise.resolve();
|
||||||
});
|
});
|
||||||
|
|
||||||
addEditCitationSpy = sinon.spy(Zotero.Integration.Document.prototype, 'addEditCitation');
|
addEditCitationSpy = sinon.spy(Zotero.Integration.Interface.prototype, 'addEditCitation');
|
||||||
});
|
});
|
||||||
|
|
||||||
after(function() {
|
after(function() {
|
||||||
|
@ -331,8 +332,8 @@ describe("Zotero.Integration", function () {
|
||||||
addEditCitationSpy.restore();
|
addEditCitationSpy.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Document', function() {
|
describe('Interface', function() {
|
||||||
describe('#addEditCitation', function() {
|
describe('#execCommand', function() {
|
||||||
var setDocumentDataSpy;
|
var setDocumentDataSpy;
|
||||||
var docID = this.fullTitle();
|
var docID = this.fullTitle();
|
||||||
|
|
||||||
|
@ -348,18 +349,7 @@ describe("Zotero.Integration", function () {
|
||||||
setDocumentDataSpy.restore();
|
setDocumentDataSpy.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call doc.setDocumentData on a fresh document', function* () {
|
it('should call doc.setDocumentData once', function* () {
|
||||||
yield execCommand('addEditCitation', docID);
|
|
||||||
assert.isTrue(setDocumentDataSpy.calledOnce);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not call doc.setDocumentData on subsequent invocations', function* () {
|
|
||||||
yield execCommand('addEditCitation', docID);
|
|
||||||
assert.isFalse(setDocumentDataSpy.called);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call doc.setDocumentData when document communicates for first time since restart to write new sessionID', function* () {
|
|
||||||
Zotero.Integration.sessions = {};
|
|
||||||
yield execCommand('addEditCitation', docID);
|
yield execCommand('addEditCitation', docID);
|
||||||
assert.isTrue(setDocumentDataSpy.calledOnce);
|
assert.isTrue(setDocumentDataSpy.calledOnce);
|
||||||
});
|
});
|
||||||
|
@ -390,8 +380,7 @@ describe("Zotero.Integration", function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when the style is not from a trusted source', function() {
|
describe('when the style is not from a trusted source', function() {
|
||||||
it('should download the style and not call doc.setDocumentData if user clicks YES', function* () {
|
it('should download the style and if user clicks YES', function* () {
|
||||||
setDocumentDataSpy.reset();
|
|
||||||
var styleInstallStub = sinon.stub(Zotero.Styles, "install").resolves();
|
var styleInstallStub = sinon.stub(Zotero.Styles, "install").resolves();
|
||||||
var style = Zotero.Styles.get(styleID);
|
var style = Zotero.Styles.get(styleID);
|
||||||
var styleGetCalledOnce = false;
|
var styleGetCalledOnce = false;
|
||||||
|
@ -407,7 +396,6 @@ describe("Zotero.Integration", function () {
|
||||||
assert.isTrue(displayAlertStub.calledOnce);
|
assert.isTrue(displayAlertStub.calledOnce);
|
||||||
assert.isFalse(displayDialogStub.calledWith(applications[docID].doc, 'chrome://zotero/content/integration/integrationDocPrefs.xul'));
|
assert.isFalse(displayDialogStub.calledWith(applications[docID].doc, 'chrome://zotero/content/integration/integrationDocPrefs.xul'));
|
||||||
assert.isTrue(styleInstallStub.calledOnce);
|
assert.isTrue(styleInstallStub.calledOnce);
|
||||||
assert.isFalse(setDocumentDataSpy.called);
|
|
||||||
assert.isOk(Zotero.Styles.get(style.styleID));
|
assert.isOk(Zotero.Styles.get(style.styleID));
|
||||||
styleInstallStub.restore();
|
styleInstallStub.restore();
|
||||||
styleGetStub.restore();
|
styleGetStub.restore();
|
||||||
|
@ -447,6 +435,194 @@ describe("Zotero.Integration", function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('#addEditCitation', function() {
|
||||||
|
var insertMultipleCitations = Zotero.Promise.coroutine(function *() {
|
||||||
|
var docID = this.test.fullTitle();
|
||||||
|
if (!(docID in applications)) initDoc(docID);
|
||||||
|
var doc = applications[docID].doc;
|
||||||
|
|
||||||
|
setAddEditItems(testItems[0]);
|
||||||
|
yield execCommand('addEditCitation', docID);
|
||||||
|
assert.equal(doc.fields.length, 1);
|
||||||
|
var citation = (new Zotero.Integration.CitationField(doc.fields[0])).unserialize();
|
||||||
|
assert.equal(citation.citationItems.length, 1);
|
||||||
|
assert.equal(citation.citationItems[0].id, testItems[0].id);
|
||||||
|
|
||||||
|
setAddEditItems(testItems.slice(1, 3));
|
||||||
|
yield execCommand('addEditCitation', docID);
|
||||||
|
assert.equal(doc.fields.length, 2);
|
||||||
|
citation = (new Zotero.Integration.CitationField(doc.fields[1])).unserialize();
|
||||||
|
assert.equal(citation.citationItems.length, 2);
|
||||||
|
for (let i = 1; i < 3; i++) {
|
||||||
|
assert.equal(citation.citationItems[i-1].id, testItems[i].id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
it('should insert citation if not in field', insertMultipleCitations);
|
||||||
|
|
||||||
|
it('should edit citation if in citation field', function* () {
|
||||||
|
yield insertMultipleCitations.call(this);
|
||||||
|
var docID = this.test.fullTitle();
|
||||||
|
var doc = applications[docID].doc;
|
||||||
|
|
||||||
|
sinon.stub(doc, 'cursorInField').returns(doc.fields[0]);
|
||||||
|
sinon.stub(doc, 'canInsertField').returns(false);
|
||||||
|
|
||||||
|
setAddEditItems(testItems.slice(3, 5));
|
||||||
|
yield execCommand('addEditCitation', docID);
|
||||||
|
assert.equal(doc.fields.length, 2);
|
||||||
|
var citation = (new Zotero.Integration.CitationField(doc.fields[0])).unserialize();
|
||||||
|
assert.equal(citation.citationItems.length, 2);
|
||||||
|
assert.equal(citation.citationItems[0].id, testItems[3].id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update bibliography if present', function* () {
|
||||||
|
yield insertMultipleCitations.call(this);
|
||||||
|
var docID = this.test.fullTitle();
|
||||||
|
var doc = applications[docID].doc;
|
||||||
|
|
||||||
|
let getCiteprocBibliographySpy =
|
||||||
|
sinon.spy(Zotero.Integration.Bibliography.prototype, 'getCiteprocBibliography');
|
||||||
|
|
||||||
|
yield execCommand('addEditBibliography', docID);
|
||||||
|
assert.isTrue(getCiteprocBibliographySpy.calledOnce);
|
||||||
|
|
||||||
|
assert.equal(getCiteprocBibliographySpy.lastCall.returnValue[0].entry_ids.length, 3);
|
||||||
|
getCiteprocBibliographySpy.reset();
|
||||||
|
|
||||||
|
setAddEditItems(testItems[3]);
|
||||||
|
yield execCommand('addEditCitation', docID);
|
||||||
|
assert.equal(getCiteprocBibliographySpy.lastCall.returnValue[0].entry_ids.length, 4);
|
||||||
|
|
||||||
|
getCiteprocBibliographySpy.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when original citation text has been modified', function() {
|
||||||
|
var displayAlertStub;
|
||||||
|
before(function* () {
|
||||||
|
displayAlertStub = sinon.stub(DocumentPluginDummy.Document.prototype, 'displayAlert').returns(0);
|
||||||
|
});
|
||||||
|
beforeEach(function() {
|
||||||
|
displayAlertStub.reset();
|
||||||
|
});
|
||||||
|
after(function() {
|
||||||
|
displayAlertStub.restore();
|
||||||
|
});
|
||||||
|
it('should keep modification if "Cancel" selected in editCitation triggered alert', async function () {
|
||||||
|
await insertMultipleCitations.call(this);
|
||||||
|
var docID = this.test.fullTitle();
|
||||||
|
var doc = applications[docID].doc;
|
||||||
|
|
||||||
|
doc.fields[0].text = "modified";
|
||||||
|
sinon.stub(doc, 'cursorInField').returns(doc.fields[0]);
|
||||||
|
sinon.stub(doc, 'canInsertField').returns(false);
|
||||||
|
|
||||||
|
await execCommand('addEditCitation', docID);
|
||||||
|
assert.equal(doc.fields.length, 2);
|
||||||
|
assert.equal(doc.fields[0].text, "modified");
|
||||||
|
});
|
||||||
|
it('should display citation dialog if "OK" selected in editCitation triggered alert', async function () {
|
||||||
|
await insertMultipleCitations.call(this);
|
||||||
|
var docID = this.test.fullTitle();
|
||||||
|
var doc = applications[docID].doc;
|
||||||
|
|
||||||
|
let origText = doc.fields[0].text;
|
||||||
|
doc.fields[0].text = "modified";
|
||||||
|
// Return OK
|
||||||
|
displayAlertStub.returns(1);
|
||||||
|
sinon.stub(doc, 'cursorInField').returns(doc.fields[0]);
|
||||||
|
sinon.stub(doc, 'canInsertField').returns(false);
|
||||||
|
setAddEditItems(testItems[0]);
|
||||||
|
|
||||||
|
await execCommand('addEditCitation', docID);
|
||||||
|
assert.isTrue(displayAlertStub.called);
|
||||||
|
assert.equal(doc.fields.length, 2);
|
||||||
|
assert.equal(doc.fields[0].text, origText);
|
||||||
|
});
|
||||||
|
it('should set dontUpdate: true if "yes" selected in refresh prompt', async function() {
|
||||||
|
await insertMultipleCitations.call(this);
|
||||||
|
var docID = this.test.fullTitle();
|
||||||
|
var doc = applications[docID].doc;
|
||||||
|
|
||||||
|
var citation = (new Zotero.Integration.CitationField(doc.fields[0])).unserialize();
|
||||||
|
assert.isNotOk(citation.properties.dontUpdate);
|
||||||
|
doc.fields[0].text = "modified";
|
||||||
|
// Return Yes
|
||||||
|
displayAlertStub.returns(1);
|
||||||
|
|
||||||
|
await execCommand('refresh', docID);
|
||||||
|
assert.isTrue(displayAlertStub.called);
|
||||||
|
assert.equal(doc.fields.length, 2);
|
||||||
|
assert.equal(doc.fields[0].text, "modified");
|
||||||
|
var citation = (new Zotero.Integration.CitationField(doc.fields[0])).unserialize();
|
||||||
|
assert.isOk(citation.properties.dontUpdate);
|
||||||
|
});
|
||||||
|
it('should reset citation text if "no" selected in refresh prompt', async function() {
|
||||||
|
await insertMultipleCitations.call(this);
|
||||||
|
var docID = this.test.fullTitle();
|
||||||
|
var doc = applications[docID].doc;
|
||||||
|
|
||||||
|
var citation = (new Zotero.Integration.CitationField(doc.fields[0])).unserialize();
|
||||||
|
assert.isNotOk(citation.properties.dontUpdate);
|
||||||
|
let origText = doc.fields[0].text;
|
||||||
|
doc.fields[0].text = "modified";
|
||||||
|
// Return No
|
||||||
|
displayAlertStub.returns(0);
|
||||||
|
|
||||||
|
await execCommand('refresh', docID);
|
||||||
|
assert.isTrue(displayAlertStub.called);
|
||||||
|
assert.equal(doc.fields.length, 2);
|
||||||
|
assert.equal(doc.fields[0].text, origText);
|
||||||
|
var citation = (new Zotero.Integration.CitationField(doc.fields[0])).unserialize();
|
||||||
|
assert.isNotOk(citation.properties.dontUpdate);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when delayCitationUpdates is set', function() {
|
||||||
|
it('should insert a citation with wave underlining', function* (){
|
||||||
|
yield insertMultipleCitations.call(this);
|
||||||
|
var docID = this.test.fullTitle();
|
||||||
|
var doc = applications[docID].doc;
|
||||||
|
var data = new Zotero.Integration.DocumentData(doc.data);
|
||||||
|
data.prefs.delayCitationUpdates = true;
|
||||||
|
doc.data = data.serialize();
|
||||||
|
|
||||||
|
var setTextSpy = sinon.spy(DocumentPluginDummy.Field.prototype, 'setText');
|
||||||
|
setAddEditItems(testItems[3]);
|
||||||
|
yield execCommand('addEditCitation', docID);
|
||||||
|
assert.isTrue(setTextSpy.lastCall.args[0].includes('\\uldash'));
|
||||||
|
|
||||||
|
setTextSpy.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not write to any other fields besides the one being updated', function* () {
|
||||||
|
yield insertMultipleCitations.call(this);
|
||||||
|
var docID = this.test.fullTitle();
|
||||||
|
var doc = applications[docID].doc;
|
||||||
|
var data = new Zotero.Integration.DocumentData(doc.data);
|
||||||
|
data.prefs.delayCitationUpdates = true;
|
||||||
|
doc.data = data.serialize();
|
||||||
|
|
||||||
|
var setTextSpy = sinon.spy(DocumentPluginDummy.Field.prototype, 'setText');
|
||||||
|
var setCodeSpy = sinon.spy(DocumentPluginDummy.Field.prototype, 'setCode');
|
||||||
|
|
||||||
|
setAddEditItems(testItems[3]);
|
||||||
|
yield execCommand('addEditCitation', docID);
|
||||||
|
var field = setTextSpy.firstCall.thisValue;
|
||||||
|
|
||||||
|
for (let i = 0; i < setTextSpy.callCount; i++) {
|
||||||
|
assert.isTrue(field.equals(setTextSpy.getCall(i).thisValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < setCodeSpy.callCount; i++) {
|
||||||
|
assert.isTrue(field.equals(setCodeSpy.getCall(i).thisValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
setTextSpy.restore();
|
||||||
|
setCodeSpy.restore();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('#addEditBibliography', function() {
|
describe('#addEditBibliography', function() {
|
||||||
var docID = this.fullTitle();
|
var docID = this.fullTitle();
|
||||||
beforeEach(function* () {
|
beforeEach(function* () {
|
||||||
|
@ -455,12 +631,13 @@ describe("Zotero.Integration", function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should insert bibliography if no bibliography field present', function* () {
|
it('should insert bibliography if no bibliography field present', function* () {
|
||||||
|
displayDialogStub.reset();
|
||||||
yield execCommand('addEditBibliography', docID);
|
yield execCommand('addEditBibliography', docID);
|
||||||
|
assert.isFalse(displayDialogStub.called);
|
||||||
var biblPresent = false;
|
var biblPresent = false;
|
||||||
for (let i = applications[docID].doc.fields.length-1; i >= 0; i--) {
|
for (let i = applications[docID].doc.fields.length-1; i >= 0; i--) {
|
||||||
let field = applications[docID].doc.fields[i];
|
let field = Zotero.Integration.Field.loadExisting(applications[docID].doc.fields[i]);
|
||||||
Zotero.debug(field.getCode(), 1);
|
if (field.type == INTEGRATION_TYPE_BIBLIOGRAPHY) {
|
||||||
if (field.getCode().includes("CSL_BIBLIOGRAPHY")) {
|
|
||||||
biblPresent = true;
|
biblPresent = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -473,7 +650,7 @@ describe("Zotero.Integration", function () {
|
||||||
displayDialogStub.reset();
|
displayDialogStub.reset();
|
||||||
yield execCommand('addEditBibliography', docID);
|
yield execCommand('addEditBibliography', docID);
|
||||||
assert.isTrue(displayDialogStub.calledOnce);
|
assert.isTrue(displayDialogStub.calledOnce);
|
||||||
assert.isTrue(displayDialogStub.lastCall.args[1].includes('editBibliographyDialog'));
|
assert.isTrue(displayDialogStub.lastCall.args[0].includes('editBibliographyDialog'));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue
Block a user