Skip to content

Commit

Permalink
speed up opening manager a bit
Browse files Browse the repository at this point in the history
* faster `fit-width` for selects
* faster calcObjSize due to no garbage collection overhead
* call performance.now() 8 times less
  • Loading branch information
tophf committed Sep 7, 2023
1 parent 9bb206b commit cb76e3d
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 49 deletions.
5 changes: 4 additions & 1 deletion js/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,10 @@ function setupLivePrefs(ids) {
}
for (const el of els) {
const oldValue = getValue(el);
if (!isSame(el, oldValue, value)) {
const diff = !isSame(el, oldValue, value);
if ((init || diff) && el.type === 'select-one' && el.classList.contains('fit-width')) {
fitSelectBox(el, value, init); /* global fitSelectBox */// manage/render.js
} else if (diff) {
if (el.type === 'radio') {
el.checked = value === oldValue;
} else if (el.type === 'checkbox') {
Expand Down
8 changes: 2 additions & 6 deletions manage/manage.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* global API msg */// msg.js
/* global CHROME UA debounce */// toolbox.js
/* global CHROME debounce */// toolbox.js
/* global Events handleBulkChange handleVisibilityChange */// events.js
/* global fitSelectBoxesIn switchUI showStyles */// render.js
/* global switchUI showStyles */// render.js
/* global fltMode */// filters.js
/* global prefs */
/* global router */
Expand Down Expand Up @@ -93,10 +93,6 @@ newUI.renderClass();
'filteredStylesAllHidden',
].map(id => `--${id}:"${CSS.escape(t(id))}";`).join('')
}}`);

if (!UA.vivaldi) {
fitSelectBoxesIn($('#filters'));
}
if (CHROME >= 80 && CHROME <= 88) {
// Wrong checkboxes are randomly checked after going back in history, https://crbug.com/1138598
window.on('pagehide', () => {
Expand Down
90 changes: 48 additions & 42 deletions manage/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,16 @@ function createAgeText(el, style) {
}

function calcObjSize(obj) {
// Inaccurate but simple
return typeof obj !== 'object' ? `${obj}`.length :
!obj ? 0 :
Array.isArray(obj) ? obj.reduce((sum, v) => sum + calcObjSize(v), 0) :
Object.entries(obj).reduce((sum, [k, v]) => sum + k.length + calcObjSize(v), 0);
if (obj === true || obj == null) return 4;
if (obj === false) return 5;
let v = typeof obj;
if (v === 'string') return obj.length + 2; // inaccurate but fast
if (v === 'number') return (v = obj) >= 0 && v < 10 ? 1 : Math.ceil(Math.log10(v < 0 ? -v : v));
if (v !== 'object') return `${obj}`.length;
let sum = 1;
if (Array.isArray(obj)) for (v of obj) sum += calcObjSize(v) + 1;
else for (const k in obj) sum += k.length + 3 + calcObjSize(obj[k]) + 1;
return sum;
}

function createStyleElement({styleMeta: style, styleNameLC: nameLC, styleSize: size}) {
Expand Down Expand Up @@ -290,46 +295,43 @@ async function initBadFavs() {
chrome.webRequest.onErrorOccurred.addListener(fn, filter); // works in FF
}

function fitSelectBox(...elems) {
const data = [];
for (const el of elems) {
const sel = el.selectedOptions[0];
if (!sel) continue;
const oldWidth = parseFloat(el.style.width);
const text = [];
data.push({el, text, oldWidth});
for (const elOpt of el.options) {
text.push(elOpt.textContent);
if (elOpt !== sel) elOpt.textContent = '';
{
const hideOpts = function (evt) {
for (const o of [...this.options]) {
if (o.value !== this.value) o.remove();
}
el.style.width = 'min-content';
}
for (const {el, text, oldWidth} of data) {
const w = el.offsetWidth;
if (w && oldWidth !== w) el.style.width = w + 'px';
text.forEach((t, i) => (el.options[i].textContent = t));
}
}
this.style.removeProperty('width');
if (evt && evt.isTrusted) return this.offsetWidth; // force layout
};

/* exported fitSelectBoxesIn */
/**
* @param {HTMLDetailsElement} el
* @param {string} targetSel
*/
function fitSelectBoxesIn(el, targetSel = 'select.fit-width') {
const fit = () => {
if (el.open) {
fitSelectBox(...$$(targetSel, el));
}
const showOpts = function (evt) {
if (evt.button || this[1]) return;
const opts = this._opts;
const elems = [...opts.values()];
const i = elems.indexOf(opts.get(this.value));
this.style.width = this.offsetWidth + 'px';
if (i > 0) this.prepend(...elems.slice(0, i));
this.append(...elems.slice(i + 1));
};
el.on('change', ({target}) => {
if (el.open && target.matches(targetSel)) {
fitSelectBox(target);

window.fitSelectBox = (el, value, init) => {
const opts = el._opts || (el._opts = new Map());
if (init) {
for (const o of el.options) opts.set(o.value, o);
el.on('keydown', showOpts);
el.on('mousedown', showOpts);
el.on('blur', hideOpts);
el.on('input', hideOpts);
}
});
fit();
new MutationObserver(fit)
.observe(el, {attributeFilter: ['open'], attributes: true});
if (typeof value !== 'string') value = `${value}`;
const opt = opts.get(value);
if (!opt.isConnected) {
if (el[0]) el[0].replaceWith(opt);
else el.append(opt);
}
el.value = value;
if (init) hideOpts.call(el);
};
}

function highlightEditedStyle() {
Expand Down Expand Up @@ -379,7 +381,11 @@ function showStyles(styles = [], matchUrlIds) {

function renderStyles() {
const t0 = performance.now();
while (index < sorted.length && (shouldRenderAll || performance.now() - t0 < 50)) {
while (index < sorted.length && (
shouldRenderAll ||
(index & 7) < 7 ||
performance.now() - t0 < 50
)) {
const entry = createStyleElement(sorted[index++]);
if (matchUrlIds && !matchUrlIds.includes(entry.styleMeta.id)) {
entry.classList.add('not-matching');
Expand Down

0 comments on commit cb76e3d

Please sign in to comment.