toggle narrow width mode tooltips via html+css; code cosmetics
This commit is contained in:
parent
1348eeb4e3
commit
e50ff316ba
17
edit.html
17
edit.html
|
@ -179,17 +179,26 @@
|
||||||
class="CodeMirror-search-field" rows="1" required
|
class="CodeMirror-search-field" rows="1" required
|
||||||
spellcheck="false"></textarea>
|
spellcheck="false"></textarea>
|
||||||
</div>
|
</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">
|
<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.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>
|
</svg>
|
||||||
</button>
|
</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">
|
<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>
|
</svg>
|
||||||
</button>
|
</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">
|
<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"/>
|
<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>
|
</svg>
|
||||||
|
|
|
@ -209,10 +209,15 @@
|
||||||
right: 0;
|
right: 0;
|
||||||
max-width: none;
|
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;
|
font-size: 0;
|
||||||
width: 24px;
|
width: 24px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
#search-replace-dialog[data-type="replace"] button svg {
|
#search-replace-dialog[data-type="replace"] button svg {
|
||||||
display: inline;
|
display: inline;
|
||||||
|
@ -222,11 +227,4 @@
|
||||||
max-width: calc(50vw - 120px);
|
max-width: calc(50vw - 120px);
|
||||||
width: auto;
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,16 +22,6 @@ onDOMready().then(() => {
|
||||||
|
|
||||||
const RX_MAYBE_REGEXP = /^\s*\/(.+?)\/([simguy]*)\s*$/;
|
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 = {
|
const state = {
|
||||||
// used for case-sensitive matching directly
|
// used for case-sensitive matching directly
|
||||||
find: '',
|
find: '',
|
||||||
|
@ -188,10 +178,12 @@ onDOMready().then(() => {
|
||||||
state.replaceValue = state.replace.replace(/(\\r)?\\n/g, '\n').replace(/\\t/g, '\t');
|
state.replaceValue = state.replace.replace(/(\\r)?\\n/g, '\n').replace(/\\t/g, '\t');
|
||||||
state.replaceHasRefs = /\$[$&`'\d]/.test(state.replaceValue);
|
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.activeAppliesTo = $(`.${APPLIES_VALUE_CLASS}:focus, .${APPLIES_VALUE_CLASS}.${TARGET_CLASS}`);
|
||||||
state.cmStart = CodeMirror.closestVisible(
|
state.cmStart = CodeMirror.closestVisible(
|
||||||
document.activeElement && document.activeElement.closest('.CodeMirror') && document.activeElement ||
|
cmFocused && document.activeElement ||
|
||||||
state.activeAppliesTo || state.cm);
|
state.activeAppliesTo ||
|
||||||
|
state.cm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -208,21 +200,19 @@ onDOMready().then(() => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
initState();
|
initState();
|
||||||
if (!state.find) {
|
|
||||||
clearMarker();
|
|
||||||
makeTargetVisible(null);
|
|
||||||
setupOverlay(editors.slice());
|
|
||||||
showTally(0, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const {cmStart} = state;
|
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 (!foundInCode) clearMarker();
|
||||||
if (!found) makeTargetVisible(null);
|
if (!found) makeTargetVisible(null);
|
||||||
const radiateFrom = foundInCode ? index : editors.indexOf(cmStart);
|
const radiateFrom = foundInCode ? index : editors.indexOf(cmStart);
|
||||||
setupOverlay(radiateArray(editors, radiateFrom));
|
setupOverlay(radiateArray(editors, radiateFrom));
|
||||||
enableReplaceButtons(foundInCode);
|
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) {
|
if (cursor) {
|
||||||
state.undoHistory.push([cm]);
|
state.undoHistory.push([cm]);
|
||||||
state.undo.disabled = false;
|
enableUndoButton(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,7 +328,7 @@ onDOMready().then(() => {
|
||||||
if (found.length) {
|
if (found.length) {
|
||||||
state.lastFind = null;
|
state.lastFind = null;
|
||||||
state.undoHistory.push(found);
|
state.undoHistory.push(found);
|
||||||
state.undo.disabled = false;
|
enableUndoButton(true);
|
||||||
doSearch({canAdvance: false});
|
doSearch({canAdvance: false});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -388,8 +378,8 @@ onDOMready().then(() => {
|
||||||
undoneSome = true;
|
undoneSome = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state.undo.disabled = !state.undoHistory.length;
|
enableUndoButton(state.undoHistory.length);
|
||||||
(state.undo.disabled ? state.input : state.undo).focus();
|
(state.undoHistory.length ? state.undo : state.input).focus();
|
||||||
if (undoneSome) {
|
if (undoneSome) {
|
||||||
state.lastFind = null;
|
state.lastFind = null;
|
||||||
restoreWindowScrollPos();
|
restoreWindowScrollPos();
|
||||||
|
@ -463,7 +453,6 @@ onDOMready().then(() => {
|
||||||
cmState.annotateTimer = 0;
|
cmState.annotateTimer = 0;
|
||||||
}
|
}
|
||||||
if (hasMatches) {
|
if (hasMatches) {
|
||||||
if (cmState.annotateTimer) clearTimeout(cmState.annotateTimer);
|
|
||||||
cmState.annotateTimer = setTimeout(annotateScrollbar, ANNOTATE_SCROLLBAR_DELAY,
|
cmState.annotateTimer = setTimeout(annotateScrollbar, ANNOTATE_SCROLLBAR_DELAY,
|
||||||
cm, query, state.icase);
|
cm, query, state.icase);
|
||||||
}
|
}
|
||||||
|
@ -481,11 +470,10 @@ onDOMready().then(() => {
|
||||||
const match = this.query.exec(stream.string);
|
const match = this.query.exec(stream.string);
|
||||||
if (match && match.index === stream.pos) {
|
if (match && match.index === stream.pos) {
|
||||||
this.numFound++;
|
this.numFound++;
|
||||||
//state.numFound++;
|
|
||||||
const t = performance.now();
|
const t = performance.now();
|
||||||
if (t - this.tallyShownTime > 10) {
|
if (t - this.tallyShownTime > 10) {
|
||||||
debounce(showTally);
|
|
||||||
this.tallyShownTime = t;
|
this.tallyShownTime = t;
|
||||||
|
debounce(showTally);
|
||||||
}
|
}
|
||||||
stream.pos += match[0].length || 1;
|
stream.pos += match[0].length || 1;
|
||||||
return MATCH_TOKEN_NAME;
|
return MATCH_TOKEN_NAME;
|
||||||
|
@ -573,6 +561,7 @@ onDOMready().then(() => {
|
||||||
#search-replace-dialog [data-action="case"] {
|
#search-replace-dialog [data-action="case"] {
|
||||||
color: ${colors.icon.fill};
|
color: ${colors.icon.fill};
|
||||||
}
|
}
|
||||||
|
#search-replace-dialog[data-type="replace"] button:hover svg,
|
||||||
#search-replace-dialog svg:hover {
|
#search-replace-dialog svg:hover {
|
||||||
fill: inherit;
|
fill: inherit;
|
||||||
}
|
}
|
||||||
|
@ -587,20 +576,11 @@ onDOMready().then(() => {
|
||||||
document.body.appendChild(dialog);
|
document.body.appendChild(dialog);
|
||||||
dispatchEvent(new Event('showHotkeyInTooltip'));
|
dispatchEvent(new Event('showHotkeyInTooltip'));
|
||||||
|
|
||||||
measureInput(state.input);
|
|
||||||
adjustTextareaSize(state.input);
|
adjustTextareaSize(state.input);
|
||||||
if (type === 'replace') {
|
if (type === 'replace') {
|
||||||
measureInput(state.input2);
|
|
||||||
adjustTextareaSize(state.input2);
|
adjustTextareaSize(state.input2);
|
||||||
enableReplaceButtons(state.find !== '');
|
enableReplaceButtons(state.find !== '');
|
||||||
|
enableUndoButton(state.undoHistory.length);
|
||||||
addEventListener('resize', toggleReplaceButtonTooltips, {passive: true});
|
|
||||||
toggleReplaceButtonTooltips(true);
|
|
||||||
|
|
||||||
state.undo = $('[data-action="undo"]');
|
|
||||||
state.undo.disabled = !state.undoHistory.length;
|
|
||||||
} else {
|
|
||||||
removeEventListener('resize', toggleReplaceButtonTooltips, {passive: true});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return dialog;
|
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} = {}) {
|
function destroyDialog({restoreFocus = false} = {}) {
|
||||||
state.input = null;
|
state.input = null;
|
||||||
$.remove(DIALOG_SELECTOR);
|
$.remove(DIALOG_SELECTOR);
|
||||||
debounce.unregister(doSearch);
|
debounce.unregister(doSearch);
|
||||||
makeTargetVisible(null);
|
makeTargetVisible(null);
|
||||||
removeEventListener('resize', toggleReplaceButtonTooltips, {passive: true});
|
|
||||||
if (restoreFocus) setTimeout(focusNoScroll, 0, state.originalFocus);
|
if (restoreFocus) setTimeout(focusNoScroll, 0, state.originalFocus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -675,20 +646,10 @@ onDOMready().then(() => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function enableUndoButton(enabled) {
|
||||||
function toggleReplaceButtonTooltips(debounced) {
|
if (state.dialog && state.dialog.dataset.type === 'replace') {
|
||||||
if (debounced !== true) {
|
for (const el of $$('[data-action="undo"]', state.dialog)) {
|
||||||
debounce(toggleReplaceButtonTooltips, 0, true);
|
el.disabled = !enabled;
|
||||||
} 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user