edit: throttle setOption for 'theme' and 'lineWrapping'

when the style has more than 4 sections, these options are propagated to CM instances in 100 ms chunks, and a progress overlay is shown over the corresponding option element after 100 ms
This commit is contained in:
tophf 2017-09-12 22:45:33 +03:00
parent a8796b0bd2
commit 3d0b811b27
2 changed files with 87 additions and 0 deletions

View File

@ -134,6 +134,12 @@ h2 .svg-icon, label .svg-icon {
#options .option > * {
padding-right: 0.25rem;
}
.set-option-progress {
position: absolute;
background-color: currentColor;
content: "";
opacity: .15;
}
/************ content ***********/
#sections > div {
margin: 0.7rem;

View File

@ -269,6 +269,10 @@ function initCodeMirror() {
CM.getOption = o => CodeMirror.defaults[o];
CM.setOption = (o, v) => {
CodeMirror.defaults[o] = v;
if (editors.length > 4 && (o === 'theme' || o === 'lineWrapping')) {
throttleSetOption({key: o, value: v, index: 0});
return;
}
editors.forEach(editor => {
editor.setOption(o, v);
});
@ -306,6 +310,83 @@ function initCodeMirror() {
setupLivePrefs();
hotkeyRerouter.setState(true);
const THROTTLE_AFTER_MS = 100;
const THROTTLE_SHOW_PROGRESS_AFTER_MS = 100;
function throttleSetOption({
key,
value,
index,
timeStart = performance.now(),
cmStart = editors.lastActive || editors[0],
editorsCopy = editors.slice(),
progress,
}) {
if (index === 0) {
if (!cmStart) {
return;
}
cmStart.setOption(key, value);
}
const t0 = performance.now();
const total = editorsCopy.length;
while (index < total) {
const cm = editorsCopy[index++];
if (cm === cmStart ||
cm !== editors[index] && !editors.includes(cm)) {
continue;
}
cm.setOption(key, value);
if (performance.now() - t0 > THROTTLE_AFTER_MS) {
break;
}
}
if (index >= total) {
if (progress) {
progress.remove();
}
return;
}
if (!progress &&
index < total / 2 &&
t0 - timeStart > THROTTLE_SHOW_PROGRESS_AFTER_MS) {
let option = $('#editor.' + key);
if (option) {
if (option.type === 'checkbox') {
option = (option.labels || [])[0] || option.nextElementSibling || option;
}
progress = document.body.appendChild($element({
className: 'set-option-progress',
targetElement: option,
}));
}
}
if (progress) {
const optionBounds = progress.targetElement.getBoundingClientRect();
const bounds = {
top: optionBounds.top + window.scrollY + 1,
left: optionBounds.left + window.scrollX + 1,
width: (optionBounds.width - 2) * index / total | 0,
height: optionBounds.height - 2,
};
const style = progress.style;
for (const prop in bounds) {
if (bounds[prop] !== parseFloat(style[prop])) {
style[prop] = bounds[prop] + 'px';
}
}
}
setTimeout(throttleSetOption, 0, {
key,
value,
index,
timeStart,
cmStart,
editorsCopy,
progress,
});
}
}
function acmeEventListener(event) {