split button for manage::export, popup::manage

This commit is contained in:
tophf 2022-01-19 16:13:53 +03:00
parent b692cf9608
commit 6a07ad0f56
10 changed files with 66 additions and 23 deletions

View File

@ -392,6 +392,9 @@
"message": "Export", "message": "Export",
"description": "Label for the button to export a style ('edit' page) or all styles ('manage' page)" "description": "Label for the button to export a style ('edit' page) or all styles ('manage' page)"
}, },
"exportCompatible": {
"message": "Export (compatible mode)"
},
"exportSavedSuccess": { "exportSavedSuccess": {
"message": "File saved with success" "message": "File saved with success"
}, },
@ -1269,6 +1272,10 @@
"message": "Click to see available hotkeys", "message": "Click to see available hotkeys",
"description": "Tooltip displayed when hovering the right edge of the extension popup" "description": "Tooltip displayed when hovering the right edge of the extension popup"
}, },
"popupManageSiteStyles": {
"message": "Manage site styles",
"description": "Item in the dropdown menu for the 'Manage' button in the popup that opens manager with styles applicable for current site."
},
"popupManageTooltip": { "popupManageTooltip": {
"message": "Shift-click or right-click opens manager with styles applicable for current site", "message": "Shift-click or right-click opens manager with styles applicable for current site",
"description": "Tooltip for the 'Manage' button in the popup." "description": "Tooltip for the 'Manage' button in the popup."

View File

@ -315,6 +315,7 @@ body.resizing-v > * {
margin-left: -1px !important; margin-left: -1px !important;
padding-left: .2em !important; padding-left: .2em !important;
padding-right: .2em !important; padding-right: .2em !important;
min-width: 0 !important;
} }
.split-btn-pedal::after { .split-btn-pedal::after {
content: '\25BC'; /* down triangle */ content: '\25BC'; /* down triangle */
@ -384,12 +385,6 @@ body.resizing-v > * {
padding: 4px; padding: 4px;
} }
/* Firefox cannot handle fractions in font-size */
.firefox button:not(.install) {
line-height: 13px;
padding: 3px 7px;
}
.firefox.moz-appearance-bug button:not(.install) { .firefox.moz-appearance-bug button:not(.install) {
padding: 2px 4px; padding: 2px 4px;
} }

View File

@ -85,20 +85,31 @@
} }
} }
/**
* @param {PointerEvent} [event] - absent when self-invoked to hide the menu
*/
function splitMenu(event) { function splitMenu(event) {
const prevMenu = $(SPLIT_BTN_MENU); const prevMenu = $(SPLIT_BTN_MENU);
const prevPedal = (prevMenu || {}).previousElementSibling; const prevPedal = (prevMenu || {}).previousElementSibling;
const pedal = event.target.closest('.split-btn-pedal'); const pedal = event && event.target.closest('.split-btn-pedal');
const entry = prevMenu && event.target.closest(SPLIT_BTN_MENU + '>*'); const entry = event && prevMenu && event.target.closest(SPLIT_BTN_MENU + '>*');
if (prevMenu) prevMenu.remove(); if (prevMenu) {
if (prevPedal) prevPedal.classList.remove('active'); prevMenu.remove();
prevPedal.classList.remove('active');
window.off('keydown', splitMenuEscape);
}
if (pedal && pedal !== prevPedal) { if (pedal && pedal !== prevPedal) {
const menu = $create(SPLIT_BTN_MENU, const menu = $create(SPLIT_BTN_MENU,
Array.from(pedal.attributes, ({name, value}) => Array.from(pedal.attributes, ({name, value}) =>
name.startsWith('menu-') && name.startsWith('menu-') &&
$create('a', {tabIndex: 0, __cmd: name.split('-').pop()}, value) $create('a', {tabIndex: 0, __cmd: name.split('-').pop()}, value)
)); ));
menu.on('focusout', e => e.target === menu && splitMenu(e)); window.on('keydown', splitMenuEscape);
menu.on('focusout', e => {
if (!menu.contains(e.relatedTarget)) {
setTimeout(splitMenu);
}
});
pedal.classList.toggle('active'); pedal.classList.toggle('active');
pedal.after(menu); pedal.after(menu);
moveFocus(menu, 0); moveFocus(menu, 0);
@ -112,6 +123,13 @@
} }
} }
function splitMenuEscape(e) {
if (getEventKeyName(e) === 'Escape') {
e.preventDefault();
splitMenu();
}
}
function suppressFocusRingOnClick({target}) { function suppressFocusRingOnClick({target}) {
const el = focusAccessibility.closest(target); const el = focusAccessibility.closest(target);
if (el) { if (el) {

View File

@ -328,7 +328,10 @@
</h2> </h2>
</summary> </summary>
<div id="backup-buttons"> <div id="backup-buttons">
<button id="file-all-styles" i18n-text="exportLabel"></button> <div class="split-btn">
<button id="file-all-styles" i18n-text="exportLabel"></button
><button class="split-btn-pedal" i18n-menu-compat="exportCompatible"></button>
</div>
<button id="unfile-all-styles" i18n-text="importLabel"></button> <button id="unfile-all-styles" i18n-text="importLabel"></button>
<button id="sync-styles" i18n-text="optionsCustomizeSync"></button> <button id="sync-styles" i18n-text="optionsCustomizeSync"></button>
</div> </div>

View File

@ -14,8 +14,11 @@
*/// dom.js */// dom.js
'use strict'; 'use strict';
$('#file-all-styles').onclick = exportToFile; Object.assign($('#file-all-styles'), {
$('#file-all-styles').oncontextmenu = exportToFile; onclick: exportToFile,
oncontextmenu: exportToFile,
onauxclick: exportToFile,
});
$('#unfile-all-styles').onclick = () => importFromFile({fileTypeFilter: '.json'}); $('#unfile-all-styles').onclick = () => importFromFile({fileTypeFilter: '.json'});
Object.assign(document.body, { Object.assign(document.body, {
@ -336,9 +339,12 @@ async function importFromString(jsonString) {
/** @param {MouseEvent} e */ /** @param {MouseEvent} e */
async function exportToFile(e) { async function exportToFile(e) {
if (e.type === 'auxclick' && !e.detail) {
return;
}
e.preventDefault(); e.preventDefault();
await require(['/js/storage-util']); await require(['/js/storage-util']);
const keepDupSections = e.type === 'contextmenu' || e.shiftKey; const keepDupSections = e.type === 'contextmenu' || e.shiftKey || e.detail === 'compat';
const data = [ const data = [
Object.assign({ Object.assign({
[prefs.STORAGE_KEY]: prefs.values, [prefs.STORAGE_KEY]: prefs.values,

View File

@ -262,7 +262,7 @@ a:hover {
flex-wrap: wrap; flex-wrap: wrap;
} }
#backup-buttons button { #backup-buttons > * {
margin: 0 .2rem .5rem 0; margin: 0 .2rem .5rem 0;
} }

View File

@ -219,8 +219,11 @@
<!-- Actions --> <!-- Actions -->
<div id="popup-options"> <div id="popup-options">
<button id="popup-manage-button" i18n-text="openManage" <div class="split-btn">
data-href="manage.html" i18n-title="popupManageTooltip"></button> <button id="popup-manage-button" i18n-text="openManage"
data-href="manage.html" i18n-title="popupManageTooltip"></button
><button class="split-btn-pedal" i18n-menu-site="popupManageSiteStyles"></button>
</div>
<button id="popup-options-button" i18n-text="openOptions"></button> <button id="popup-options-button" i18n-text="openOptions"></button>
<button id="popup-wiki-button" <button id="popup-wiki-button"
i18n-text="linkStylusWiki" i18n-text="linkStylusWiki"

View File

@ -110,7 +110,7 @@ const Events = {
async openManager(event) { async openManager(event) {
event.preventDefault(); event.preventDefault();
const isSearch = tabURL && (event.shiftKey || event.button === 2); const isSearch = tabURL && (event.shiftKey || event.button === 2 || event.detail === 'site');
await API.openManage(isSearch ? {search: tabURL, searchMode: 'url'} : {}); await API.openManage(isSearch ? {search: tabURL, searchMode: 'url'} : {});
window.close(); window.close();
}, },

View File

@ -668,20 +668,30 @@ body.blocked .actions > .main-controls {
flex-direction: row; flex-direction: row;
padding: var(--outer-padding) 1px; padding: var(--outer-padding) 1px;
} }
#popup-options .split-btn {
display: flex;
}
#popup-options button { #popup-options button {
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
padding: 2px 4px; padding: 2px 4px;
}
#popup-options > :nth-last-child(n + 2) {
margin-right: 4px; margin-right: 4px;
}
#popup-options > *,
#popup-manage-button {
/* several languages have labels of wildly different lengths so we try to maintain the proportion */ /* several languages have labels of wildly different lengths so we try to maintain the proportion */
flex: 1 1 auto; flex: 1 1 auto;
min-width: 2em; min-width: 2em;
} }
#popup-manage-button + .split-btn-pedal::after {
#popup-options button:last-child { content: '\25B2'; /* up triangle */
margin-right: 0; }
#popup-manage-button ~ .split-btn-menu {
bottom: 0;
transform: translateY(-20px); /* global button style: 13(font) * 1.2(line) + 4(pad) + 2(border) */
} }
/* confirm */ /* confirm */

View File

@ -103,6 +103,7 @@ async function initPopup(frames) {
Object.assign($('#popup-manage-button'), { Object.assign($('#popup-manage-button'), {
onclick: Events.openManager, onclick: Events.openManager,
oncontextmenu: Events.openManager, oncontextmenu: Events.openManager,
onauxclick: Events.openManager,
}); });
$('#popup-options-button').onclick = () => { $('#popup-options-button').onclick = () => {