fx-compat: Restore word processor integration (#2841)

- Word for Windows not tested since there's no build yet
- Word for Mac currently causes a sigsev, and likely we'll see this on
windows too. This is happening on an API call where we pass a callback,
so likely an issue in ctypes that we'll have to work around.
- All integration UIs restored.
- Added a component for richlistitems with a checkbox with corresponding
interactions (spacebar/double-click to toggle).
This commit is contained in:
Adomas Ven 2022-10-06 07:17:28 +03:00 committed by GitHub
parent 03de28a7b7
commit aa1aac6adb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 1279 additions and 390 deletions

View file

@ -78,3 +78,8 @@ contract @mozilla.org/network/protocol;1?name=zotero {9BC3D762-9038-486A-9D70-C
content scaffold chrome/content/scaffold/
locale scaffold en-US chrome/locale/en-US/scaffold/
skin scaffold default chrome/skin/default/scaffold/
# Word Plugins
manifest integration/libreoffice/chrome.manifest
manifest integration/word-for-windows/chrome.manifest
manifest integration/word-for-mac/chrome.manifest

View file

@ -51,6 +51,7 @@ var Zotero_File_Interface_Bibliography = new function() {
*/
this.init = Zotero.Promise.coroutine(function* (args = {}) {
window.addEventListener('dialogaccept', () => this.acceptSelection());
window.addEventListener('dialoghelp', () => this.openHelpLink());
// Set font size from pref
// Affects bibliography.xhtml and integrationDocPrefs.xul
@ -267,7 +268,7 @@ var Zotero_File_Interface_Bibliography = new function() {
this.exportDocument = function () {
if (Zotero.Integration.confirmExportDocument()) {
_io.exportDocument = true;
document.documentElement.acceptDialog();
document.querySelector('dialog').acceptDialog();
}
}
@ -322,7 +323,7 @@ var Zotero_File_Interface_Bibliography = new function() {
this.manageStyles = function () {
document.querySelector('dialog').getButton('cancel').click();
document.querySelector('dialog').cancelDialog();
var win = Zotero.Utilities.Internal.openPreferences('zotero-prefpane-cite', { tab: 'styles-tab' });
if (isDocPrefs) {
Zotero.Utilities.Internal.activate(win);

View file

@ -1593,15 +1593,16 @@ var Columns = class {
};
function renderCell(index, data, column) {
column = column || { columnName: "" }
let span = document.createElement('span');
span.className = `cell ${column.className}`;
span.innerText = data;
return span;
}
function renderCheckboxCell(index, data, column) {
function renderCheckboxCell(index, data, columnName) {
let span = document.createElement('span');
span.className = `cell checkbox ${column.className}`;
span.className = `cell checkbox ${columnName}`;
span.setAttribute('role', 'checkbox');
span.setAttribute('aria-checked', data);
if (data) {
@ -1626,16 +1627,21 @@ function makeRowRenderer(getRowData) {
div.classList.toggle('focused', selection.focused == index);
const rowData = getRowData(index);
for (let column of columns) {
if (column.hidden) continue;
if (columns.length) {
for (let column of columns) {
if (column.hidden) continue;
if (column.type === 'checkbox') {
div.appendChild(renderCheckboxCell(index, rowData[column.dataKey], column));
}
else {
div.appendChild(renderCell(index, rowData[column.dataKey], column));
if (column.type === 'checkbox') {
div.appendChild(renderCheckboxCell(index, rowData[column.dataKey], column));
}
else {
div.appendChild(renderCell(index, rowData[column.dataKey], column));
}
}
}
else {
div.appendChild(renderCell(index, rowData));
}
return div;
};

View file

@ -0,0 +1,85 @@
/*
***** BEGIN LICENSE BLOCK *****
Copyright © 2022 Corporation for Digital Scholarship
Vienna, Virginia, USA
http://zotero.org
This file is part of Zotero.
Zotero is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Zotero is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
***** END LICENSE BLOCK *****
*/
"use strict";
{
if (!customElements.get("richlistitem")) {
delete document.createXULElement("richlistitem");
}
/**
* Extend richlistbox for checkbox inputs since we use them in multiple places
*/
class RichListCheckbox extends customElements.get('richlistitem') {
connectedCallback() {
this._checkbox = document.createXULElement('checkbox');
this._checkbox.setAttribute('native', 'true');
this._checkbox.setAttribute('checked', this.checked);
this._checkbox.addEventListener('focus', () => this.control.focus())
this._label = document.createElement('label');
this._label.textContent = this.label;
this.append(this._checkbox);
this.append(this._label);
// this.control (parent richlistbox) only available after connecting
this.control.addEventListener('keypress', (event) => {
if (
event.key == " " &&
!event.ctrlKey &&
!event.shiftKey &&
!event.altKey &&
!event.metaKey
) {
if (!this.selected) return;
this.checked = !this.checked;
event.stopPropagation();
}
});
this.addEventListener('dblclick', (event) => {
this.checked = !this.checked;
event.stopPropagation();
});
}
get label() {
return this.getAttribute('label');
}
set label(val) {
this._label.innerText = val;
return this.setAttribute('label', 'val');
}
get checked() {
return JSON.parse(this.getAttribute('checked'));
}
set checked(val) {
this._checkbox.setAttribute('checked', !!val);
return this.setAttribute('checked', !!val);
}
}
customElements.define("richlistcheckbox", RichListCheckbox);
}

View file

@ -52,6 +52,7 @@ var Zotero_Citation_Dialog = new function () {
var _sortCheckbox;
var _citationList;
var _originalHTML;
var _editor;
var serial_number;
var io;
@ -85,16 +86,21 @@ var Zotero_Citation_Dialog = new function () {
}
}, 0);
document.documentElement.getButton("extra1").label = Zotero.getString("citation.multipleSources");
document.documentElement.getButton("extra2").label = Zotero.getString("citation.showEditor");
io = window.arguments[0].wrappedJSObject;
// find accept button
_acceptButton = document.getElementById("zotero-add-citation-dialog").getButton("accept");
_multipleSourceButton = document.documentElement.getButton("extra1");
_acceptButton = document.querySelector('dialog').getButton("accept");
_multipleSourceButton = document.querySelector('dialog').getButton("extra1");
_multipleSourceButton.label = Zotero.getString("citation.multipleSources")
document.querySelector('dialog').getButton("extra2").label = Zotero.getString("citation.showEditor");
_autoRegeneratePref = Zotero.Prefs.get("integration.autoRegenerate");
_citationList = document.getElementById("citation-list");
_citationList = document.getElementById("item-list");
window.addEventListener('dialogaccept', () => Zotero_Citation_Dialog.accept());
window.addEventListener('dialogcancel', () => Zotero_Citation_Dialog.cancel());
window.addEventListener('dialogextra1', () => Zotero_Citation_Dialog.toggleMultipleSources());
window.addEventListener('dialogextra2', () => Zotero_Citation_Dialog.toggleEditor());
// Manipulated by _addItem(). Discriminates between cite instances
// based on the same item in the same citation. Internal throwaway variable,
@ -137,7 +143,7 @@ var Zotero_Citation_Dialog = new function () {
yield doLoad();
// if we already have a citation, load data from it
document.getElementById('editor').format = "RTF";
_editor = document.querySelector('#editor').contentWindow.editor;
if(io.citation.citationItems.length) {
if(io.citation.citationItems.length === 1) {
// single citation
@ -217,7 +223,7 @@ var Zotero_Citation_Dialog = new function () {
}
_multipleSourcesOn = !_multipleSourcesOn;
var popup = document.defaultView;
var dialog = document.getElementById("zotero-add-citation-dialog");
var dialog = document.documentElement;
if (dialog.getAttribute("height") == 1) {
popup.sizeToContent();
}
@ -287,7 +293,7 @@ var Zotero_Citation_Dialog = new function () {
// turn off highlight in selected item list
_suppressNextListSelect = true;
document.getElementById("citation-list").selectedIndex = -1;
document.getElementById("item-list").selectedIndex = -1;
// disable all fields
@ -515,7 +521,7 @@ var Zotero_Citation_Dialog = new function () {
* Ask whether to modify the preview
*/
function confirmRegenerate(focusShifted) {
if(document.getElementById('editor').value == _originalHTML || _originalHTML === undefined) {
if(_editor.getContent() == _originalHTML || _originalHTML === undefined) {
// no changes; just update without asking
_updatePreview();
return;
@ -563,26 +569,24 @@ var Zotero_Citation_Dialog = new function () {
_previewShown = !_previewShown;
if(_previewShown) {
document.documentElement.getButton("extra2").label = Zotero.getString("citation.hideEditor");
document.querySelector('dialog').getButton("extra2").label = Zotero.getString("citation.hideEditor");
if (!text && _customHTML) {
text = _customHTML;
}
if(text) {
io.preview().then(function(preview) {
_originalHTML = preview;
editor.value = text;
_editor.setContent(text, true);
}).done();
} else {
_updatePreview();
}
} else {
if (editor.initialized) {
if (editor.value) {
_customHTML = editor.value;
}
}
document.documentElement.getButton("extra2").label = Zotero.getString("citation.showEditor");
_customHTML = _editor.getContent(true);
document.querySelector('dialog').getButton("extra2").label = Zotero.getString("citation.showEditor");
}
// To resize virtualized-tables
window.dispatchEvent(new Event('resize'));
}
/*
@ -594,10 +598,10 @@ var Zotero_Citation_Dialog = new function () {
_getCitation();
var isCustom = _previewShown && io.citation.citationItems.length // if a citation is selected
&& _originalHTML
&& document.getElementById('editor').value != _originalHTML // and citation has been edited
&& _editor.getContent(true) != _originalHTML // and citation has been edited
if(isCustom) {
var citation = document.getElementById('editor').value;
var citation = _editor.getContent(true);
if(Zotero.Utilities.trim(citation) == "") {
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
@ -664,23 +668,17 @@ var Zotero_Citation_Dialog = new function () {
*/
function _updatePreview() {
if(_previewShown) {
var editor = document.getElementById('editor');
_getCitation();
editor.readonly = !io.citation.citationItems.length;
if(io.citation.citationItems.length) {
io.preview().then(function(preview) {
editor.value = preview;
if (editor.initialized) {
_originalHTML = editor.value;
}
else {
editor.onInit(() => _originalHTML = editor.value);
}
_editor.setEnabled(io.citation.citationItems.length);
if (io.citation.citationItems.length) {
io.preview().then((preview) => {
_editor.setContent(preview, true);
_originalHTML = _editor.getContent(true);
});
} else {
editor.value = "";
_editor.setContent("");
_originalHTML = "";
}
}
@ -818,7 +816,7 @@ var Zotero_Citation_Dialog = new function () {
* Add an item to the item list (multiple sources only)
*/
function _addItem(item, forceID) {
var itemNode = document.createElement("listitem");
var itemNode = document.createXULElement("richlistitem");
var itemDataID;
if (!forceID) {
@ -829,9 +827,11 @@ var Zotero_Citation_Dialog = new function () {
}
itemNode.setAttribute("value", itemDataID);
itemNode.setAttribute("label", item.getDisplayTitle());
let image = document.createXULElement('image');
image.src = item.getImageSrc();
itemNode.append(image);
itemNode.setAttribute("class", "listitem-iconic");
itemNode.setAttribute("image", item.getImageSrc());
itemNode.append(item.getDisplayTitle());
_citationList.appendChild(itemNode);
return itemNode;
}

View file

@ -32,36 +32,42 @@
<?xml-stylesheet href="chrome://zotero/skin/integration.css" type="text/css"?>
<!DOCTYPE window SYSTEM "chrome://zotero/locale/zotero.dtd">
<dialog
id="zotero-add-citation-dialog"
<window
windowtype="zotero:item-selector"
orient="vertical"
title="&zotero.integration.addEditCitation.title;"
width="600" height="450"
onload="Zotero_Citation_Dialog.load();"
onunload="doUnload();"
ondialogaccept="return Zotero_Citation_Dialog.accept();"
ondialogcancel="Zotero_Citation_Dialog.cancel();"
onclose="Zotero_Citation_Dialog.cancel();"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
persist="screenX screenY width height"
resizable="true"
buttons="extra1,extra2,accept,cancel"
ondialogextra2="Zotero_Citation_Dialog.toggleEditor()"
ondialogextra1="Zotero_Citation_Dialog.toggleMultipleSources()">
<script src="../include.js"/>
<script src="../selectItemsDialog.js"/>
<script src="addCitationDialog.js"/>
resizable="true">
<dialog
id="zotero-add-citation-dialog"
buttons="extra1,extra2,accept,cancel">
<script>
var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
Services.scriptloader.loadSubScript("chrome://zotero/content/include.js", this);
Services.scriptloader.loadSubScript("chrome://zotero/content/selectItemsDialog.js", this);
Services.scriptloader.loadSubScript("chrome://zotero/content/integration/addCitationDialog.js", this);
// Custom elements
Services.scriptloader.loadSubScript("chrome://global/content/customElements.js", this);
Services.scriptloader.loadSubScript("chrome://zotero/content/elements/quickSearchTextbox.js", this);
</script>
<vbox id="zotero-select-items-container" flex="1">
<vbox flex="1">
<hbox flex="1">
<vbox align="stretch" flex="1">
<vbox align="stretch" flex="1" style="min-width: 500px">
<hbox align="center" pack="end">
<textbox id="zotero-tb-search" type="search" timeout="250" oncommand="onSearch()" tabindex="1"
onkeypress="if(event.keyCode == event.DOM_VK_ESCAPE) { if (this.value == '') { cancelDialog(); return false; } this.value = ''; onSearch(); return false; } return true;"/>
<quick-search-textbox id="zotero-tb-search" timeout="250" oncommand="onSearch()" dir="reverse"/>
</hbox>
<hbox flex="1" style="margin-top: 5px">
<vbox id="zotero-collections-tree-container" class="virtualized-table-container" style="min-width: 200px">
@ -82,8 +88,8 @@
<toolbarbutton id="down" oncommand="Zotero_Citation_Dialog.down()" disabled="true"/>
</vbox>
<vbox align="left">
<checkbox id="keepSorted" hidden="true" checked="false" oncommand="Zotero_Citation_Dialog.citationSortUnsort()" label="&zotero.citation.keepSorted.label;"/>
<listbox id="citation-list" flex="1" align="stretch" seltype="single"
<checkbox id="keepSorted" hidden="true" checked="false" oncommand="Zotero_Citation_Dialog.citationSortUnsort()" label="&zotero.citation.keepSorted.label;" native="true"/>
<richlistbox id="item-list" flex="1" align="stretch" seltype="single" style="width: 250px;"
onselect="Zotero_Citation_Dialog.listItemSelected();"/>
</vbox>
</hbox>
@ -93,29 +99,34 @@
<vbox flex="1">
<hbox align="center">
<label value="&zotero.citation.prefix.label;"/>
<textbox oninput="Zotero_Citation_Dialog.confirmRegenerate(false)" onchange="Zotero_Citation_Dialog.confirmRegenerate(true)" class="fix" id="prefix" align="stretch" flex="1" tabindex="3"/>
<html:input type="text" class="fix" id="prefix" tabindex="3"
oninput="Zotero_Citation_Dialog.confirmRegenerate(false)"
onchange="Zotero_Citation_Dialog.confirmRegenerate(true)"/>
</hbox>
<hbox align="center">
<label value="&zotero.citation.suffix.label;"/>
<textbox oninput="Zotero_Citation_Dialog.confirmRegenerate(false)" onchange="Zotero_Citation_Dialog.confirmRegenerate(true)" class="fix" id="suffix" align="stretch" flex="1" tabindex="4"/>
<html:input type="text" class="fix" id="suffix" tabindex="4"
oninput="Zotero_Citation_Dialog.confirmRegenerate(false)"
onchange="Zotero_Citation_Dialog.confirmRegenerate(true)"/>
</hbox>
<spacer flex="1"/>
</vbox>
<separator flex="4"/>
<vbox flex="1">
<hbox align="stretch">
<menulist onchange="Zotero_Citation_Dialog.confirmRegenerate(true)" id="label" tabindex="5">
<menulist onchange="Zotero_Citation_Dialog.confirmRegenerate(true)" id="label" tabindex="5" native="true">
<menupopup id="locator-type-popup"/>
</menulist>
<textbox oninput="Zotero_Citation_Dialog.confirmRegenerate(false)" onchange="Zotero_Citation_Dialog.confirmRegenerate(true)" id="locator" tabindex="2" flex="1"/>
</hbox>
<separator style="height: 2px" flex="1"/>
<checkbox oncommand="Zotero_Citation_Dialog.confirmRegenerate(true)" id="suppress-author" label="&zotero.citation.suppressAuthor.label;" tabindex="6"/>
<checkbox oncommand="Zotero_Citation_Dialog.confirmRegenerate(true)" id="suppress-author" label="&zotero.citation.suppressAuthor.label;" tabindex="6" native="true"/>
</vbox>
</hbox>
</vbox>
<textbox id="editor" type="styled" mode="integration" hidden="true" flex="1"/>
<iframe id="editor" src="simpleEditor.html" hidden="true" flex="1" type="content" remote="false" maychangeremoteness="false"/>
<description id="zotero-editor-warning" style="margin: 9px 1px 0" hidden="true">&zotero.citation.editorWarning.label;</description>
</vbox>
</dialog>
</window>

View file

@ -0,0 +1,32 @@
<!DOCTYPE html>
<!--
***** BEGIN LICENSE BLOCK *****
Copyright © 2022 Center for History and New Media
George Mason University, Fairfax, Virginia, USA
http://zotero.org
This file is part of Zotero.
Zotero is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Zotero is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
***** END LICENSE BLOCK *****
-->
<html xmlns="http://www.w3.org/1999/xhtml" style="height: 100%">
<head>
<link rel="stylesheet" type="text/css" href="chrome://zotero/skin/integration.css"/>
<link rel="stylesheet" type="text/css" href="chrome://zotero-platform/content/integration.css"/>
</head>
<body contenteditable="true" spellcheck="false" class="citation-dialog editor"></body>
</html>

View file

@ -31,6 +31,7 @@ var Zotero_Bibliography_Dialog = new function () {
var _accepted = false;
var _revertButton, _revertAllButton, _addButton, _removeButton;
var _itemList;
var _editor;
var _suppressAllSelectEvents = false;
/**
@ -39,18 +40,23 @@ var Zotero_Bibliography_Dialog = new function () {
this.load = async function() {
bibEditInterface = window.arguments[0].wrappedJSObject;
_revertAllButton = document.documentElement.getButton("extra2");
_revertButton = document.documentElement.getButton("extra1");
_revertAllButton = document.querySelector('dialog').getButton("extra2");
_revertButton = document.querySelector('dialog').getButton("extra1");
_addButton = document.getElementById("add");
_removeButton = document.getElementById("remove");
_itemList = document.getElementById("item-list");
_revertAllButton.label = Zotero.getString("integration.revertAll.button");
_revertAllButton.disabled = bibEditInterface.isAnyEdited();
_revertAllButton.addEventListener('command', () => Zotero_Bibliography_Dialog.revertAll());
_revertButton.label = Zotero.getString("integration.revert.button");
_revertButton.disabled = true;
_revertButton.addEventListener('command', () => Zotero_Bibliography_Dialog.revert());
document.getElementById('editor').format = "RTF";
window.addEventListener('dialogaccept', () => Zotero_Bibliography_Dialog.accept());
window.addEventListener('dialogcancel', () => Zotero_Bibliography_Dialog.close());
_editor = document.querySelector('#editor').contentWindow.editor;
// load (from selectItemsDialog.js)
await doLoad();
@ -274,25 +280,24 @@ var Zotero_Bibliography_Dialog = new function () {
* Updates the contents of the preview pane
*/
function _updatePreview(ignoreSelection) {
var index = !ignoreSelection && _itemList.selectedItems.length == 1 ? _itemList.selectedIndex : undefined;
var editor = document.getElementById('editor');
var index = !ignoreSelection && _itemList.selectedCount == 1 && _itemList.selectedIndex != -1 ? _itemList.selectedIndex : undefined;
if(_lastSelectedItemID) {
var newValue = editor.value;
var newValue = _editor.getContent(true);
if(_lastSelectedValue != newValue) {
bibEditInterface.setCustomText(_lastSelectedItemID, newValue);
}
}
editor.readonly = index === undefined;
_editor.setEnabled(index !== undefined);
if(index !== undefined) {
var itemID = bibEditInterface.bib[0].entry_ids[index];
editor.value = bibEditInterface.bib[1][index];
_editor.setContent(bibEditInterface.bib[1][index], true);
_lastSelectedIndex = index;
_lastSelectedItemID = itemID;
_lastSelectedValue = editor.value;
_lastSelectedValue = _editor.getContent(true);
} else {
editor.value = "";
_editor.setContent("");
_lastSelectedIndex = _lastSelectedItemID = _lastSelectedValue = false;
}
@ -314,11 +319,13 @@ var Zotero_Bibliography_Dialog = new function () {
// add new items
for(var i=0; i<items.length; i++) {
var itemNode = document.createElement("listitem");
var itemNode = document.createXULElement("richlistitem");
itemNode.setAttribute("value", i);
itemNode.setAttribute("label", items[i].getDisplayTitle());
let image = document.createXULElement('image');
image.src = items[i].getImageSrc();
itemNode.append(image);
itemNode.append(items[i].getDisplayTitle());
itemNode.setAttribute("class", "listitem-iconic");
itemNode.setAttribute("image", items[i].getImageSrc());
itemList.appendChild(itemNode);
}

View file

@ -31,34 +31,40 @@
<?xml-stylesheet href="chrome://zotero/skin/integration.css" type="text/css"?>
<!DOCTYPE window SYSTEM "chrome://zotero/locale/zotero.dtd">
<dialog
id="zotero-edit-bibliography-dialog"
<window
orient="vertical"
title="&zotero.integration.editBibliography.title;"
width="750" height="450"
onload="Zotero_Bibliography_Dialog.load();"
ondialogaccept="Zotero_Bibliography_Dialog.accept();"
ondialogcancel="Zotero_Bibliography_Dialog.close();"
onclose="Zotero_Bibliography_Dialog.close();"
onunload="doUnload();"
buttons="extra1,extra2,accept,cancel" buttonpack="end"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
persist="screenX screenY width height"
resizable="true"
ondialogextra1="Zotero_Bibliography_Dialog.revert()"
ondialogextra2="Zotero_Bibliography_Dialog.revertAll()">
resizable="true">
<dialog
id="zotero-edit-bibliography-dialog"
buttons="extra1,extra2,accept,cancel" buttonpack="end">
<script src="../include.js"/>
<script src="../selectItemsDialog.js"/>
<script src="editBibliographyDialog.js"/>
<script>
var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
Services.scriptloader.loadSubScript("chrome://zotero/content/include.js", this);
Services.scriptloader.loadSubScript("chrome://zotero/content/selectItemsDialog.js", this);
Services.scriptloader.loadSubScript("chrome://zotero/content/integration/editBibliographyDialog.js", this);
// Custom elements
Services.scriptloader.loadSubScript("chrome://global/content/customElements.js", this);
Services.scriptloader.loadSubScript("chrome://zotero/content/elements/quickSearchTextbox.js", this);
</script>
<vbox id="zotero-select-items-container" flex="1">
<vbox flex="1">
<hbox flex="1">
<vbox align="stretch" flex="1">
<hbox align="center" pack="end">
<textbox id="zotero-tb-search" type="search" timeout="250" oncommand="onSearch()" dir="reverse" onkeypress="if(event.keyCode == event.DOM_VK_ESCAPE) { this.value = ''; this.doCommand('cmd_zotero_search'); return false; } return true;"/>
<quick-search-textbox id="zotero-tb-search" timeout="250" oncommand="onSearch()" dir="reverse"/>
</hbox>
<hbox flex="1" style="margin-top: 5px">
<vbox id="zotero-collections-tree-container" class="virtualized-table-container" style="min-width: 150px">
@ -78,7 +84,7 @@
</vbox>
<vbox>
<label value="&zotero.integration.references.label;"/>
<listbox id="item-list" flex="1" align="stretch" seltype="multiple"
<richlistbox id="item-list" flex="1" align="stretch" seltype="multiple"
style="width: 250px;" onselect="Zotero_Bibliography_Dialog.listItemSelected();"
onchanged="Zotero_Bibliography_Dialog.textChanged()"/>
</vbox>
@ -86,7 +92,8 @@
</hbox>
</vbox>
<textbox id="editor" type="styled" mode="integration" flex="1"/>
<iframe id="editor" src="simpleEditor.html" flex="1" type="content" remote="false" maychangeremoteness="false"/>
<description id="zotero-editor-warning" style="margin: 9px 1px 0">&zotero.citation.editorWarning.label;</description>
</vbox>
</dialog>
</window>

View file

@ -28,6 +28,7 @@
<?xml-stylesheet href="chrome://zotero/skin/zotero.css" type="text/css"?>
<?xml-stylesheet href="chrome://zotero/skin/integration.css" type="text/css"?>
<?xml-stylesheet href="chrome://zotero-platform/content/integration.css" type="text/css"?>
<?xml-stylesheet href="chrome://zotero-platform-version/content/style.css" type="text/css"?>
<!DOCTYPE window SYSTEM "chrome://zotero/locale/zotero.dtd">
<window
@ -50,14 +51,21 @@
<deck class="citation-dialog deck" selectedIndex="0" flex="1">
<hbox class="citation-dialog search" flex="1" align="start">
<hbox flex="1">
<iframe class="citation-dialog 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%20spellcheck=%22false%22%20class=%22citation-dialog%20editor%22/%3E%3C/html%3E"
tabindex="1" flex="1"/>
<iframe
class="citation-dialog iframe"
ondragstart="event.stopPropagation()"
src="citationDialogIframe.html"
tabindex="1"
flex="1"
type="content"
remote="false"
maychangeremoteness="false"/>
<vbox class="citation-dialog spinner" style="visibility: hidden">
<image class="zotero-spinner-16"/>
</vbox>
</hbox>
</hbox>
<progressmeter class="citation-dialog progress-meter" mode="undetermined" value="0" flex="1"/>
<html:progress class="citation-dialog progress-meter" max="100"/>
</deck>
</box>
<panel class="citation-dialog reference-panel" noautofocus="true" norestorefocus="true"

View file

@ -0,0 +1,104 @@
<?xml version="1.0"?>
<!--
***** BEGIN LICENSE BLOCK *****
Copyright © 2009 Center for History and New Media
George Mason University, Fairfax, Virginia, USA
http://zotero.org
This file is part of Zotero.
Zotero is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Zotero is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
***** END LICENSE BLOCK *****
-->
<?xml-stylesheet href="chrome://global/skin/"?>
<?xml-stylesheet href="chrome://zotero/skin/zotero.css"?>
<?xml-stylesheet href="chrome://zotero/skin/bibliography.css"?>
<!DOCTYPE window SYSTEM "chrome://zotero/locale/zotero.dtd">
<window
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
title="&zotero.integration.docPrefs.title;"
onload="Zotero_File_Interface_Bibliography.init();"
>
<dialog
id="zotero-doc-prefs-dialog"
orient="vertical"
buttons="accept,cancel,help"
persist="screenX screenY"
ondialogaccept="Zotero_File_Interface_Bibliography.acceptSelection();"
ondialoghelp="Zotero_File_Interface_Bibliography.openHelpLink();"
onclose="document.documentElement.cancelDialog(); event.preventDefault(); event.stopPropagation();"
style="width: 600px">
<script src="../include.js"/>
<script src="../bibliography.js"/>
<vbox id="zotero-bibliography-container">
<groupbox>
<label><html:h2>&zotero.bibliography.style.label;</html:h2></label>
<richlistbox id="style-listbox" onselect="Zotero_File_Interface_Bibliography.styleChanged()" flex="1"/>
<hbox align="right">
<label id="manage-styles" class="text-link"
onclick="Zotero_File_Interface_Bibliography.manageStyles()">&zotero.bibliography.manageStyles;</label>
</hbox>
</groupbox>
<groupbox id="locale-box">
<hbox align="center">
<label><html:h2>&zotero.bibliography.locale.label;</html:h2></label>
<menulist id="locale-menu" oncommand="Zotero_File_Interface_Bibliography.localeChanged(this.selectedItem.value)" native="true"/>
</hbox>
</groupbox>
<groupbox id="displayAs-groupbox">
<label><html:h2>&zotero.integration.prefs.displayAs.label;</html:h2></label>
<radiogroup id="displayAs" orient="horizontal">
<radio id="footnotes" label="&zotero.integration.prefs.footnotes.label;" selected="true"/>
<radio id="endnotes" label="&zotero.integration.prefs.endnotes.label;"/>
</radiogroup>
</groupbox>
<groupbox id="formatUsing-groupbox">
<label><html:h2>&zotero.integration.prefs.formatUsing.label;</html:h2></label>
<radiogroup id="formatUsing" orient="vertical">
<radio id="fields" selected="true"/>
<label class="radioDescription" id="fields-caption"/>
<label class="radioDescription" id="fields-file-format-notice"/>
<radio id="bookmarks" label="&zotero.integration.prefs.bookmarks.label;"/>
<description class="radioDescription" id="bookmarks-caption">&zotero.integration.prefs.bookmarks.caption;</description>
<description class="radioDescription" id="bookmarks-file-format-notice"/>
</radiogroup>
</groupbox>
<vbox class="pref-vbox" id="automaticJournalAbbreviations-vbox">
<checkbox id="automaticJournalAbbreviations-checkbox" label="&zotero.integration.prefs.automaticJournalAbbeviations.label;" native="true"/>
<description class="radioDescription">&zotero.integration.prefs.automaticJournalAbbeviations.caption;</description>
</vbox>
<vbox id="advanced-settings" hidden="false">
<vbox id="automaticCitationUpdates-vbox">
<checkbox id="automaticCitationUpdates-checkbox" label="&zotero.integration.prefs.automaticCitationUpdates.label;" tooltiptext="&zotero.integration.prefs.automaticCitationUpdates.tooltip;" native="true"/>
<description class="radioDescription">&zotero.integration.prefs.automaticCitationUpdates.description;</description>
</vbox>
<hbox id="exportImport" hidden="true">
<button label="&zotero.integration.prefs.exportDocument;" oncommand="Zotero_File_Interface_Bibliography.exportDocument()"/>
</hbox>
</vbox>
</vbox>
</dialog>
</window>

View file

@ -1,100 +0,0 @@
<?xml version="1.0"?>
<!--
***** BEGIN LICENSE BLOCK *****
Copyright © 2009 Center for History and New Media
George Mason University, Fairfax, Virginia, USA
http://zotero.org
This file is part of Zotero.
Zotero is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Zotero is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
***** END LICENSE BLOCK *****
-->
<?xml-stylesheet href="chrome://global/skin/global.css"?>
<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css"?>
<?xml-stylesheet href="chrome://zotero/skin/bibliography.css"?>
<!DOCTYPE window SYSTEM "chrome://zotero/locale/zotero.dtd">
<dialog
id="zotero-doc-prefs-dialog"
orient="vertical"
buttons="accept,cancel,help"
title="&zotero.integration.docPrefs.title;"
onload="Zotero_File_Interface_Bibliography.init();"
ondialogaccept="Zotero_File_Interface_Bibliography.acceptSelection();"
ondialoghelp="Zotero_File_Interface_Bibliography.openHelpLink();"
onclose="document.documentElement.cancelDialog(); event.preventDefault(); event.stopPropagation();"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
persist="screenX screenY"
style="width: 600px">
<script src="../include.js"/>
<script src="../bibliography.js"/>
<vbox id="zotero-bibliography-container">
<groupbox>
<caption label="&zotero.bibliography.style.label;"/>
<listbox id="style-listbox" onselect="Zotero_File_Interface_Bibliography.styleChanged()"/>
<hbox align="right">
<label id="manage-styles" class="text-link"
onclick="Zotero_File_Interface_Bibliography.manageStyles()">&zotero.bibliography.manageStyles;</label>
</hbox>
</groupbox>
<groupbox id="locale-box">
<hbox align="center">
<caption label="&zotero.bibliography.locale.label;"/>
<menulist id="locale-menu" oncommand="Zotero_File_Interface_Bibliography.localeChanged(this.selectedItem.value)"/>
</hbox>
</groupbox>
<groupbox id="displayAs-groupbox">
<caption label="&zotero.integration.prefs.displayAs.label;"/>
<radiogroup id="displayAs" orient="horizontal">
<radio id="footnotes" label="&zotero.integration.prefs.footnotes.label;" selected="true"/>
<radio id="endnotes" label="&zotero.integration.prefs.endnotes.label;"/>
</radiogroup>
</groupbox>
<groupbox id="formatUsing-groupbox">
<caption label="&zotero.integration.prefs.formatUsing.label;"/>
<radiogroup id="formatUsing" orient="vertical">
<radio id="fields" selected="true"/>
<label class="radioDescription" id="fields-caption"/>
<label class="radioDescription" id="fields-file-format-notice"/>
<radio id="bookmarks" label="&zotero.integration.prefs.bookmarks.label;"/>
<description class="radioDescription" id="bookmarks-caption">&zotero.integration.prefs.bookmarks.caption;</description>
<description class="radioDescription" id="bookmarks-file-format-notice"/>
</radiogroup>
</groupbox>
<vbox class="pref-vbox" id="automaticJournalAbbreviations-vbox">
<checkbox id="automaticJournalAbbreviations-checkbox" label="&zotero.integration.prefs.automaticJournalAbbeviations.label;"/>
<description class="radioDescription">&zotero.integration.prefs.automaticJournalAbbeviations.caption;</description>
</vbox>
<vbox id="advanced-settings" hidden="false">
<vbox id="automaticCitationUpdates-vbox">
<checkbox id="automaticCitationUpdates-checkbox" label="&zotero.integration.prefs.automaticCitationUpdates.label;" tooltiptext="&zotero.integration.prefs.automaticCitationUpdates.tooltip;"/>
<description class="radioDescription">&zotero.integration.prefs.automaticCitationUpdates.description;</description>
</vbox>
<hbox id="exportImport" hidden="true">
<button label="&zotero.integration.prefs.exportDocument;" oncommand="Zotero_File_Interface_Bibliography.exportDocument()"/>
</hbox>
</vbox>
</vbox>
</dialog>

View file

@ -81,9 +81,8 @@ var Zotero_ProgressBar = new function () {
function _onProgress(percent) {
var meter = document.querySelector(".citation-dialog.progress-meter");
if(percent === null) {
meter.mode = "undetermined";
meter.removeAttribute('value');
} else {
meter.mode = "determined";
meter.value = Math.round(percent);
}
}

View file

@ -45,7 +45,7 @@
<box orient="horizontal" class="citation-dialog entry">
<deck class="citation-dialog deck" selectedIndex="0" flex="1">
<progressmeter class="citation-dialog progress-meter" mode="undetermined" value="0" flex="1"/>
<html:progress class="citation-dialog progress-meter" max="100"/>
</deck>
</box>
</window>

View file

@ -22,7 +22,8 @@
***** END LICENSE BLOCK *****
*/
Components.utils.import("resource://gre/modules/Services.jsm");
var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
Services.scriptloader.loadSubScript("chrome://zotero/content/elements/guidancePanel.js", this);
var Zotero_QuickFormat = new function () {
const pixelRe = /^([0-9]+)px$/
@ -686,7 +687,7 @@ var Zotero_QuickFormat = new function () {
_buildItemDescription(item, infoNode);
// add to rich list item
var rll = document.createElement("richlistitem");
var rll = document.createXULElement("richlistitem");
rll.setAttribute("orient", "vertical");
rll.setAttribute("class", "citation-dialog item");
rll.setAttribute("zotero-item", item.cslItemID ? item.cslItemID : item.id);
@ -708,7 +709,7 @@ var Zotero_QuickFormat = new function () {
titleNode.setAttribute("value", labelText);
// add to rich list item
var rll = document.createElement("richlistitem");
var rll = document.createXULElement("richlistitem");
rll.setAttribute("orient", "vertical");
rll.setAttribute("disabled", true);
rll.setAttribute("class", loading ? "citation-dialog loading" : "citation-dialog separator");
@ -947,7 +948,7 @@ var Zotero_QuickFormat = new function () {
}
if(!panelFrameHeight) {
panelFrameHeight = referencePanel.boxObject.height - referencePanel.clientHeight;
panelFrameHeight = referencePanel.getBoundingClientRect().height - referencePanel.clientHeight;
var computedStyle = window.getComputedStyle(referenceBox, null);
for(var attr of ["border-top-width", "border-bottom-width"]) {
var val = computedStyle.getPropertyValue(attr);
@ -1124,11 +1125,10 @@ var Zotero_QuickFormat = new function () {
* Called when progress changes
*/
function _onProgress(percent) {
var meter = document.querySelector(".citation-dialog .progress-meter");
var meter = document.querySelector(".citation-dialog.progress-meter");
if(percent === null) {
meter.mode = "undetermined";
meter.removeAttribute('value');
} else {
meter.mode = "determined";
meter.value = Math.round(percent);
}
}
@ -1204,7 +1204,7 @@ var Zotero_QuickFormat = new function () {
var offset = range.startOffset,
childNodes = qfe.childNodes,
node = childNodes[offset-(right ? 0 : 1)];
if (node && node.dataset.citationItem) return node;
if (node && node.dataset && node.dataset.citationItem) return node;
return null;
}
@ -1507,7 +1507,7 @@ var Zotero_QuickFormat = new function () {
_updateCitationObject();
var newWindow = window.newWindow = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
.getService(Components.interfaces.nsIWindowWatcher)
.openWindow(null, 'chrome://zotero/content/integration/addCitationDialog.xul',
.openWindow(null, 'chrome://zotero/content/integration/addCitationDialog.xhtml',
'', 'chrome,centerscreen,resizable', io);
newWindow.addEventListener("focus", function() {
newWindow.removeEventListener("focus", arguments.callee, true);

View file

@ -63,14 +63,22 @@
</menupopup>
</toolbarbutton>
<iframe class="citation-dialog 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%20spellcheck=%22false%22%20class=%22citation-dialog%20editor%22/%3E%3C/html%3E"
tabindex="1" flex="1"/>
<iframe
class="citation-dialog iframe"
ondragstart="event.stopPropagation()"
src="citationDialogIframe.html"
tabindex="1"
flex="1"
type="content"
remote="false"
maychangeremoteness="false"/>
<vbox class="citation-dialog spinner" style="visibility: hidden">
<image class="zotero-spinner-16"/>
</vbox>
</hbox>
</hbox>
<progressmeter class="citation-dialog progress-meter" mode="undetermined" value="0" flex="1"/>
<html:progress class="citation-dialog progress-meter" max="100"/>
</deck>
</box>
<panel class="citation-dialog reference-panel" noautofocus="true" norestorefocus="true"
@ -84,43 +92,31 @@
<description id="citation-properties-title"/>
<hbox id="citation-properties-info"/>
</vbox>
<grid flex="1">
<columns>
<column/>
<column flex="1"/>
</columns>
<rows>
<row align="center">
<menulist id="locator-label" sizetopopup="none"
oncommand="Zotero_QuickFormat.onCitationPropertiesChanged(event)">
<menupopup id="locator-label-popup"/>
</menulist>
<textbox id="locator" flex="1"
oninput="window.setTimeout(function(event) { Zotero_QuickFormat.onCitationPropertiesChanged(event) }, 0)"/>
</row>
<row align="center">
<label value="&zotero.citation.prefix.label;"/>
<textbox class="citation-textbox" id="prefix" flex="1"
oninput="window.setTimeout(function(event) { Zotero_QuickFormat.onCitationPropertiesChanged(event) }, 0)"/>
</row>
<row align="center">
<label value="&zotero.citation.suffix.label;"/>
<textbox class="citation-textbox" id="suffix" flex="1"
oninput="window.setTimeout(function(event) { Zotero_QuickFormat.onCitationPropertiesChanged(event) }, 0)"/>
</row>
<html:div>
<html:input type="checkbox" id="suppress-author"
onchange="Zotero_QuickFormat.onCitationPropertiesChanged(event)"/>
<html:label for="suppress-author">
&zotero.citation.suppressAuthor.label;
</html:label>
</html:div>
</rows>
</grid>
<html:div id="citation-properties-grid">
<menulist id="locator-label" sizetopopup="none"
oncommand="Zotero_QuickFormat.onCitationPropertiesChanged(event)" native="true">
<menupopup id="locator-label-popup"/>
</menulist>
<html:input type="text" id="locator"
oninput="window.setTimeout(function(event) { Zotero_QuickFormat.onCitationPropertiesChanged(event) }, 0)"/>
<label value="&zotero.citation.prefix.label;"/>
<html:input type="text" class="citation-textbox" id="prefix" flex="1"
oninput="window.setTimeout(function(event) { Zotero_QuickFormat.onCitationPropertiesChanged(event) }, 0)"/>
<label value="&zotero.citation.suffix.label;"/>
<html:input type="text" class="citation-textbox" id="suffix" flex="1"
oninput="window.setTimeout(function(event) { Zotero_QuickFormat.onCitationPropertiesChanged(event) }, 0)"/>
<html:div>
<html:input type="checkbox" id="suppress-author" native="true"
onchange="Zotero_QuickFormat.onCitationPropertiesChanged(event)"/>
<html:label for="suppress-author">
&zotero.citation.suppressAuthor.label;
</html:label>
</html:div>
</html:div>
<vbox flex="1" align="center">
<button id="citation-properties-library-link" onclick="Zotero_QuickFormat.showInLibrary()"/>
</vbox>
</panel>
<guidance-panel class="citation-dialog guidance" about="quickFormat"
for="zotero-icon" x="26"/> <!-- fx-compat TODO: pull in chrome://zotero/content/elements/guidancePanel.js for this -->
for="zotero-icon" x="26"/>
</window>

View file

@ -0,0 +1,35 @@
<!DOCTYPE html>
<!--
***** BEGIN LICENSE BLOCK *****
Copyright © 2022 Center for History and New Media
George Mason University, Fairfax, Virginia, USA
http://zotero.org
This file is part of Zotero.
Zotero is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Zotero is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
***** END LICENSE BLOCK *****
-->
<html xmlns="http://www.w3.org/1999/xhtml" style="height: 100%">
<head>
<link rel="stylesheet" type="text/css" href="chrome://zotero/skin/integration.css"/>
<link rel="stylesheet" type="text/css" href="chrome://zotero-platform/content/integration.css"/>
</head>
<body style="margin: 0; height: 100%">
<div id="simple-editor" class="zotero-simpleEditor"></div>
<script type="text/javascript" src="simpleEditor.js"></script>
</body>
</html>

View file

@ -0,0 +1,581 @@
/*
***** BEGIN LICENSE BLOCK *****
Copyright © 2022 Corporation for Digital Scholarship
Vienna, Virginia, USA
http://zotero.org
This file is part of Zotero.
Zotero is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Zotero is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
*****************************
Based on https://github.com/jaredreich/pell/blob/master/src/pell.js,
which is covered by the following copyright and permission notice:
The MIT License (MIT)
Copyright (c) Jared Reich
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
***** END LICENSE BLOCK *****
*/
// Simple WYSIWYG editor using contenteditable
(function() {
var Zotero = Components.classes['@zotero.org/Zotero;1']
.getService(Components.interfaces.nsISupports)
.wrappedJSObject;
const defaultParagraphSeparatorString = 'defaultParagraphSeparator'
const formatBlock = 'formatBlock'
const addEventListener = (parent, type, listener) => parent.addEventListener(type, listener)
const appendChild = (parent, child) => parent.appendChild(child)
const createElement = tag => document.createElement(tag)
const queryCommandState = command => document.queryCommandState(command)
const queryCommandValue = command => document.queryCommandValue(command)
const exec = (command, value = null) => document.execCommand(command, false, value)
const defaultActions = {
bold: {
icon: '<b>B</b>',
title: 'Bold',
state: () => queryCommandState('bold'),
result: () => exec('bold')
},
italic: {
icon: '<i>I</i>',
title: 'Italic',
state: () => queryCommandState('italic'),
result: () => exec('italic')
},
underline: {
icon: '<u>U</u>',
title: 'Underline',
state: () => queryCommandState('underline'),
result: () => exec('underline')
},
strikethrough: {
icon: '<strike>S</strike>',
title: 'Strike-through',
state: () => queryCommandState('strikeThrough'),
result: () => exec('strikeThrough')
},
heading1: {
icon: '<b>H<sub>1</sub></b>',
title: 'Heading 1',
result: () => exec(formatBlock, '<h1>')
},
heading2: {
icon: '<b>H<sub>2</sub></b>',
title: 'Heading 2',
result: () => exec(formatBlock, '<h2>')
},
paragraph: {
icon: '&#182;',
title: 'Paragraph',
result: () => exec(formatBlock, '<p>')
},
quote: {
icon: '&#8220; &#8221;',
title: 'Quote',
result: () => exec(formatBlock, '<blockquote>')
},
olist: {
icon: '&#35;',
title: 'Ordered List',
result: () => exec('insertOrderedList')
},
ulist: {
icon: '&#8226;',
title: 'Unordered List',
result: () => exec('insertUnorderedList')
},
code: {
icon: '&lt;/&gt;',
title: 'Code',
result: () => exec(formatBlock, '<pre>')
},
line: {
icon: '&#8213;',
title: 'Horizontal Line',
result: () => exec('insertHorizontalRule')
},
link: {
icon: '&#128279;',
title: 'Link',
result: () => {
const url = window.prompt('Enter the link URL')
if (url) exec('createLink', url)
}
},
image: {
icon: '&#128247;',
title: 'Image',
result: () => {
const url = window.prompt('Enter the image URL')
if (url) exec('insertImage', url)
}
}
}
const defaultClasses = {
actionbar: 'zotero-simpleEditor-actionbar',
button: 'zotero-simpleEditor-button',
content: 'zotero-simpleEditor-content',
selected: 'zotero-simpleEditor-button-selected'
}
/**
* @param settings
* settings.actions {Array} - array of action names or objects
* settings.element {HTMLElement} - element to which attach the editor
* settings.onChange {Function} - change handler
* settings.classes {Object} - default classes overrides
* settings.defaultParagraphSeparator {String} - ["div"] element name for paragraph separator
*/
const init = settings => {
const actions = settings.actions
? (
settings.actions.map(action => {
if (typeof action === 'string') return defaultActions[action]
else if (defaultActions[action.name]) return { ...defaultActions[action.name], ...action }
return action
})
)
: Object.keys(defaultActions).map(action => defaultActions[action])
const classes = { ...defaultClasses, ...settings.classes }
const defaultParagraphSeparator = settings[defaultParagraphSeparatorString] || 'div'
const actionbar = createElement('div')
actionbar.className = classes.actionbar
appendChild(settings.element, actionbar)
const content = settings.element.content = createElement('div')
content.contentEditable = true
content.className = classes.content
content.oninput = ({ target: { firstChild } }) => {
if (firstChild && firstChild.nodeType === 3) exec(formatBlock, `<${defaultParagraphSeparator}>`)
else if (content.innerHTML === '<br>') content.innerHTML = ''
settings.onChange && settings.onChange(content.innerHTML)
}
content.onkeydown = event => {
if (event.key === 'Enter' && queryCommandValue(formatBlock) === 'blockquote') {
setTimeout(() => exec(formatBlock, `<${defaultParagraphSeparator}>`), 0)
}
}
appendChild(settings.element, content)
actions.forEach(action => {
const button = createElement('button')
button.className = classes.button
button.innerHTML = action.icon
button.title = action.title
button.setAttribute('type', 'button')
button.onclick = () => action.result() && content.focus()
if (action.state) {
const handler = () => button.classList[action.state() ? 'add' : 'remove'](classes.selected)
addEventListener(content, 'keyup', handler)
addEventListener(content, 'mouseup', handler)
addEventListener(button, 'click', handler)
}
appendChild(actionbar, button)
})
if (settings.styleWithCSS) exec('styleWithCSS')
exec(defaultParagraphSeparatorString, defaultParagraphSeparator)
return settings.element
}
var RTFConverter = new function() {
// Atomic units, HTML -> RTF (cleanup)
//[/<\/p>(?!\s*$)/g, "\\par{}"],
//[/ /g, "&nbsp;"],
//[/\u00A0/g, " "],
this._htmlRTFmap = [
[/<br \/>/g, "\x0B"],
[/<span class=\"tab\">&nbsp;<\/span>/g, "\\tab{}"],
[/&lsquo;/g, ""],
[/&rsquo;/g, ""],
[/&ldquo;/g, "“"],
[/&rdquo;/g, "”"],
[/&nbsp;/g, "\u00A0"],
[/"(\w)/g, "“$1"],
[/([\w,.?!])"/g, "$1”"],
[/<p>/g, ""],
[/<\/?div[^>]*>/g, ""]
];
// Atomic units, RTF -> HTML (cleanup)
this._rtfHTMLmap = [
[/\\uc0\{?\\u([0-9]+)\}?(?:{}| )?/g, function(wholeStr, aCode) { return String.fromCharCode(aCode) }],
[/\\tab(?:\{\}| )/g, '<span class="tab">&nbsp;</span>'],
[/(?:\\par{}|\\\r?\n)/g, "</p><p>"]
];
this.prepare = function() {
// DEBUG: Does this actually happen?
if (this.prepared) return;
// Tag data
var _rexData = [
[
[
["<span +style=\"font-variant: *small-caps;\">"],
["{\\scaps ", "{\\scaps{}"]
],
[
["<\/span>"],
["}"]
]
],
[
[
["<span +style=\"text-decoration: *underline;\">"],
["{\\ul{}", "{\\ul "]
],
[
["<\/span>"],
["}"]
]
],
[
[
["<sup>"],
["\\super ", "\\super{}"]
],
[
["</sup>"],
["\\nosupersub{}", "\\nosupersub "]
]
],
[
[
["<sub>"],
["\\sub ", "\\sub{}"]
],
[
["</sub>"],
["\\nosupersub{}", "\\nosupersub "]
]
],
[
[
["<em>"],
["{\\i{}", "{\\i "]
],
[
["</em>"],
["}"]
]
],
[
[
["<i>"],
["{\\i{}", "{\\i "]
],
[
["</i>"],
["}"]
]
],
[
[
["<b>"],
["{\\b{}", "{\\b "]
],
[
["</b>"],
["}"]
]
],
[
[
["<strong>"],
["{\\b{}", "{\\b "]
],
[
["</strong>"],
["}"]
]
],
[
[
["<span +style=\"font-variant: *normal;\">"],
["{\\scaps0{}", "{\\scaps0 "]
],
[
["</span>"],
["}"]
]
],
[
[
["<span +style=\"font-style: *normal;\">"],
["{\\i0{}", "{\\i0 "]
],
[
["</span>"],
["}"]
]
],
[
[
["<span +style=\"font-weight: *normal;\">"],
["{\\b0{}", "{\\b0 "]
],
[
["</span>"],
["}"]
]
]
];
function longestFirst(a, b) {
if (a.length < b.length) {
return 1;
} else if (a.length > b.length) {
return -1;
} else {
return 0;
}
}
function normalizeRegExpString(str) {
if (!str) return str;
return str.replace(/\s+/g, " ")
.replace(/(?:[\+]|\s[\*])/g, "")
.replace(/[\']/g, '\"')
.replace(/:\s/g, ":");
}
this.normalizeRegExpString = normalizeRegExpString;
function composeRex(rexes, noGlobal) {
var lst = [];
for (var rex in rexes) {
lst.push(rex);
}
lst.sort(longestFirst);
var rexStr = "(?:" + lst.join("|") + ")";
return new RegExp(rexStr, "g");
}
// Create splitting regexps
function splitRexMaker(segment) {
var rexes = {};
for (var i=0,ilen=_rexData.length; i < ilen; i++) {
for (var j=0,jlen=_rexData[i].length; j < jlen; j++) {
for (var k=0,klen=_rexData[i][j][segment].length; k < klen; k++) {
rexes[_rexData[i][j][segment][k].replace("\\", "\\\\")] = true;
}
}
}
var ret = composeRex(rexes, true);
return ret;
}
this.rtfHTMLsplitRex = splitRexMaker(1);
this.htmlRTFsplitRex = splitRexMaker(0);
// Create open-tag sniffing regexp
function openSniffRexMaker(segment) {
var rexes = {};
for (var i=0,ilen=_rexData.length; i < ilen; i++) {
for (var j=0,jlen=_rexData[i][0][segment].length; j < jlen; j++) {
rexes[_rexData[i][0][segment][j].replace("\\", "\\\\")] = true;
}
}
return composeRex(rexes);
}
this.rtfHTMLopenSniffRex = openSniffRexMaker(1);
this.htmlRTFopenSniffRex = openSniffRexMaker(0);
// Create open-tag remapper
function openTagRemapMaker(segment) {
var ret = {};
for (var i=0,ilen=_rexData.length; i < ilen; i++) {
var primaryVal = normalizeRegExpString(_rexData[i][0][segment][0]);
for (var j=0,jlen=_rexData[i][0][segment].length; j < jlen; j++) {
var key = normalizeRegExpString(_rexData[i][0][segment][j]);
ret[key] = primaryVal;
}
}
return ret;
}
this.rtfHTMLopenTagRemap = openTagRemapMaker(1);
this.htmlRTFopenTagRemap = openTagRemapMaker(0);
// Create open-tag-keyed close-tag sniffing regexps
function closeTagRexMaker(segment) {
var ret = {};
var rexes = {};
for (var i=0,ilen=_rexData.length; i < ilen; i++) {
var primaryVal = _rexData[i][0][segment][0];
for (var j=0,jlen=_rexData[i][1][segment].length; j < jlen; j++) {
rexes[_rexData[i][1][segment][j]] = true;
}
ret[primaryVal] = composeRex(rexes);
}
return ret;
}
this.rtfHTMLcloseTagRex = closeTagRexMaker(1);
this.htmlRTFcloseTagRex = closeTagRexMaker(0);
// Create open-tag-keyed open/close tag registry
function tagRegistryMaker(segment) {
var antisegment = 1;
if (segment == 1) {
antisegment = 0;
}
var ret = {};
for (var i=0,ilen=_rexData.length; i < ilen; i++) {
var primaryVal = normalizeRegExpString(_rexData[i][0][segment][0]);
ret[primaryVal] = {
open: normalizeRegExpString(_rexData[i][0][antisegment][0]),
close: _rexData[i][1][antisegment][0]
}
}
return ret;
}
this.rtfHTMLtagRegistry = tagRegistryMaker(1);
this.htmlRTFtagRegistry = tagRegistryMaker(0);
this.prepared = true;
}
this.prepare();
this.getSplit = function(mode, txt) {
if (!txt) return [];
var splt = txt.split(this[mode + "splitRex"]);
var mtch = txt.match(this[mode + "splitRex"]);
var lst = [splt[0]];
for (var i=1,ilen=splt.length; i < ilen; i++) {
lst.push(mtch[i-1]);
lst.push(splt[i]);
}
return lst;
}
this.getOpenTag = function(mode, str) {
var m = str.match(this[mode + "openSniffRex"]);
if (m) {
m = this[mode + "openTagRemap"][this.normalizeRegExpString(m[0])];
}
return m;
}
this.convert = function(mode, txt) {
var lst = this.getSplit(mode, txt);
var sdepth = 0;
var depth = 0;
for (var i=1,ilen=lst.length; i < ilen; i += 2) {
var openTag = this.getOpenTag(mode, lst[i]);
if (openTag) {
sdepth++;
depth = sdepth;
for (var j=(i+2),jlen=lst.length; j < jlen; j += 2) {
var closeTag = !this.getOpenTag(mode, lst[j]);
if (closeTag) {
if (depth === sdepth && lst[j].match(this[mode + "closeTagRex"][openTag])) {
lst[i] = this[mode + "tagRegistry"][openTag].open;
lst[j] = this[mode + "tagRegistry"][openTag].close;
break;
}
depth--;
} else {
depth++;
}
}
} else {
sdepth--;
}
}
return lst.join("");
}
this.htmlToRTF = function(txt) {
txt = this.convert("htmlRTF", txt);
for (var i=0,ilen=this._htmlRTFmap.length; i < ilen; i++) {
var entry = this._htmlRTFmap[i];
txt = txt.replace(entry[0], entry[1]);
}
txt = Zotero.Utilities.unescapeHTML(txt);
txt = txt.replace(/[\x7F-\uFFFF]/g, function(aChar) { return "\\uc0\\u"+aChar.charCodeAt(0).toString()+"{}"});
return txt.trim();
}
this.rtfToHTML = function(txt) {
for (var i=0,ilen=this._rtfHTMLmap.length; i < ilen; i++) {
var entry = this._rtfHTMLmap[i];
txt = txt.replace(entry[0], entry[1]);
}
txt = this.convert("rtfHTML", txt);
return txt.trim();
}
}
init({
element: document.querySelector('#simple-editor'),
actions: ['bold', 'italic', 'underline']
});
var editorContents = document.querySelector('.zotero-simpleEditor-content');
window.editor = {
get element() {
document.querySelector('#simple-editor');
},
setContent(content, isRTF) {
if (isRTF) {
content = RTFConverter.rtfToHTML(content);
}
editorContents.innerHTML = content;
},
getContent(asRTF) {
let content = editorContents.innerHTML;
if (asRTF) {
return RTFConverter.htmlToRTF(content);
}
return content;
},
setEnabled(enabled) {
editorContents.setAttribute('contenteditable', !!enabled);
}
}
})();

View file

@ -76,7 +76,7 @@ WindowDraggingElement.prototype = {
return true;
},
isPanel : function() {
return this._elem instanceof Components.interfaces.nsIDOMXULElement &&
return this._elem instanceof XULElement &&
this._elem.localName == "panel";
},
handleEvent: function(aEvent) {

View file

@ -35,48 +35,32 @@ var { makeRowRenderer } = VirtualizedTable;
Zotero_Preferences.Cite = {
styles: [],
wordPluginIDs: new Set([
'zoteroOpenOfficeIntegration@zotero.org',
'zoteroMacWordIntegration@zotero.org',
'zoteroWinWordIntegration@zotero.org'
]),
wordPluginResourcePaths: {
libreOffice: 'zotero-libreoffice-integration',
macWord: 'zotero-macword-integration',
winWord: 'zotero-winword-integration'
},
init: async function () {
Components.utils.import("resource://gre/modules/AddonManager.jsm");
this.updateWordProcessorInstructions();
await this.refreshStylesList();
},
/**
* Determines if any word processors are disabled and if so, shows a message in the pref pane
*/
updateWordProcessorInstructions: async function () {
var someDisabled = false;
await new Promise(function(resolve) {
AddonManager.getAllAddons(function(addons) {
for (let addon of addons) {
if (Zotero_Preferences.Cite.wordPluginIDs.has(addon.id) && addon.userDisabled) {
someDisabled = true;
}
}
resolve();
});
});
if (someDisabled) {
document.getElementById("wordProcessors-somePluginsDisabled").hidden = undefined;
// Init word plugin sections
let wordPlugins = ['libreOffice'];
if (Zotero.isWindows) {
wordPlugins.push('winWord');
}
},
enableWordPlugins: function () {
AddonManager.getAllAddons(function(addons) {
for (let addon of addons) {
if (Zotero_Preferences.Cite.wordPluginIDs.has(addon.id) && addon.userDisabled) {
addon.userDisabled = false;
}
else if (Zotero.isMac) {
wordPlugins.push('macWord');
}
await Zotero.Promise.delay();
for (let wordPlugin of wordPlugins) {
// This is the weirdest indirect code, but let's not fix what's not broken
try {
var installer = Components.utils.import(`resource://${this.wordPluginResourcePaths[wordPlugin]}/installer.jsm`).Installer;
(new installer(true)).showPreferences(document);
} catch(e) {
Zotero.logError(e);
}
return Zotero.Utilities.Internal.quit(true);
});
}
await this.refreshStylesList();
},

View file

@ -71,14 +71,6 @@
<vbox class="main-section" id="wordProcessors">
<html:h1>&zotero.preferences.cite.wordProcessors;</html:h1>
<vbox id="wordProcessors-somePluginsDisabled" hidden="true">
<label style="font-weight: bold; margin-top: 1em; text-align: center">Some word processor plugins are disabled.</label>
<hbox pack="center" style="margin-bottom: 2em">
<button id="wordProcessors-enablePlugins"
label="Enable Plugins and Restart Zotero"
oncommand="Zotero_Preferences.Cite.enableWordPlugins()"/>
</hbox>
</vbox>
<checkbox label="&zotero.preferences.cite.wordProcessors.useClassicAddCitationDialog;" preference="extensions.zotero.integration.useClassicAddCitationDialog" native="true"/>
</vbox>
</vbox>

View file

@ -1,14 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://zotero/skin/zotero.css" type="text/css"?>
<window id="zotero-progress-meter-window"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
windowtype="alert:alert">
<vbox id="zotero-progress-text-box" flex="1">
<label/>
<progressmeter/>
</vbox>
</window>

View file

@ -0,0 +1,49 @@
<?xml version="1.0"?>
<!--
***** BEGIN LICENSE BLOCK *****
Copyright © 2022 Corporation for Digital Scholarship
Vienna, Virginia, USA
https://www.zotero.org
This file is part of Zotero.
Zotero is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Zotero is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
***** END LICENSE BLOCK *****
-->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://global/skin/browser.css" type="text/css"?>
<?xml-stylesheet href="chrome://zotero/skin/zotero.css" type="text/css"?>
<!DOCTYPE window SYSTEM "chrome://zotero/locale/zotero.dtd">
<window id="zotero-progress"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
title="&zotero.progress.title;"
width="300" height="30"
style="max-height: 20px"
windowtype="alert:alert">
<vbox id="zotero-progress-text-box" flex="1" style="padding: 10px">
<hbox align="stretch">
<label id="progress-label" flex="1"/>
</hbox>
<html:progress id="progress-indicator" max="100"/>
</vbox>
<script>
window.addEventListener("DOMContentLoaded", () => window.sizeToContent())
</script>
</window>

View file

@ -1,15 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://zotero/skin/zotero.css" type="text/css"?>
<window id="zotero-progress-window"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
windowtype="alert:alert">
<hbox id="zotero-progress-box">
<vbox id="zotero-progress-text-box" flex="1">
<hbox id="zotero-progress-text-headline" pack="start"/>
</vbox>
</hbox>
</window>

View file

@ -73,6 +73,27 @@ Zotero.Integration = new function() {
this.currentWindow = false;
this.sessions = {};
var upgradeTemplateNotNowTime = 0;
/**
* Initialize LibreOffice, Word for Mac and Word for Windows plugin components.
*/
this.init = function () {
let classNames = ["@zotero.org/Zotero/integration/initializer?agent=LibreOffice;1"];
if (Zotero.isMac) {
classNames.push("@zotero.org/Zotero/integration/installer?agent=MacWord;1")
} else if (Zotero.isWindows) {
classNames.push("@zotero.org/Zotero/integration/installer?agent=WinWord;1")
}
for (let className of classNames) {
try {
Components.classes[className]
.getService(Components.interfaces.nsISupports);
}
catch (e) {
Zotero.logError(e);
}
}
}
/**
* Begin listening for integration commands on the given pipe
@ -1443,15 +1464,15 @@ Zotero.Integration.Session.prototype.cite = async function (field, addNote=false
var mode = (!Zotero.isMac && Zotero.Prefs.get('integration.keepAddCitationDialogRaised')
? 'popup' : 'alwaysRaised')+',resizable=false';
if (addNote) {
Zotero.Integration.displayDialog('chrome://zotero/content/integration/insertNoteDialog.xul',
Zotero.Integration.displayDialog('chrome://zotero/content/integration/insertNoteDialog.xhtml',
mode, io);
}
else if (Zotero.Prefs.get("integration.useClassicAddCitationDialog")) {
Zotero.Integration.displayDialog('chrome://zotero/content/integration/addCitationDialog.xul',
Zotero.Integration.displayDialog('chrome://zotero/content/integration/addCitationDialog.xhtml',
'alwaysRaised,resizable', io);
}
else {
Zotero.Integration.displayDialog('chrome://zotero/content/integration/quickFormat.xul',
Zotero.Integration.displayDialog('chrome://zotero/content/integration/quickFormat.xhtml',
mode, io);
}
@ -1836,7 +1857,7 @@ Zotero.Integration.Session.prototype.setDocPrefs = async function (showImportExp
// Make sure styles are initialized for new docs
await Zotero.Styles.init();
await Zotero.Integration.displayDialog('chrome://zotero/content/integration/integrationDocPrefs.xul', '', io);
await Zotero.Integration.displayDialog('chrome://zotero/content/integration/integrationDocPrefs.xhtml', '', io);
if (io.exportDocument) {
return this.exportDocument();
@ -2292,20 +2313,23 @@ Zotero.Integration.Session.prototype.promptForRetraction = function (citedItem,
* Edits integration bibliography
* @param {Zotero.Integration.Bibliography} bibliography
*/
Zotero.Integration.Session.prototype.editBibliography = Zotero.Promise.coroutine(function *(bibliography) {
Zotero.Integration.Session.prototype.editBibliography = async function (bibliography) {
if (!Object.keys(this.citationsByIndex).length) {
throw new Error('Integration.Session.editBibliography: called without loaded citations');
}
yield bibliography.loadItemData();
// Update citeproc with citations in the doc
await this._updateCitations();
await bibliography.loadItemData();
await bibliography.getCiteprocBibliography(this.style);
var bibliographyEditor = new Zotero.Integration.BibliographyEditInterface(bibliography, this.citationsByItemID, this.style);
yield Zotero.Integration.displayDialog('chrome://zotero/content/integration/editBibliographyDialog.xul', 'resizable', bibliographyEditor);
await Zotero.Integration.displayDialog('chrome://zotero/content/integration/editBibliographyDialog.xhtml', 'resizable', bibliographyEditor);
if (bibliographyEditor.cancelled) throw new Zotero.Exception.UserCancelled("bibliography editing");
this.bibliographyDataHasChanged = this.bibliographyHasChanged = true;
this.bibliography = bibliographyEditor.bibliography;
});
};
/**
* @class Interface for bibliography editor to alter document bibliography
@ -2321,9 +2345,10 @@ Zotero.Integration.BibliographyEditInterface = function(bibliography, citationsB
this._update();
}
Zotero.Integration.BibliographyEditInterface.prototype._update = Zotero.Promise.coroutine(function* () {
Zotero.Integration.BibliographyEditInterface.prototype._update = function () {
this.bib = this.bibliography.getCiteprocBibliography(this.citeproc);
});
};
/**
* Reverts the text of an individual bibliography entry
@ -2336,12 +2361,12 @@ Zotero.Integration.BibliographyEditInterface.prototype.revert = function(itemID)
/**
* Reverts bibliography to condition in which no edits have been made
*/
Zotero.Integration.BibliographyEditInterface.prototype.revertAll = Zotero.Promise.coroutine(function* () {
Zotero.Integration.BibliographyEditInterface.prototype.revertAll = function () {
this.bibliography.customEntryText = {};
this.bibliography.uncitedItemIDs.clear();
this.bibliography.omittedItemIDs.clear();
return this._update();
});
};
/**
* Reverts bibliography to condition before BibliographyEditInterface was opened
@ -3052,7 +3077,7 @@ Zotero.Integration.Citation = class {
io.addBorder = Zotero.isWin;
io.singleSelection = true;
await Zotero.Integration.displayDialog('chrome://zotero/content/selectItemsDialog.xul', 'resizable', io);
await Zotero.Integration.displayDialog('chrome://zotero/content/selectItemsDialog.xhtml', 'resizable', io);
if (io.dataOut && io.dataOut.length) {
return Zotero.Items.get(io.dataOut[0]);
@ -3374,7 +3399,7 @@ Zotero.Integration.Progress = class {
io.isNote = this.isNote;
this.window = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
.getService(Components.interfaces.nsIWindowWatcher)
.openWindow(null, 'chrome://zotero/content/integration/progressBar.xul', '', options, io);
.openWindow(null, 'chrome://zotero/content/integration/progressBar.xhtml', '', options, io);
Zotero.Utilities.Internal.activate(this.window);
}
async hide(fast=false) {

View file

@ -594,8 +594,11 @@ Zotero.Styles = new function() {
// Make sure the locale we want to select is in the menulist
if (availableLocales.indexOf(selectLocale) == -1) {
let customLocale = menulist.insertItemAt(0, selectLocale, selectLocale);
customLocale.setAttributeNS('zotero:', 'customLocale', true);
var menuitem = menulist.ownerDocument.createXULElement('menuitem');
menuitem.setAttribute('label', selectLocale);
menuitem.setAttribute('value', selectLocale);
menuitem.setAttributeNS('zotero:', 'customLocale', true);
menulist.append(menuitem);
}
return menulist.value = selectLocale;

View file

@ -2362,8 +2362,7 @@ Zotero.Utilities.Internal.activate = new function() {
* 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 windowTitle = win.getInterface(Ci.nsIWebNavigation).title;
var x11Window = _X11FindWindow(_x11RootWindow, windowTitle);
if(!x11Window) return;

View file

@ -445,6 +445,8 @@ Services.scriptloader.loadSubScript("resource://zotero/polyfill.js");
Zotero.debug('Triggering "zotero-loaded" event');
Services.obs.notifyObservers(Zotero, "zotero-loaded", null);
Zotero.debug('Initializing Word Processor plugins');
Zotero.Integration.init();
await Zotero.Plugins.init();
}

View file

@ -74,10 +74,6 @@
padding: 0 !important;
}
#prefix, #suffix {
width: 200px;
}
#tree-locator {
width: 60px;
}
@ -91,6 +87,12 @@
max-height: 100px;
}
#item-list richlistitem image {
margin-right: 5px;
height: 16px;
vertical-align: top;
}
.citation-dialog.title {
margin: 0;
font-weight: bold;
@ -144,11 +146,13 @@
height: 9999px;
}
body {
.citation-dialog.editor {
padding: 0 2px 0 2px;
margin: 0;
font: -moz-field;
overflow: hidden;
outline: none;
line-height: 2em;
}
.citation-dialog.spinner {
@ -190,6 +194,10 @@ richlistitem[selected="true"] {
-moz-user-focus: ignore;
}
.citation-dialog.reference-panel:is(panel, menupopup)::part(content) {
display: contents;
}
.citation-dialog.reference-list {
margin: 0;
padding: 0;
@ -213,6 +221,10 @@ richlistitem[selected="true"] {
margin: 0;
}
#citation-properties:is(panel, menupopup)::part(content) {
padding: 10px;
}
#citation-properties #suppress-author {
-moz-user-focus: normal;
}
@ -237,6 +249,46 @@ richlistitem[selected="true"] {
margin-bottom: 3px;
}
#citation-properties-grid {
display: grid;
align-items: center;
grid-template-columns: max-content 1fr;
}
.zotero-simpleEditor {
box-sizing: border-box;
font-size: 14px;
height: 100%;
}
.zotero-simpleEditor-content {
box-sizing: border-box;
outline: 0;
overflow-y: auto;
padding: 36px 10px 10px 10px;
}
.zotero-simpleEditor-actionbar {
background-color: #fff;
border-bottom: 1px solid rgba(10, 10, 10, 0.1);
position: fixed;
width: 100%;
}
.zotero-simpleEditor-button {
background-color: transparent;
border: none;
cursor: pointer;
height: 30px;
outline: 0;
width: 30px;
vertical-align: bottom;
}
.zotero-simpleEditor-button-selected {
background-color: #f0f0f0;
}
panel button .button-text {
margin: 0 !important;
}

View file

@ -52,6 +52,11 @@ richlistitem, richlistitem > * {
text-overflow: ellipsis;
}
richlistcheckbox[selected=true] {
background-color: -moz-cellhighlight;
color: -moz-cellhighlighttext;
}
groupbox > label > h2, groupbox > * > label > h2 {
font-size: 14px;
margin-top: 1em;

View file

@ -36,7 +36,6 @@ var Zotero = Components.classes["@zotero.org/Zotero;1"]
.wrappedJSObject;
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/AddonManager.jsm");
var installationInProgress = false;
var _runningTimers = [];
@ -63,52 +62,32 @@ var ZoteroPluginInstaller = function(addon, failSilently, force) {
this.prefPaneDoc = null;
var me = this;
var extensionIDs = [this._addon.EXTENSION_ID].concat(this._addon.REQUIRED_ADDONS.map(req => req.id));
Zotero.debug("PluginInstaller: fetching addon info");
AddonManager.getAddonsByIDs(extensionIDs, function(addons) {
Zotero.debug("PluginInstaller: addon info fetched");
me._addonInfo = addons[0];
me._addonInfoAvailable();
});
this.init();
};
ZoteroPluginInstaller.prototype = {
_errorDisplayed: false,
_addonInfoAvailable: function() {
init: async function() {
if (this._initialized) return;
Zotero.debug("PluginInstaller: fetching addon info");
Zotero.debug("PluginInstaller: addon info fetched");
try {
this._version = this._addonInfo.version;
try {
this._addon.verifyNotCorrupt(this);
} catch(e) {
Zotero.debug("Not installing +this._addon.EXTENSION_STRING+: "+e.toString());
return;
}
var version = this.prefBranch.getCharPref("version");
if(this.force || (
(
Services.vc.compare(version, this._addon.LAST_INSTALLED_FILE_UPDATE) < 0
|| (!Zotero.isStandalone && !this.prefBranch.getBoolPref("installed"))
)
&& !this.prefBranch.getBoolPref("skipInstallation")
)) {
var me = this;
this._version = (await Zotero.File.getContentsFromURLAsync(this._addon.VERSION_FILE)).trim();
var version = this.prefBranch.getCharPref("version");
if (this.force || (Services.vc.compare(version, this._addon.LAST_INSTALLED_FILE_UPDATE) < 0
&& !this.prefBranch.getBoolPref("skipInstallation"))) {
if (installationInProgress) {
Zotero.debug(`${this._addon.APP} extension installation is already in progress`);
return;
}
installationInProgress = true;
if(!this._addon.DISABLE_PROGRESS_WINDOW) {
this._progressWindow = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
.getService(Components.interfaces.nsIWindowWatcher)
.openWindow(null, "chrome://"+this._addon.EXTENSION_DIR+"/content/progress.xul", '',
"chrome,resizable=no,close=no,centerscreen", null);
this._progressWindow.addEventListener("load", function() { me._firstRunListener() }, false);
.openWindow(null, "chrome://zotero/content/progressWindow.xhtml", '',
"chrome,resizable=no,close=no,centerscreen", null);
this._progressWindow.addEventListener("load", () => { this._firstRunListener() }, false);
} else {
this._addon.install(this);
}
@ -118,24 +97,21 @@ ZoteroPluginInstaller.prototype = {
} finally {
installationInProgress = false;
}
this._initialized = true;
},
_errorDisplayed: false,
isInstalled: function() {
while(!this._version) Zotero.mainThread.processNextEvent(true);
return this.prefBranch.getBoolPref("installed");
},
getAddonPath: function(addonID) {
return this._addonInfo.getResourceURI().
QueryInterface(Components.interfaces.nsIFileURL).file;
},
setProgressWindowLabel: function(value) {
if(this._progressWindow) this._progressWindowLabel.value = value;
if (this._progressWindow) this._progressWindowLabel.value = value;
},
closeProgressWindow: function(value) {
if(this._progressWindow) this._progressWindow.close();
if (this._progressWindow) this._progressWindow.close();
},
success: function() {

View file

@ -41,3 +41,8 @@
@import "components/collection-tree";
@import "components/virtualized-table";
@import "components/item-tree";
// Elements
// --------------------------------------------------
@import "elements/richlistCheckbox";

View file

@ -0,0 +1,49 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
richlistcheckbox {
display: flex;
line-height: 1.5em;
checkbox {
padding: 0;
margin: 0
}
}
richlistcheckbox[selected="true"] {
background-color: -moz-cellhighlight;
color: -moz-cellhighlighttext;
}
richlistbox:where(:focus) > richlistcheckbox[selected="true"] {
background-color: SelectedItem;
color: SelectedItemText;
}
richlistbox[seltype="multiple"]:focus > richlistcheckbox[current="true"],
richlistbox.theme-listbox:focus > richlistcheckbox[current="true"] {
outline: var(--default-focusring);
outline-color: SelectedItem;
outline-offset: calc(-1 * var(--default-focusring-width));
}
richlistbox[seltype="multiple"]:focus > richlistcheckbox[current="true"][selected="true"],
richlistbox.theme-listbox:focus > richlistcheckbox[current="true"][selected="true"] {
outline-color: #F3D982; /* TODO: find a suitable system color */
}
richlistbox.theme-listbox:not(:focus) > richlistcheckbox[selected="true"] {
background-color: -moz-cellhighlight;
color: -moz-cellhighlighttext;
}
richlistbox.theme-listbox > richlistcheckbox > label {
margin: 0px;
padding-top: 0px;
padding-bottom: 1px;
padding-inline-start: 4px;
padding-inline-end: 0px;
white-space: nowrap;
}