Use messageBox in manage for confirm; partially revert c5741aff
This commit is contained in:
parent
54bb7cdd4e
commit
363f752934
|
@ -130,13 +130,16 @@ function importFromString(jsonString) {
|
|||
</small>
|
||||
</details>`)
|
||||
.join('');
|
||||
const box = messageBox({
|
||||
messageBox({
|
||||
title: 'Finished importing styles',
|
||||
contents: report || 'Nothing was changed.',
|
||||
buttons: [t('confirmOK'), numChanged && t('undo')],
|
||||
onclick: btnIndex => btnIndex == 1 && undo(),
|
||||
onshow: bindClick,
|
||||
}).then(({button, enter, esc}) => {
|
||||
if (button == 1) {
|
||||
undo();
|
||||
}
|
||||
});
|
||||
bindClick(box);
|
||||
resolve(numChanged);
|
||||
});
|
||||
}
|
||||
|
|
12
manage.html
12
manage.html
|
@ -5,7 +5,6 @@
|
|||
<title i18n-text="manageTitle"></title>
|
||||
<link rel="stylesheet" href="manage.css">
|
||||
<link rel="stylesheet" href="msgbox/msgbox.css">
|
||||
<link rel="stylesheet" href="msgbox/confirm.css">
|
||||
|
||||
<template data-id="style">
|
||||
<div class="entry">
|
||||
|
@ -117,17 +116,6 @@
|
|||
</div>
|
||||
<div id="installed"></div>
|
||||
|
||||
<div id="confirm">
|
||||
<div>
|
||||
<b>Style's Name</b>
|
||||
<span i18n-text="deleteStyleConfirm"></span>
|
||||
<div>
|
||||
<button i18n-text="confirmCancel" data-cmd="cancel"></button>
|
||||
<button i18n-text="confirmDelete" data-cmd="ok"></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" style="display: none">
|
||||
<symbol id="svg-icon-external-link" height="16" width="16" viewBox="0 0 8 8">
|
||||
<path d="M0 0v8h8v-2h-1v1h-6v-6h1v-1h-2zm4 0l1.5 1.5-2.5 2.5 1 1 2.5-2.5 1.5 1.5v-4h-4z"></path>
|
||||
|
|
19
manage.js
19
manage.js
|
@ -172,7 +172,7 @@ function createStyleElement(style) {
|
|||
$('.disable', entry).onclick = EntryOnClick.toggle;
|
||||
$('.check-update', entry).onclick = EntryOnClick.check;
|
||||
$('.update', entry).onclick = EntryOnClick.update;
|
||||
$('.delete', entry).onclick = event => confirmDelete(event, {float: true});
|
||||
$('.delete', entry).onclick = EntryOnClick.delete;
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
@ -224,6 +224,23 @@ class EntryOnClick {
|
|||
}));
|
||||
}
|
||||
|
||||
static delete(event) {
|
||||
const styleElement = getClickedStyleElement(event);
|
||||
const id = styleElement.styleId;
|
||||
const name = ((cachedStyles.byId.get(id) || {}).style || {}).name;
|
||||
animateElement(styleElement, {className: 'highlight'});
|
||||
messageBox({
|
||||
title: t('deleteStyleConfirm'),
|
||||
contents: name,
|
||||
className: 'danger center',
|
||||
buttons: [t('confirmDelete'), t('confirmCancel')],
|
||||
})
|
||||
.then(({button, enter, esc}) => {
|
||||
if (button == 0 || enter) {
|
||||
deleteStyle(id);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,80 +0,0 @@
|
|||
#confirm,
|
||||
#confirm > div > span {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#confirm {
|
||||
z-index: 2147483647;
|
||||
display: none;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
margin: 0 !important;
|
||||
box-sizing: border-box;
|
||||
animation: lights-off .5s cubic-bezier(.03, .67, .08, .94);
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
#confirm.lights-on {
|
||||
animation: lights-on .25s ease-in-out;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
#confirm.lights-on > div{
|
||||
display: none;
|
||||
}
|
||||
|
||||
#confirm[data-display=true] {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#confirm > div {
|
||||
width: 80vw;
|
||||
max-width: 16em;
|
||||
min-height: 8em;
|
||||
max-height: 80vh;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: solid 2px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
#confirm > div > span {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
#confirm > div > b {
|
||||
padding: 10px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
#confirm > div > div {
|
||||
padding: 10px;
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
@keyframes lights-off {
|
||||
from {
|
||||
background-color: transparent;
|
||||
}
|
||||
to {
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes lights-on {
|
||||
from {
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
to {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
function confirmDelete(event, {float = false} = {}) {
|
||||
const id = getClickedStyleId(event);
|
||||
const box = $('#confirm');
|
||||
box.dataset.id = id;
|
||||
box.dataset.display = true;
|
||||
box.style.cssText = '';
|
||||
$('b', box).textContent = ((cachedStyles.byId.get(id) || {}).style || {}).name;
|
||||
if (float) {
|
||||
const GAP = 50;
|
||||
const {width:W, height:H} = box.firstElementChild.getBoundingClientRect();
|
||||
const {left:L, top:T, right:R, bottom:B} = event.target.getBoundingClientRect();
|
||||
Object.assign(box.style, {
|
||||
paddingTop: (Math.min(T - H/2, innerHeight - H) - GAP) + 'px',
|
||||
paddingLeft: (Math.min(L - W/2, innerWidth - W) - GAP) + 'px',
|
||||
paddingRight: (innerWidth - Math.max(R + W/2, W) - GAP) + 'px',
|
||||
paddingBottom: (innerHeight - Math.max(B + H/2, H) - GAP) + 'px',
|
||||
});
|
||||
}
|
||||
let resolveMe;
|
||||
$('[data-cmd="ok"]', box).onclick = event => doDelete(true);
|
||||
$('[data-cmd="cancel"]', box).onclick = event => doDelete(false);
|
||||
window.addEventListener('keydown', onKey);
|
||||
|
||||
const stopScroll = {x: scrollX, y: scrollY};
|
||||
window.addEventListener('scroll', preventScroll);
|
||||
|
||||
return new Promise(resolve => resolveMe = resolve);
|
||||
|
||||
function doDelete(confirmed) {
|
||||
window.removeEventListener('keydown', onKey);
|
||||
window.removeEventListener('scroll', preventScroll);
|
||||
animateElement(box, {className: 'lights-on'}).then(() => {
|
||||
box.dataset.display = false;
|
||||
});
|
||||
Promise.resolve(confirmed && deleteStyle(id))
|
||||
.then(resolveMe);
|
||||
}
|
||||
|
||||
function onKey(event) {
|
||||
if (!event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey
|
||||
&& (event.keyCode == 13 || event.keyCode == 27)) {
|
||||
event.preventDefault();
|
||||
doDelete(event.keyCode == 13);
|
||||
}
|
||||
}
|
||||
|
||||
function preventScroll() {
|
||||
window.scrollTo(stopScroll.x, stopScroll.y);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,17 @@
|
|||
#message-box {
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
position: fixed;
|
||||
box-shadow: 5px 5px 50px rgba(0, 0, 0, 0.35);
|
||||
background-color: rgba(0, 0, 0, .25);
|
||||
animation: fadein .25s ease-in-out;
|
||||
z-index: 9999990;
|
||||
}
|
||||
|
||||
#message-box > div {
|
||||
top: 3rem;
|
||||
right: 3rem;
|
||||
min-width: 10rem;
|
||||
|
@ -7,41 +20,36 @@
|
|||
max-height: 90vh;
|
||||
position: fixed;
|
||||
display: flex;
|
||||
box-shadow: 5px 5px 50px rgba(0, 0, 0, 0.35);
|
||||
animation: fadein .25s ease-in-out;
|
||||
flex-direction: column;
|
||||
z-index: 9999990;
|
||||
}
|
||||
|
||||
#message-box > * {
|
||||
z-index: 9999991;
|
||||
background-color: white;
|
||||
box-shadow: 5px 5px 50px rgba(0, 0, 0, 0.35);
|
||||
z-index: 9999991;
|
||||
}
|
||||
|
||||
#message-box.fadeout {
|
||||
animation: fadeout .5s ease-in-out;
|
||||
}
|
||||
|
||||
#message-box::before {
|
||||
position: fixed;
|
||||
content: "";
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, .25);
|
||||
#message-box.center {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#message-box.big {
|
||||
max-width: none;
|
||||
left: 3rem;
|
||||
#message-box.center #message-box-contents {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#message-box.center > div {
|
||||
top: unset;
|
||||
right: unset;
|
||||
}
|
||||
|
||||
#message-box-title {
|
||||
font-weight: bold;
|
||||
background-color: rgb(145, 208, 198);
|
||||
padding: .75rem 50px .75rem .75rem;
|
||||
padding: .75rem 50px .75rem 52px;
|
||||
font-size: 1rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#message-box-title::before {
|
||||
|
@ -49,10 +57,23 @@
|
|||
width: 0;
|
||||
height: 0;
|
||||
padding: 0 32px 32px 0;
|
||||
background: url('/images/icon/32.png');
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-right: .5rem;
|
||||
background: url(/images/icon/32.png);
|
||||
position: absolute;
|
||||
left: 11px;
|
||||
top: 8px;
|
||||
}
|
||||
|
||||
#message-box.danger #message-box-title {
|
||||
background-color: firebrick;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#message-box.danger #message-box-title::before {
|
||||
background: url('/images/icon/32x.png');
|
||||
}
|
||||
|
||||
#message-box.danger #message-box-contents {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#message-box-close-icon {
|
||||
|
@ -68,7 +89,7 @@
|
|||
|
||||
#message-box-contents {
|
||||
overflow: auto;
|
||||
padding: .75rem;
|
||||
padding: 1.5rem .75rem;
|
||||
position: relative;
|
||||
flex-grow: 9;
|
||||
}
|
||||
|
@ -76,6 +97,7 @@
|
|||
#message-box-buttons {
|
||||
padding: .75rem;
|
||||
background-color: #f0f0f0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#message-box-buttons button:not(:last-child) {
|
||||
|
|
109
msgbox/msgbox.js
109
msgbox/msgbox.js
|
@ -1,51 +1,90 @@
|
|||
'use strict';
|
||||
|
||||
function messageBox({title, contents, buttons, onclick}) {
|
||||
// keep the same reference to be able to remove the listener later
|
||||
messageBox.close = messageBox.close || close;
|
||||
function messageBox({
|
||||
title, // [mandatory] the title string for innerHTML
|
||||
contents, // [mandatory] 1) DOM element 2) string for innerHTML
|
||||
className = '', // string, CSS class name of the message box element
|
||||
buttons = [], // array of strings used as labels
|
||||
onshow, // function(messageboxElement) invoked after the messagebox is shown
|
||||
blockScroll, // boolean, blocks the page scroll
|
||||
}) { // RETURNS: Promise resolved to {button[number], enter[boolean], esc[boolean]}
|
||||
initOwnListeners();
|
||||
bindGlobalListeners();
|
||||
createElement();
|
||||
document.body.appendChild(messageBox.element);
|
||||
if (onshow) {
|
||||
onshow(messageBox.element);
|
||||
}
|
||||
return new Promise(_resolve => {
|
||||
messageBox.resolve = _resolve;
|
||||
});
|
||||
|
||||
function initOwnListeners() {
|
||||
messageBox.listeners = messageBox.listeners || {
|
||||
closeIcon() {
|
||||
resolveWith({button: -1});
|
||||
},
|
||||
button() {
|
||||
resolveWith({button: this.buttonIndex});
|
||||
},
|
||||
key(event) {
|
||||
if (!event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey
|
||||
&& (event.keyCode == 13 || event.keyCode == 27)) {
|
||||
event.preventDefault();
|
||||
resolveWith(event.keyCode == 13 ? {enter: true} : {esc: true});
|
||||
}
|
||||
},
|
||||
scroll() {
|
||||
scrollTo(blockScroll.x, blockScroll.y);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function resolveWith(value) {
|
||||
setTimeout(messageBox.resolve, 0, value);
|
||||
animateElement(messageBox.element, {className: 'fadeout', remove: true})
|
||||
.then(unbindAndRemoveSelf);
|
||||
}
|
||||
|
||||
function createElement() {
|
||||
if (messageBox.element) {
|
||||
messageBox.element.remove();
|
||||
unbindAndRemoveSelf();
|
||||
}
|
||||
const id = 'message-box';
|
||||
const putAs = typeof contents == 'string' ? 'innerHTML' : 'appendChild';
|
||||
messageBox.element = $element({id, appendChild: [
|
||||
messageBox.element = $element({id, className, appendChild: [
|
||||
$element({appendChild: [
|
||||
$element({id: `${id}-title`, innerHTML: title}),
|
||||
$element({id: `${id}-close-icon`, onclick: messageBox.close}),
|
||||
$element({id: `${id}-close-icon`, onclick: messageBox.listeners.closeIcon}),
|
||||
$element({id: `${id}-contents`, [putAs]: contents}),
|
||||
$element({id: `${id}-buttons`,
|
||||
onclick: relayButtonClick,
|
||||
appendChild: (buttons || []).map(textContent =>
|
||||
textContent && $element({tag: 'button', textContent}))
|
||||
$element({id: `${id}-buttons`, appendChild:
|
||||
buttons.map((textContent, buttonIndex) => textContent &&
|
||||
$element({
|
||||
tag: 'button',
|
||||
buttonIndex,
|
||||
textContent,
|
||||
onclick: messageBox.listeners.button,
|
||||
})
|
||||
)
|
||||
}),
|
||||
]}),
|
||||
]});
|
||||
show();
|
||||
return messageBox.element;
|
||||
|
||||
function show() {
|
||||
document.body.appendChild(messageBox.element);
|
||||
document.addEventListener('keydown', messageBox.close);
|
||||
}
|
||||
|
||||
function close(event) {
|
||||
if ((!event
|
||||
|| event.type == 'click'
|
||||
|| event.keyCode == 27 && !event.altKey && !event.ctrlKey && !event.shiftKey && !event.metaKey)
|
||||
&& messageBox.element) {
|
||||
animateElement(messageBox.element, {className: 'fadeout', remove: true});
|
||||
document.removeEventListener('keydown', messageBox.close);
|
||||
$(`#${id}-buttons`).onclick = null;
|
||||
function bindGlobalListeners() {
|
||||
blockScroll = blockScroll && {x: scrollX, y: scrollY};
|
||||
if (blockScroll) {
|
||||
window.addEventListener('scroll', messageBox.listeners.scroll);
|
||||
}
|
||||
window.addEventListener('keydown', messageBox.listeners.key);
|
||||
}
|
||||
|
||||
function unbindAndRemoveSelf() {
|
||||
document.removeEventListener('keydown', messageBox.listeners.key);
|
||||
window.removeEventListener('scroll', messageBox.listeners.scroll);
|
||||
messageBox.element.remove();
|
||||
messageBox.element = null;
|
||||
}
|
||||
}
|
||||
|
||||
function relayButtonClick(event) {
|
||||
const button = event.target.closest('button');
|
||||
if (button) {
|
||||
close();
|
||||
if (onclick) {
|
||||
onclick([...this.children].indexOf(button));
|
||||
}
|
||||
}
|
||||
messageBox.resolve = null;
|
||||
}
|
||||
|
||||
function $element(opt) {
|
||||
|
|
72
popup.css
72
popup.css
|
@ -212,3 +212,75 @@ body>div:not(#installed) {
|
|||
white-space: nowrap;
|
||||
padding-right: 5px;
|
||||
}
|
||||
/* confirm */
|
||||
#confirm,
|
||||
#confirm>div>span {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
#confirm {
|
||||
z-index: 2147483647;
|
||||
display: none; /* flex */
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0!important;
|
||||
box-sizing: border-box;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
animation: lights-off .5s cubic-bezier(.03, .67, .08, .94);
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
#confirm.lights-on {
|
||||
animation: lights-on .25s ease-in-out;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
#confirm.lights-on > div{
|
||||
display: none;
|
||||
}
|
||||
#confirm[data-display=true] {
|
||||
display: flex;
|
||||
}
|
||||
#confirm>div {
|
||||
width: 80%;
|
||||
height: 100px;
|
||||
max-height: 80%;
|
||||
min-height: 8em;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: solid 2px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
#confirm>div>span {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
padding: 0 10px;
|
||||
}
|
||||
#confirm>div>b {
|
||||
padding: 10px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
#confirm>div>div {
|
||||
padding: 10px;
|
||||
direction: rtl;
|
||||
}
|
||||
@keyframes lights-off {
|
||||
from {
|
||||
background-color: transparent;
|
||||
}
|
||||
to {
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
}
|
||||
@keyframes lights-on {
|
||||
from {
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
to {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
|
||||
<link rel="stylesheet" href="popup.css">
|
||||
<link rel="stylesheet" href="msgbox/confirm.css">
|
||||
|
||||
<template data-id="style">
|
||||
<div class="entry">
|
||||
|
@ -44,7 +43,6 @@
|
|||
<script src="messaging.js"></script>
|
||||
<script src="apply.js"></script>
|
||||
<script src="dom.js"></script>
|
||||
<script src="msgbox/confirm.js"></script>
|
||||
|
||||
<script src="popup.js"></script>
|
||||
</head>
|
||||
|
|
23
popup.js
23
popup.js
|
@ -188,13 +188,34 @@ class EntryOnClick {
|
|||
}
|
||||
|
||||
static delete(event) {
|
||||
confirmDelete(event).then(() => {
|
||||
const id = getClickedStyleId(event);
|
||||
const box = $('#confirm');
|
||||
box.dataset.display = true;
|
||||
box.style.cssText = '';
|
||||
$('b', box).textContent = ((cachedStyles.byId.get(id) || {}).style || {}).name;
|
||||
$('[data-cmd="ok"]', box).onclick = () => confirm(true);
|
||||
$('[data-cmd="cancel"]', box).onclick = () => confirm(false);
|
||||
window.onkeydown = event => {
|
||||
if (!event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey
|
||||
&& (event.keyCode == 13 || event.keyCode == 27)) {
|
||||
event.preventDefault();
|
||||
confirm(event.keyCode == 13);
|
||||
}
|
||||
};
|
||||
function confirm(ok) {
|
||||
window.onkeydown = null;
|
||||
animateElement(box, {className: 'lights-on'})
|
||||
.then(() => box.dataset.display = false);
|
||||
if (ok) {
|
||||
deleteStyle(id).then(() => {
|
||||
// update view with 'No styles installed for this site' message
|
||||
if (!installed.children.length) {
|
||||
showStyles([]);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user