WIP: kill getSection

This commit is contained in:
eight 2018-10-10 12:08:35 +08:00
parent ba6159e067
commit 15a1f552f6
6 changed files with 107 additions and 106 deletions

View File

@ -1,4 +1,4 @@
/* global CodeMirror prefs loadScript editor editors */ /* global CodeMirror prefs loadScript editor */
'use strict'; 'use strict';

View File

@ -27,13 +27,8 @@ onDOMscriptReady('/codemirror.js').then(() => {
'find', 'findNext', 'findPrev', 'replace', 'replaceAll', 'find', 'findNext', 'findPrev', 'replace', 'replaceAll',
'colorpicker', 'colorpicker',
]); ]);
Object.assign(CodeMirror, {
getOption,
setOption,
closestVisible,
});
Object.assign(CodeMirror.prototype, { Object.assign(CodeMirror.prototype, {
getSection, // getSection,
rerouteHotkeys, rerouteHotkeys,
}); });
Object.assign(CodeMirror.commands, COMMANDS); Object.assign(CodeMirror.commands, COMMANDS);
@ -256,6 +251,7 @@ onDOMscriptReady('/codemirror.js').then(() => {
case 'autocompleteOnTyping': case 'autocompleteOnTyping':
if (editor) { if (editor) {
// FIXME: this won't work with removed sections
editor.getEditors().forEach(cm => setupAutocomplete(cm, value)); editor.getEditors().forEach(cm => setupAutocomplete(cm, value));
} }
return; return;
@ -304,7 +300,7 @@ onDOMscriptReady('/codemirror.js').then(() => {
} }
const rerouteCommand = name => { const rerouteCommand = name => {
if (REROUTED.has(name)) { if (REROUTED.has(name)) {
CodeMirror.commands[name](closestVisible(event.target)); CodeMirror.commands[name](editor.closestVisible(event.target));
return true; return true;
} }
}; };
@ -317,87 +313,6 @@ onDOMscriptReady('/codemirror.js').then(() => {
//////////////////////////////////////////////// ////////////////////////////////////////////////
// priority:
// 1. associated CM for applies-to element
// 2. last active if visible
// 3. first visible
function closestVisible(nearbyElement) {
const cm =
nearbyElement instanceof CodeMirror ? nearbyElement :
nearbyElement instanceof Node &&
(nearbyElement.closest('#sections > .section') || {}).CodeMirror ||
editor.getLastActivatedEditor();
if (nearbyElement instanceof Node && cm) {
const {left, top} = nearbyElement.getBoundingClientRect();
const bounds = cm.display.wrapper.getBoundingClientRect();
if (top >= 0 && top >= bounds.top &&
left >= 0 && left >= bounds.left) {
return cm;
}
}
// closest editor should have at least 2 lines visible
const lineHeight = editor.getEditors()[0].defaultTextHeight();
const scrollY = window.scrollY;
const windowBottom = scrollY + window.innerHeight - 2 * lineHeight;
const allSectionsContainerTop = scrollY + $('#sections').getBoundingClientRect().top;
const distances = [];
const alreadyInView = cm && offscreenDistance(null, cm) === 0;
return alreadyInView ? cm : findClosest();
function offscreenDistance(index, cm) {
if (index >= 0 && distances[index] !== undefined) {
return distances[index];
}
const section = cm.display.wrapper.closest('.section');
if (!section) {
return 1e9;
}
const top = allSectionsContainerTop + section.offsetTop;
if (top < scrollY + lineHeight) {
return Math.max(0, scrollY - top - lineHeight);
}
if (top < windowBottom) {
return 0;
}
const distance = top - windowBottom + section.offsetHeight;
if (index >= 0) {
distances[index] = distance;
}
return distance;
}
function findClosest() {
const editors = editor.getEditors();
const last = editors.length - 1;
let a = 0;
let b = last;
let c;
let distance;
while (a < b - 1) {
c = (a + b) / 2 | 0;
distance = offscreenDistance(c);
if (!distance || !c) {
break;
}
const distancePrev = offscreenDistance(c - 1);
const distanceNext = c < last ? offscreenDistance(c + 1) : 1e20;
if (distancePrev <= distance && distance <= distanceNext) {
b = c;
} else {
a = c;
}
}
while (b && offscreenDistance(b - 1) <= offscreenDistance(b)) {
b--;
}
const cm = editors[b];
if (distances[b] > 0) {
editor.scrollToEditor(cm);
}
return cm;
}
}
//////////////////////////////////////////////// ////////////////////////////////////////////////
function setupAutocomplete(cm, enable = true) { function setupAutocomplete(cm, enable = true) {

View File

@ -4,9 +4,7 @@ global createSourceEditor
global closeCurrentTab regExpTester messageBox global closeCurrentTab regExpTester messageBox
global setupCodeMirror global setupCodeMirror
global beautify global beautify
global initWithSectionStyle addSections removeSection getSectionsHashes
global sectionsToMozFormat global sectionsToMozFormat
global exclusions
global moveFocus editorWorker msg createSectionEditor global moveFocus editorWorker msg createSectionEditor
*/ */
'use strict'; 'use strict';

View File

@ -1,4 +1,4 @@
/* global CodeMirror editors makeSectionVisible */ /* global CodeMirror */
/* global focusAccessibility */ /* global focusAccessibility */
/* global colorMimicry editor */ /* global colorMimicry editor */
'use strict'; 'use strict';
@ -207,7 +207,7 @@ onDOMready().then(() => {
} }
const cmFocused = document.activeElement && document.activeElement.closest('.CodeMirror'); 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 = editor.closestVisible(
cmFocused && document.activeElement || cmFocused && document.activeElement ||
state.activeAppliesTo || state.activeAppliesTo ||
state.cm); state.cm);
@ -291,7 +291,7 @@ onDOMready().then(() => {
function doSearchInApplies(cm, canAdvance) { function doSearchInApplies(cm, canAdvance) {
if (!state.searchInApplies) return; if (!state.searchInApplies) return;
const inputs = [...cm.getSection().getElementsByClassName(APPLIES_VALUE_CLASS)]; const inputs = editor.getSearchableInputs(cm);
if (state.reverse) inputs.reverse(); if (state.reverse) inputs.reverse();
inputs.splice(0, inputs.indexOf(state.activeAppliesTo)); inputs.splice(0, inputs.indexOf(state.activeAppliesTo));
for (const input of inputs) { for (const input of inputs) {

View File

@ -61,10 +61,11 @@ function createResizeGrip(cm) {
const allBounds = $('#sections').getBoundingClientRect(); const allBounds = $('#sections').getBoundingClientRect();
const pageExtrasHeight = allBounds.top + window.scrollY + const pageExtrasHeight = allBounds.top + window.scrollY +
parseFloat(getComputedStyle($('#sections')).paddingBottom); parseFloat(getComputedStyle($('#sections')).paddingBottom);
const sectionExtrasHeight = cm.getSection().clientHeight - wrapper.offsetHeight; const sectionEl = wrapper.parentNode;
const sectionExtrasHeight = sectionEl.clientHeight - wrapper.offsetHeight;
cm.state.toggleHeightSaved = wrapper.clientHeight; cm.state.toggleHeightSaved = wrapper.clientHeight;
cm.setSize(null, window.innerHeight - sectionExtrasHeight - pageExtrasHeight); cm.setSize(null, window.innerHeight - sectionExtrasHeight - pageExtrasHeight);
const bounds = cm.getSection().getBoundingClientRect(); const bounds = sectionEl.getBoundingClientRect();
if (bounds.top < 0 || bounds.bottom > window.innerHeight) { if (bounds.top < 0 || bounds.bottom > window.innerHeight) {
window.scrollBy(0, bounds.top); window.scrollBy(0, bounds.top);
} }
@ -143,9 +144,96 @@ function createSectionsEditor(style) {
save: saveStyle, save: saveStyle,
toggleStyle, toggleStyle,
nextEditor, nextEditor,
prevEditor prevEditor,
closestVisible,
getSearchableInputs,
}; };
function getSearchableInputs(cm) {
return sections.find(s => s.cm === cm).appliesTo.map(a => a.valueEl).filter(Boolean);
}
// priority:
// 1. associated CM for applies-to element
// 2. last active if visible
// 3. first visible
function closestVisible(nearbyElement) {
const cm =
nearbyElement instanceof CodeMirror ? nearbyElement :
nearbyElement instanceof Node &&
(nearbyElement.closest('#sections > .section') || {}).CodeMirror ||
editor.getLastActivatedEditor();
if (nearbyElement instanceof Node && cm) {
const {left, top} = nearbyElement.getBoundingClientRect();
const bounds = cm.display.wrapper.getBoundingClientRect();
if (top >= 0 && top >= bounds.top &&
left >= 0 && left >= bounds.left) {
return cm;
}
}
// closest editor should have at least 2 lines visible
const lineHeight = editor.getEditors()[0].defaultTextHeight();
const scrollY = window.scrollY;
const windowBottom = scrollY + window.innerHeight - 2 * lineHeight;
const allSectionsContainerTop = scrollY + $('#sections').getBoundingClientRect().top;
const distances = [];
const alreadyInView = cm && offscreenDistance(null, cm) === 0;
return alreadyInView ? cm : findClosest();
function offscreenDistance(index, cm) {
if (index >= 0 && distances[index] !== undefined) {
return distances[index];
}
const section = cm.display.wrapper.closest('.section');
if (!section) {
return 1e9;
}
const top = allSectionsContainerTop + section.offsetTop;
if (top < scrollY + lineHeight) {
return Math.max(0, scrollY - top - lineHeight);
}
if (top < windowBottom) {
return 0;
}
const distance = top - windowBottom + section.offsetHeight;
if (index >= 0) {
distances[index] = distance;
}
return distance;
}
function findClosest() {
const editors = editor.getEditors();
const last = editors.length - 1;
let a = 0;
let b = last;
let c;
let distance;
while (a < b - 1) {
c = (a + b) / 2 | 0;
distance = offscreenDistance(c);
if (!distance || !c) {
break;
}
const distancePrev = offscreenDistance(c - 1);
const distanceNext = c < last ? offscreenDistance(c + 1) : 1e20;
if (distancePrev <= distance && distance <= distanceNext) {
b = c;
} else {
a = c;
}
}
while (b && offscreenDistance(b - 1) <= offscreenDistance(b)) {
b--;
}
const cm = editors[b];
if (distances[b] > 0) {
editor.scrollToEditor(cm);
}
return cm;
}
}
function getEditors() { function getEditors() {
return sections.filter(s => !s.isRemoved()).map(s => s.cm); return sections.filter(s => !s.isRemoved()).map(s => s.cm);
} }
@ -241,12 +329,13 @@ function createSectionsEditor(style) {
cm.setCursor(0, 0); cm.setCursor(0, 0);
break; break;
} }
const animation = (cm.getSection().firstElementChild.getAnimations() || [])[0]; // FIXME: what is this?
if (animation) { // const animation = (cm.getSection().firstElementChild.getAnimations() || [])[0];
animation.playbackRate = -1; // if (animation) {
animation.currentTime = 2000; // animation.playbackRate = -1;
animation.play(); // animation.currentTime = 2000;
} // animation.play();
// }
} }
function scrollEntirePageOnCtrlShift(event) { function scrollEntirePageOnCtrlShift(event) {

View File

@ -52,8 +52,6 @@ function createSourceEditor(style) {
updateLivePreview(); updateLivePreview();
}); });
CodeMirror.closestVisible = () => cm;
cm.operation(initAppliesToLineWidget); cm.operation(initAppliesToLineWidget);
const metaCompiler = createMetaCompiler(cm); const metaCompiler = createMetaCompiler(cm);
@ -409,6 +407,7 @@ function createSourceEditor(style) {
save, save,
toggleStyle, toggleStyle,
prevEditor: cm => nextPrevMozDocument(cm, -1), prevEditor: cm => nextPrevMozDocument(cm, -1),
nextEditor: cm => nextPrevMozDocument(cm, 1) nextEditor: cm => nextPrevMozDocument(cm, 1),
closestVisible: () => cm
}; };
} }