toggle narrow width mode tooltips via html+css; code cosmetics

This commit is contained in:
tophf 2017-12-19 02:48:47 +03:00
parent 1348eeb4e3
commit e50ff316ba
3 changed files with 41 additions and 73 deletions

View File

@ -179,17 +179,26 @@
class="CodeMirror-search-field" rows="1" required
spellcheck="false"></textarea>
</div>
<button data-action="replace" i18n-text="replace" disabled>
<button data-action="replace" i18n-text="replace" disabled></button>
<button data-action="replaceAll" i18n-text="replaceAll" disabled></button>
<button data-action="undo" i18n-text="undo" disabled></button>
<!--
Using a separate set of buttons because
1. FF can display tooltips only when specified on the <button>, ignores the nested <title> in <svg>
2. the icon doesn't fill the entire button area so tooltips aren't shown when the edges are hovered
-->
<button class="hidden" data-action="replace" i18n-title="replace" disabled>
<svg class="svg-icon" viewBox="0 0 20 20">
<polygon points="15.83 4.75 8.76 11.82 5.2 8.26 3.51 9.95 8.76 15.19 17.52 6.43 15.83 4.75"/>
</svg>
</button>
<button data-action="replaceAll" i18n-text="replaceAll" disabled>
<button class="hidden" data-action="replaceAll" i18n-title="replaceAll" disabled>
<svg class="svg-icon" viewBox="0 0 20 20">
<polygon points="15.83 4.75 8.76 11.82 5.2 8.26 3.51 9.95 8.76 15.19 17.52 6.43 15.83 4.75"/>
<polygon points="15.8,1.8 8.8,8.8 5.2,5.3 3.5,6.9 8.8,12.2 17.5,3.4 "/>
<polygon points="15.8,7.8 8.8,14.8 5.2,11.3 3.5,12.9 8.8,18.2 17.5,9.4 "/>
</svg>
</button>
<button data-action="undo" i18n-text="undo" disabled>
<button class="hidden" data-action="undo" i18n-title="undo" disabled>
<svg class="svg-icon" viewBox="0 0 20 20">
<path d="M11.3,5.5H8.7V1.4L1.9,6.5l6.8,5.1V7.5h2.6c1.8,0,3.2,1.4,3.2,3.2s-1.4,3.2-3.2,3.2H7.8v2h3.5c2.9,0,5.2-2.3,5.2-5.2S14.2,5.5,11.3,5.5z"/>
</svg>

View File

@ -209,10 +209,15 @@
right: 0;
max-width: none;
}
#search-replace-dialog[data-type="replace"] button {
#search-replace-dialog[data-type="replace"] button:not(.hidden) {
display: none !important;
}
#search-replace-dialog[data-type="replace"] button.hidden {
display: block !important;
font-size: 0;
width: 24px;
text-align: center;
cursor: pointer;
}
#search-replace-dialog[data-type="replace"] button svg {
display: inline;
@ -222,11 +227,4 @@
max-width: calc(50vw - 120px);
width: auto;
}
#search-replace-dialog[data-type="replace"] button[data-action="replaceAll"] svg {
top: -3px;
position: relative;
/* unprefixed since Chrome 53 */
-webkit-filter: drop-shadow(0 5px 0 currentColor);
filter: drop-shadow(0 5px 0 currentColor);
}
}

View File

@ -22,16 +22,6 @@ onDOMready().then(() => {
const RX_MAYBE_REGEXP = /^\s*\/(.+?)\/([simguy]*)\s*$/;
const NARROW_WIDTH = [...document.styleSheets]
.filter(({href}) => href && href.endsWith('global-search.css'))
.map(sheet =>
[...sheet.cssRules]
.filter(r => r.media && r.conditionText.includes('max-width'))
.map(r => r.conditionText.match(/\d+/) | 0)
.sort((a, b) => a - b)
.pop())
.pop() || 800;
const state = {
// used for case-sensitive matching directly
find: '',
@ -188,10 +178,12 @@ onDOMready().then(() => {
state.replaceValue = state.replace.replace(/(\\r)?\\n/g, '\n').replace(/\\t/g, '\t');
state.replaceHasRefs = /\$[$&`'\d]/.test(state.replaceValue);
}
const cmFocused = document.activeElement && document.activeElement.closest('.CodeMirror');
state.activeAppliesTo = $(`.${APPLIES_VALUE_CLASS}:focus, .${APPLIES_VALUE_CLASS}.${TARGET_CLASS}`);
state.cmStart = CodeMirror.closestVisible(
document.activeElement && document.activeElement.closest('.CodeMirror') && document.activeElement ||
state.activeAppliesTo || state.cm);
cmFocused && document.activeElement ||
state.activeAppliesTo ||
state.cm);
}
@ -208,21 +200,19 @@ onDOMready().then(() => {
return;
}
initState();
if (!state.find) {
clearMarker();
makeTargetVisible(null);
setupOverlay(editors.slice());
showTally(0, 0);
return;
}
const {cmStart} = state;
const {index, found, foundInCode} = doSearchInEditors({cmStart, canAdvance, inApplies}) || {};
const {index, found, foundInCode} = state.find && doSearchInEditors({cmStart, canAdvance, inApplies}) || {};
if (!foundInCode) clearMarker();
if (!found) makeTargetVisible(null);
const radiateFrom = foundInCode ? index : editors.indexOf(cmStart);
setupOverlay(radiateArray(editors, radiateFrom));
enableReplaceButtons(foundInCode);
debounce(showTally, 0, foundInCode && !state.numFound ? 1 : undefined);
if (state.find) {
const firstSuccessfulSearch = foundInCode && !state.numFound;
debounce(showTally, 0, firstSuccessfulSearch ? 1 : undefined);
} else {
showTally(0, 0);
}
}
@ -326,7 +316,7 @@ onDOMready().then(() => {
if (cursor) {
state.undoHistory.push([cm]);
state.undo.disabled = false;
enableUndoButton(true);
}
}
@ -338,7 +328,7 @@ onDOMready().then(() => {
if (found.length) {
state.lastFind = null;
state.undoHistory.push(found);
state.undo.disabled = false;
enableUndoButton(true);
doSearch({canAdvance: false});
}
}
@ -388,8 +378,8 @@ onDOMready().then(() => {
undoneSome = true;
}
}
state.undo.disabled = !state.undoHistory.length;
(state.undo.disabled ? state.input : state.undo).focus();
enableUndoButton(state.undoHistory.length);
(state.undoHistory.length ? state.undo : state.input).focus();
if (undoneSome) {
state.lastFind = null;
restoreWindowScrollPos();
@ -463,7 +453,6 @@ onDOMready().then(() => {
cmState.annotateTimer = 0;
}
if (hasMatches) {
if (cmState.annotateTimer) clearTimeout(cmState.annotateTimer);
cmState.annotateTimer = setTimeout(annotateScrollbar, ANNOTATE_SCROLLBAR_DELAY,
cm, query, state.icase);
}
@ -481,11 +470,10 @@ onDOMready().then(() => {
const match = this.query.exec(stream.string);
if (match && match.index === stream.pos) {
this.numFound++;
//state.numFound++;
const t = performance.now();
if (t - this.tallyShownTime > 10) {
debounce(showTally);
this.tallyShownTime = t;
debounce(showTally);
}
stream.pos += match[0].length || 1;
return MATCH_TOKEN_NAME;
@ -573,6 +561,7 @@ onDOMready().then(() => {
#search-replace-dialog [data-action="case"] {
color: ${colors.icon.fill};
}
#search-replace-dialog[data-type="replace"] button:hover svg,
#search-replace-dialog svg:hover {
fill: inherit;
}
@ -587,20 +576,11 @@ onDOMready().then(() => {
document.body.appendChild(dialog);
dispatchEvent(new Event('showHotkeyInTooltip'));
measureInput(state.input);
adjustTextareaSize(state.input);
if (type === 'replace') {
measureInput(state.input2);
adjustTextareaSize(state.input2);
enableReplaceButtons(state.find !== '');
addEventListener('resize', toggleReplaceButtonTooltips, {passive: true});
toggleReplaceButtonTooltips(true);
state.undo = $('[data-action="undo"]');
state.undo.disabled = !state.undoHistory.length;
} else {
removeEventListener('resize', toggleReplaceButtonTooltips, {passive: true});
enableUndoButton(state.undoHistory.length);
}
return dialog;
@ -620,20 +600,11 @@ onDOMready().then(() => {
}
function measureInput(input) {
const style = getComputedStyle(input);
input._padding = parseFloat(style.paddingTop) + parseFloat(style.paddingBottom);
input._maxWidth = parseFloat(style.maxWidth);
input._rowHeight = input.clientHeight - input._padding;
}
function destroyDialog({restoreFocus = false} = {}) {
state.input = null;
$.remove(DIALOG_SELECTOR);
debounce.unregister(doSearch);
makeTargetVisible(null);
removeEventListener('resize', toggleReplaceButtonTooltips, {passive: true});
if (restoreFocus) setTimeout(focusNoScroll, 0, state.originalFocus);
}
@ -675,20 +646,10 @@ onDOMready().then(() => {
}
}
function toggleReplaceButtonTooltips(debounced) {
if (debounced !== true) {
debounce(toggleReplaceButtonTooltips, 0, true);
} else {
const addTitle = window.innerWidth <= NARROW_WIDTH;
for (const el of state.dialog.getElementsByTagName('button')) {
if (addTitle && !el.title) {
el.title = el.textContent;
} else if (!addTitle && el.title) {
el.title = '';
} else {
break;
}
function enableUndoButton(enabled) {
if (state.dialog && state.dialog.dataset.type === 'replace') {
for (const el of $$('[data-action="undo"]', state.dialog)) {
el.disabled = !enabled;
}
}
}