Quick-format: do not hide reference panel (#3816)

Citation dialog: keep reference panel open without selection

- Reference panel remains opened while the focus is on an input
- The first item from the reference panel is no longer selected by default
to avoid unwanted items being added as a bubble
- The first item from the reference panel is selected only when the
dialog has no bubbles or when a search for a non-empty input has ran
- Shift-Enter from input or reference panel will accept the dialog's
state instead of creating a bubble
- Ensure that the reference panel reloads when a bubble is deleted
- Added button to accept the citation dialog

Some other changes:
- Z-icon and spinner/accept icon occupy the same amount
of space
- Ensure that window's width is 800px
- Set the editor's width dynamically when DOM is loaded
- Remove not used css classes and css adding margins to
z-icon.
- Do not accept/bubbleize while loading
This commit is contained in:
abaevbog 2024-03-18 08:27:21 -04:00 committed by GitHub
parent 3dc37183b4
commit 1eaff8110c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 86 additions and 78 deletions

View file

@ -3,10 +3,6 @@ body {
font-size: 15px;
}
body[multiline="true"] {
line-height: 26px;
}
window.citation-dialog {
background: transparent;
-moz-appearance: none;
@ -18,13 +14,6 @@ window.citation-dialog {
height: 37px;
}
.citation-dialog.search {
padding: 2px 2px 0 2px;
margin: 2.5px 3.5px;
border: 1px solid rgba(0, 0, 0, 0.5);
-moz-appearance: none;
border-radius: 10px;
}
.citation-dialog.entry {
@ -36,10 +25,6 @@ window.citation-dialog {
background: -moz-linear-gradient(-90deg, rgb(249, 231, 179) 0, rgb(228, 193, 94) 50%, rgb(221, 184, 81) 50%);
}
#zotero-icon {
margin: -1px 0 0 4px;
-moz-appearance: none;
}
#citation-properties menulist {
-moz-appearance: none; color: #fff;

View file

@ -2,23 +2,7 @@ body {
line-height: 1.5em;
}
.citation-dialog.search:not([multiline="true"]) {
height: 29px !important;
}
.citation-dialog.search {
padding: 0 2px 0 0;
border: 1px solid rgba(0, 0, 0, 0.5);
-moz-appearance: textfield;
}
window.citation-dialog {
-moz-appearance: none;
padding: 5px;
}
#zotero-icon {
padding: 4px 4px 6px 4px !important;
margin: 2px 0;
-moz-appearance: none;
}

View file

@ -4,16 +4,6 @@ window.citation-dialog {
-moz-appearance: none;
}
.citation-dialog.search {
padding: 2px 2px 2px 0;
border: 1px solid rgba(0, 0, 0, 0.5);
border-radius: 10px;
-moz-appearance: none;
}
.citation-dialog.search:not([multiline="true"]) {
height: 28px !important;
}
.citation-dialog.entry {
background: -moz-linear-gradient(-90deg, rgb(243,123,119) 0, rgb(180,47,38) 50%, rgb(156,36,27) 50%);
@ -29,10 +19,6 @@ window.citation-dialog {
border-radius: 15px;
}
#zotero-icon {
margin: -1px 0 0 4px;
-moz-appearance: none;
}
body {
line-height: 1.65em;

View file

@ -42,7 +42,6 @@ var Zotero_QuickFormat = new function () {
isPaste = false, _itemPopoverClosed, skipInputRefocus;
var locatorNode = null;
var _searchPromise;
var inputIsPristine = true;
var _lastFocusedInput = null;
var _bubbleMouseDown = false;
@ -85,6 +84,7 @@ var Zotero_QuickFormat = new function () {
dialog = document.querySelector(".citation-dialog.entry");
editor = document.querySelector(".citation-dialog.editor");
_resizeEditor();
dialog.addEventListener("click", _onQuickSearchClick, false);
dialog.addEventListener("keypress", _onQuickSearchKeyPress, false);
editor.addEventListener("dragover", _onEditorDragOver);
@ -94,7 +94,7 @@ var Zotero_QuickFormat = new function () {
// Navigation within the reference panel
referenceBox.addEventListener("keypress", (event) => {
// Enter or ; selects the reference
if (event.key == "Enter" || event.charCode == 59) {
if ((event.key == "Enter" && !event.shiftKey) || event.charCode == 59) {
event.preventDefault();
event.stopPropagation();
event.target.closest("richlistitem").click();
@ -118,8 +118,15 @@ var Zotero_QuickFormat = new function () {
_lastFocusedInput.focus();
}
else if (["ArrowDown", "ArrowUp"].includes(event.key)) {
// ArrowUp from first item focuses the input
if (referenceBox.selectedIndex == 1 && event.key == "ArrowUp") {
_lastFocusedInput.focus();
referenceBox.selectedIndex = -1;
}
else {
handleItemSelection(event);
}
}
// Right/Left arrow will hide ref panel and move focus to the previour/next element
else if ("ArrowLeft" == event.key) {
_lastFocusedInput.focus();
@ -858,10 +865,14 @@ var Zotero_QuickFormat = new function () {
});
}
let currentInput = _getCurrentInput();
// Do not select the item in reference panel if the editor
// is non-empty and nothing has been typed yet
if (selectedIndex > 1 || isEditorCleared() || !isInputEmpty(currentInput)) {
referenceBox.selectedIndex = selectedIndex;
}
referenceBox.ensureIndexIsVisible(selectedIndex);
// Record the last input used for a search
let currentInput = _getCurrentInput();
if (currentInput) {
_lastFocusedInput = currentInput;
}
@ -1102,7 +1113,7 @@ var Zotero_QuickFormat = new function () {
this._bubbleizeSelected = Zotero.Promise.coroutine(function* () {
const panelShowing = referencePanel.state === "open" || referencePanel.state === "showing";
let inputExists = _lastFocusedInput || _getCurrentInput()
if(!panelShowing || !referenceBox.hasChildNodes() || !referenceBox.selectedItem) return false;
if(!panelShowing || !referenceBox.hasChildNodes() || !referenceBox.selectedItem || _searchPromise?.isPending()) return false;
if(!referenceBox.hasChildNodes() || !referenceBox.selectedItem || !inputExists) return false;
var citationItem = {"id":referenceBox.selectedItem.getAttribute("zotero-item")};
@ -1154,9 +1165,6 @@ var Zotero_QuickFormat = new function () {
let newBubble = _insertBubble(citationItem, input);
isPaste = false;
_clearEntryList();
// After the first bubble was made, the next input should not display the panel
// even if there were no searches yet
inputIsPristine = false;
clearLastFocused(input);
input.remove();
@ -1174,6 +1182,19 @@ var Zotero_QuickFormat = new function () {
e.preventDefault();
}
// Set the editor's width so that it fills up all remaining space in the window.
// It should be window.width - padding - icon wrappers width. The is needed to be explicitly set
// so that the editor's height expands/shrinks vertically without going outside of the
// window boundaries.
function _resizeEditor() {
let editorParentWidth = editor.parentNode.getBoundingClientRect().width;
let iconWrapperWidth = document.querySelector(".citation-dialog.icons").getBoundingClientRect().width;
let editorDesiredWidth = editorParentWidth - iconWrapperWidth * 2;
// Sanity check: editor width should never be that small
if (editorDesiredWidth > 700) {
editor.style.width = `${editorDesiredWidth}px`;
}
}
function _resizeWindow() {
let box = document.querySelector(".citation-dialog.entry");
let contentHeight = box.getBoundingClientRect().height;
@ -1217,13 +1238,8 @@ var Zotero_QuickFormat = new function () {
break;
}
}
let inputNode = _getCurrentInput() || _lastFocusedInput;
// References should be shown if:
// - there are matching items and the input is non-empty
// - the dialog just opened
// - everything but the last, non-removable, input has been cleared.
// Otherwise, the panel is hidden.
let showReferencePanel = visibleNodes.length > 0 && (!isInputEmpty(inputNode) || inputIsPristine || isEditorCleared());
// References should be shown whenever there are matching items
let showReferencePanel = visibleNodes.length > 0;
if (!showReferencePanel) {
referencePanel.hidePopup();
return;
@ -1428,8 +1444,8 @@ var Zotero_QuickFormat = new function () {
/**
* Accepts current selection and adds citation
*/
this._accept = function() {
if(accepted) return;
this.accept = function() {
if (accepted || _searchPromise?.isPending()) return;
accepted = true;
try {
_updateCitationObject();
@ -1464,7 +1480,7 @@ var Zotero_QuickFormat = new function () {
}
else if (event.key == "Enter") {
event.preventDefault();
Zotero_QuickFormat._accept();
Zotero_QuickFormat.accept();
}
// In rare circumstances, the focus can get lost (e.g. if the focus is on an item
// in reference panel when it is refreshed and all nodes are deleted).
@ -1567,7 +1583,8 @@ var Zotero_QuickFormat = new function () {
*/
function _resetSearchTimer() {
// Show spinner
var spinner = document.querySelector('.citation-dialog.spinner image');
var spinner = document.querySelector('.citation-dialog.icons.end image');
spinner.nextElementSibling.style.display = "none";
spinner.setAttribute("status", "animate");
// Cancel current search if active
if (_searchPromise && _searchPromise.isPending()) {
@ -1577,9 +1594,9 @@ var Zotero_QuickFormat = new function () {
_searchPromise = Zotero.Promise.delay(SEARCH_TIMEOUT)
.then(() => _quickFormat())
.then(() => {
inputIsPristine = false;
_searchPromise = null;
spinner.removeAttribute("status");
spinner.nextElementSibling.style.removeProperty("display");
});
}
@ -1697,7 +1714,7 @@ var Zotero_QuickFormat = new function () {
var onInputPress = function (event) {
if (accepted) return;
if ((event.charCode === 59 /* ; */ || event.key === "Enter") && referencePanel.state === "open") {
if ((event.charCode === 59 /* ; */ || (event.key === "Enter" && !event.shiftKey)) && referenceBox.selectedIndex >= 1) {
event.preventDefault();
event.stopPropagation();
Zotero_QuickFormat._bubbleizeSelected();
@ -1723,19 +1740,30 @@ var Zotero_QuickFormat = new function () {
this.previousElementSibling.remove();
_combineNeighboringInputs();
}
// If this removed the last bubble, make sure the reference panel is open
if (isEditorCleared()) {
// Rerun search to update opened documents section if needed
_resetSearchTimer();
}
}
else if (["ArrowDown", "ArrowUp"].includes(event.key) && referencePanel.state === "open") {
// Arrow up/down from wherever will navigate the references panel if that's opened
// ArrowUp when item is selected does nothing
if (referenceBox.selectedIndex < 1 && event.key == "ArrowUp") {
return;
}
// Arrow up/down will navigate the references panel if that's opened
if (referenceBox.selectedIndex < 1) {
referenceBox.selectedIndex = 1;
referenceBox.selectedItem.focus();
}
else {
handleItemSelection(event);
}
}
else if (event.key == "Tab" && !event.shiftKey && referencePanel.state === "open") {
// Tab from the input will focus the selected item in the references list
event.preventDefault();
event.stopPropagation();
if (referenceBox.selectedIndex < 1) {
referenceBox.selectedIndex = 1;
}
referenceBox.selectedItem.focus();
}
};
@ -1803,6 +1831,9 @@ var Zotero_QuickFormat = new function () {
moveFocusForward(this);
}
this.remove();
// Removed item bubble may belong to opened documents section. Reference panel
// needs to be reset so that it appears among other items.
_clearEntryList();
_combineNeighboringInputs();
// If all bubbles are removed, add and focus an input
if (getAllBubbles().length == 0) {
@ -1880,6 +1911,12 @@ var Zotero_QuickFormat = new function () {
event.preventDefault();
}
// Shift-Enter will accept the existing dialog's state
else if (keyCode == "Enter" && event.shiftKey) {
event.preventDefault();
event.stopPropagation();
this.accept();
}
else {
isPaste = false;
}

View file

@ -55,7 +55,7 @@
<deck class="citation-dialog deck" selectedIndex="0" flex="1">
<hbox class="citation-dialog main" flex="1" align="start">
<hbox flex="1">
<vbox flex="1" align="center" style="display: flex;align-items: center;max-width: 38px;justify-content: center;">
<vbox class="citation-dialog icons start">
<toolbarbutton id="zotero-icon" type="menu" tabindex="0" disabled="true">
<menupopup>
<menuitem id="keep-sorted" label="&zotero.citation.keepSorted.label;"
@ -70,8 +70,9 @@
</toolbarbutton>
</vbox>
<html:div flex="1" spellcheck="false" class="citation-dialog editor" role="application"></html:div>
<vbox class="citation-dialog spinner">
<image class="zotero-spinner-16"/>
<vbox class="citation-dialog icons end">
<image class="icon zotero-spinner-16"/>
<toolbarbutton class="icon accept-button" onclick="Zotero_QuickFormat.accept()" data-l10n-id="quickformat-accept"></toolbarbutton>
</vbox>
</hbox>
</hbox>

View file

@ -437,3 +437,5 @@ toggle-preview =
quickformat-aria-bubble = Press Down Arrow to open citation properties.
quickformat-aria-input = Type your search term. Use Down Arrow and Up Arrow to navigate the search results.
quickformat-aria-item = Press { return-or-enter } to select this item. Press Tab to return to the search field.
quickformat-accept =
.tooltiptext = Save edits to this citation

View file

@ -185,7 +185,7 @@
font: -moz-field;
outline: none;
line-height: 2em;
width: 710px;
width: 700px; /* initial editor width - adjusted after dom load */
height: 28px;
font-size: 13px;
background: white;
@ -201,9 +201,22 @@
background: var(--color-accent);
}
.citation-dialog.spinner {
.citation-dialog.icons {
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
width: 36px;
}
.citation-dialog.entry {
max-width: 800px;
min-width: 800px;
}
.citation-dialog .accept-button {
list-style-image: url("chrome://zotero/skin/20/universal/arrow-right.svg");
fill: currentColor;
}
.citation-dialog.item {