Add: use cache template

This commit is contained in:
eight 2017-11-16 14:48:13 +08:00 committed by tophf
parent 3fd4343cfd
commit 5dbd2249dd

View File

@ -1,6 +1,16 @@
/* global regExpTester debounce messageBox CodeMirror */ /* global regExpTester debounce messageBox CodeMirror */
'use strict'; 'use strict';
function templateCache(cache) {
function clone(id) {
if (typeof cache[id] === 'function') {
cache[id] = cache[id]();
}
return cache[id].cloneNode(true);
}
return {clone};
}
function createAppliesToLineWidget(cm) { function createAppliesToLineWidget(cm) {
const APPLIES_TYPE = [ const APPLIES_TYPE = [
[t('appliesUrlOption'), 'url'], [t('appliesUrlOption'), 'url'],
@ -13,6 +23,57 @@ function createAppliesToLineWidget(cm) {
let fromLine, toLine, styleVariables; let fromLine, toLine, styleVariables;
let initialized = false; let initialized = false;
const template = templateCache({
container: () =>
$element({className: 'applies-to', appendChild: [
$element({tag: 'label', appendChild: t('appliesLabel')}),
$element({
tag: 'ul',
className: 'applies-to-list'
})
]}),
listItem: () =>
$element({tag: 'li', appendChild: [
$element({
tag: 'select',
className: 'applies-type',
appendChild: APPLIES_TYPE.map(([label, value]) => $element({
tag: 'option',
value: value,
textContent: label
}))
}),
$element({
tag: 'input',
className: 'applies-value'
}),
$element({
tag: 'button',
type: 'button',
className: 'applies-to-regexp-test',
textContent: t('styleRegexpTestButton')
}),
$element({
tag: 'button',
type: 'button',
className: 'applies-to-remove',
textContent: t('appliesRemove')
}),
$element({
tag: 'button',
type: 'button',
className: 'applies-to-add',
textContent: t('appliesAdd')
})
]}),
appliesToEverything: () =>
$element({
tag: 'li',
className: 'applies-to-everything',
textContent: t('appliesToEverything')
})
});
return {toggle}; return {toggle};
function toggle(newState = !initialized) { function toggle(newState = !initialized) {
@ -240,128 +301,93 @@ function createAppliesToLineWidget(cm) {
} }
function buildElement({applies}) { function buildElement({applies}) {
const el = $element({className: 'applies-to', appendChild: [ const el = template.clone('container');
$element({tag: 'label', appendChild: [ const appliesToList = $('.applies-to-list', el);
t('appliesLabel'), applies.map(makeLi)
// $element({tag: 'svg'}) .forEach(item => appliesToList.appendChild(item));
]}), if (!appliesToList.childNodes.length) {
$element({ appliesToList.appendChild(template.clone('appliesToEverything'));
tag: 'ul',
className: 'applies-to-list',
appendChild: applies.map(makeLi)
})
]});
if (!$('li', el)) {
$('ul', el).appendChild($element({
tag: 'li',
className: 'applies-to-everything',
textContent: t('appliesToEverything')
}));
} }
return el; return el;
function makeLi(apply) { function makeLi(apply) {
const el = $element({tag: 'li', appendChild: makeInput(apply)}); const el = template.clone('listItem');
el.dataset.type = apply.type.text; el.dataset.type = apply.type.text;
el.addEventListener('change', e => { el.addEventListener('change', e => {
if (e.target.classList.contains('applies-type')) { if (e.target.classList.contains('applies-type')) {
el.dataset.type = apply.type.text; el.dataset.type = apply.type.text;
} }
}); });
return el;
}
function makeInput(apply) { const typeInput = $('.applies-type', el);
const typeInput = $element({
tag: 'select',
className: 'applies-type',
appendChild: APPLIES_TYPE.map(([label, value]) => $element({
tag: 'option',
value: value,
textContent: label
})),
onchange() {
applyChange(apply.type, this.value);
}
});
typeInput.value = apply.type.text; typeInput.value = apply.type.text;
const valueInput = $element({ typeInput.onchange = function () {
tag: 'input', applyChange(apply.type, this.value);
className: 'applies-value', };
value: apply.value.text,
oninput() { const valueInput = $('.applies-value', el);
debounce(applyChange, THROTTLE_DELAY, apply.value, this.value); valueInput.value = apply.value.text;
}, valueInput.oninput = function () {
onfocus: updateRegexpTest debounce(applyChange, THROTTLE_DELAY, apply.value, this.value);
}); };
const regexpTestButton = $element({ valueInput.onfocus = updateRegexpTest;
tag: 'button',
type: 'button', const regexpTestButton = $('.applies-to-regexp-test', el);
className: 'applies-to-regexp-test', regexpTestButton.onclick = () => {
textContent: t('styleRegexpTestButton'), regExpTester.toggle();
onclick() { regExpTester.update([apply.value.text]);
regExpTester.toggle(); };
regExpTester.update([apply.value.text]);
const removeButton = $('.applies-to-remove', el);
removeButton.onclick = function () {
const i = applies.indexOf(apply);
let repl;
let from;
let to;
if (applies.length < 2) {
messageBox({
contents: chrome.i18n.getMessage('appliesRemoveError'),
buttons: [t('confirmClose')]
});
return;
} }
}); if (i === 0) {
const removeButton = $element({ from = apply.mark.find().from;
tag: 'button', to = applies[i + 1].mark.find().from;
type: 'button', repl = '';
className: 'applies-to-remove', } else if (i === applies.length - 1) {
textContent: t('appliesRemove'), from = applies[i - 1].mark.find().to;
onclick() { to = apply.mark.find().to;
const i = applies.indexOf(apply); repl = '';
let repl; } else {
let from; from = applies[i - 1].mark.find().to;
let to; to = applies[i + 1].mark.find().from;
if (applies.length < 2) { repl = ', ';
messageBox({
contents: chrome.i18n.getMessage('appliesRemoveError'),
buttons: [t('confirmClose')]
});
return;
}
if (i === 0) {
from = apply.mark.find().from;
to = applies[i + 1].mark.find().from;
repl = '';
} else if (i === applies.length - 1) {
from = applies[i - 1].mark.find().to;
to = apply.mark.find().to;
repl = '';
} else {
from = applies[i - 1].mark.find().to;
to = applies[i + 1].mark.find().from;
repl = ', ';
}
cm.replaceRange(repl, from, to, 'appliesTo');
clearApply(apply);
this.closest('li').remove();
applies.splice(i, 1);
} }
}); cm.replaceRange(repl, from, to, 'appliesTo');
const addButton = $element({ clearApply(apply);
tag: 'button', this.closest('li').remove();
type: 'button', applies.splice(i, 1);
className: 'applies-to-add', };
textContent: t('appliesAdd'),
onclick() { const addButton = $('.applies-to-add', el);
const i = applies.indexOf(apply); addButton.onclick = function () {
const pos = apply.mark.find().to; const i = applies.indexOf(apply);
const text = `, ${apply.type.text}("")`; const pos = apply.mark.find().to;
cm.replaceRange(text, pos, pos, 'appliesTo'); const text = `, ${apply.type.text}("")`;
const newApply = createApply( cm.replaceRange(text, pos, pos, 'appliesTo');
cm.indexFromPos(pos) + 2, const newApply = createApply(
apply.type.text, cm.indexFromPos(pos) + 2,
'', apply.type.text,
true '',
); true
setupApplyMarkers(newApply); );
applies.splice(i + 1, 0, newApply); setupApplyMarkers(newApply);
this.closest('li').insertAdjacentElement('afterend', makeLi(newApply)); applies.splice(i + 1, 0, newApply);
} this.closest('li').insertAdjacentElement('afterend', makeLi(newApply));
}); };
return [typeInput, valueInput, regexpTestButton, removeButton, addButton];
return el;
function updateRegexpTest() { function updateRegexpTest() {
if (apply.type.text === 'regexp') { if (apply.type.text === 'regexp') {