Merge remote-tracking branch 'upstream/master'
* upstream/master: (45 commits) Alas, poor clamp! I knew it well Update number input on blur Don't re-render input while focused Fix undefined value Update current value in updateRangeCurrentValue Remove onblur, don't save invalid inputs Change stored number value on change Remove isNumber function Fix isNumber function Change clamp function order & only call onblur Remove misleading comment Fix strict equals Fix clamp function Check for null in isNumber Fix clamp function Fix clamp undefined step Fix clamp undefined min/max Switch to isNumber function More suggested changes Remove unnecessary css ...
This commit is contained in:
commit
5a8936e15e
|
@ -1051,6 +1051,15 @@
|
||||||
},
|
},
|
||||||
"description": "Error displayed when the value of @var color is invalid"
|
"description": "Error displayed when the value of @var color is invalid"
|
||||||
},
|
},
|
||||||
|
"styleMetaErrorRangeOrNumber": {
|
||||||
|
"message": "Invalid @var $type$: value must be an array containing at least one number at index zero",
|
||||||
|
"description": "Error displayed when the value of @var number or @var range is invalid",
|
||||||
|
"placeholders": {
|
||||||
|
"type": {
|
||||||
|
"content": "$1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"styleMetaErrorPreprocessor": {
|
"styleMetaErrorPreprocessor": {
|
||||||
"message": "Unsupported @preprocessor: $preprocessor$",
|
"message": "Unsupported @preprocessor: $preprocessor$",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
|
|
|
@ -29,7 +29,7 @@ var usercss = (() => {
|
||||||
['version', 0],
|
['version', 0],
|
||||||
]);
|
]);
|
||||||
const MANDATORY_META = ['name', 'namespace', 'version'];
|
const MANDATORY_META = ['name', 'namespace', 'version'];
|
||||||
const META_VARS = ['text', 'color', 'checkbox', 'select', 'dropdown', 'image'];
|
const META_VARS = ['text', 'color', 'checkbox', 'select', 'dropdown', 'image', 'number', 'range'];
|
||||||
const META_URLS = [...KNOWN_META.keys()].filter(k => k.endsWith('URL'));
|
const META_URLS = [...KNOWN_META.keys()].filter(k => k.endsWith('URL'));
|
||||||
|
|
||||||
const BUILDER = {
|
const BUILDER = {
|
||||||
|
@ -194,12 +194,40 @@ var usercss = (() => {
|
||||||
state.errorPrefix = 'Invalid JSON: ';
|
state.errorPrefix = 'Invalid JSON: ';
|
||||||
parseJSONValue(state);
|
parseJSONValue(state);
|
||||||
state.errorPrefix = '';
|
state.errorPrefix = '';
|
||||||
|
const extractDefaultOption = (key, value) => {
|
||||||
|
if (key.endsWith('*')) {
|
||||||
|
const option = createOption(key.slice(0, -1), value);
|
||||||
|
result.default = option.name;
|
||||||
|
return option;
|
||||||
|
}
|
||||||
|
return createOption(key, value);
|
||||||
|
};
|
||||||
if (Array.isArray(state.value)) {
|
if (Array.isArray(state.value)) {
|
||||||
result.options = state.value.map(text => createOption(text));
|
result.options = state.value.map(k => extractDefaultOption(k));
|
||||||
} else {
|
} else {
|
||||||
result.options = Object.keys(state.value).map(k => createOption(k, state.value[k]));
|
result.options = Object.keys(state.value).map(k => extractDefaultOption(k, state.value[k]));
|
||||||
|
}
|
||||||
|
if (result.default === null) {
|
||||||
|
result.default = (result.options[0] || {}).name || '';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'number':
|
||||||
|
case 'range': {
|
||||||
|
state.errorPrefix = 'Invalid JSON: ';
|
||||||
|
parseJSONValue(state);
|
||||||
|
state.errorPrefix = '';
|
||||||
|
// [default, start, end, step, units] (start, end, step & units are optional)
|
||||||
|
if (Array.isArray(state.value) && state.value.length) {
|
||||||
|
// label may be placed anywhere
|
||||||
|
result.units = (state.value.find(i => typeof i === 'string') || '').replace(/[\d.+-]/g, '');
|
||||||
|
const range = state.value.filter(i => typeof i === 'number' || i === null);
|
||||||
|
result.default = range[0];
|
||||||
|
result.min = range[1];
|
||||||
|
result.max = range[2];
|
||||||
|
result.step = range[3] === 0 ? 1 : range[3];
|
||||||
}
|
}
|
||||||
result.default = (result.options[0] || {}).name || '';
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -541,6 +569,9 @@ var usercss = (() => {
|
||||||
// TODO: handle customized image
|
// TODO: handle customized image
|
||||||
return va.options.find(o => o.name === va[prop]).value;
|
return va.options.find(o => o.name === va[prop]).value;
|
||||||
}
|
}
|
||||||
|
if ((va.type === 'number' || va.type === 'range') && va.units) {
|
||||||
|
return va[prop] + va.units;
|
||||||
|
}
|
||||||
return va[prop];
|
return va[prop];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -578,6 +609,8 @@ var usercss = (() => {
|
||||||
throw new Error(chrome.i18n.getMessage('styleMetaErrorCheckbox'));
|
throw new Error(chrome.i18n.getMessage('styleMetaErrorCheckbox'));
|
||||||
} else if (va.type === 'color') {
|
} else if (va.type === 'color') {
|
||||||
va[value] = colorConverter.format(colorConverter.parse(va[value]), 'rgb');
|
va[value] = colorConverter.format(colorConverter.parse(va[value]), 'rgb');
|
||||||
|
} else if ((va.type === 'number' || va.type === 'range') && typeof va[value] !== 'number') {
|
||||||
|
throw new Error(chrome.i18n.getMessage('styleMetaErrorRangeOrNumber', va.type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,15 @@
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.current-value {
|
||||||
|
padding: 2px 4px;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-number span, .config-range span {
|
||||||
|
line-height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
.config-body label:not(.nondefault) .config-reset-icon {
|
.config-body label:not(.nondefault) .config-reset-icon {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
|
|
|
@ -258,16 +258,44 @@ function configDialog(style) {
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'range':
|
||||||
|
case 'number': {
|
||||||
|
const options = {
|
||||||
|
va,
|
||||||
|
type: va.type,
|
||||||
|
onfocus: va.type === 'number' ? selectAllOnFocus : null,
|
||||||
|
onblur: va.type === 'number' ? updateVarOnBlur : null,
|
||||||
|
onchange: updateVarOnChange,
|
||||||
|
oninput: updateVarOnInput,
|
||||||
|
required: true
|
||||||
|
};
|
||||||
|
if (typeof va.min === 'number') {
|
||||||
|
options.min = va.min;
|
||||||
|
}
|
||||||
|
if (typeof va.max === 'number') {
|
||||||
|
options.max = va.max;
|
||||||
|
}
|
||||||
|
if (typeof va.step === 'number' && isFinite(va.step)) {
|
||||||
|
options.step = va.step;
|
||||||
|
}
|
||||||
|
children = [
|
||||||
|
va.type === 'range' && $create('span.current-value'),
|
||||||
|
va.input = $create('input.config-value', options)
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
children = [
|
children = [
|
||||||
va.input = $create('input.config-value', {
|
va.input = $create('input.config-value', {
|
||||||
va,
|
va,
|
||||||
type: 'text',
|
type: va.type,
|
||||||
onchange: updateVarOnChange,
|
onchange: updateVarOnChange,
|
||||||
oninput: updateVarOnInput,
|
oninput: updateVarOnInput,
|
||||||
|
onfocus: selectAllOnFocus,
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resetter = resetter.cloneNode(true);
|
resetter = resetter.cloneNode(true);
|
||||||
|
@ -285,8 +313,28 @@ function configDialog(style) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateVarOnBlur() {
|
||||||
|
this.value = isDefault(this.va) ? this.va.default : this.va.value;
|
||||||
|
}
|
||||||
|
|
||||||
function updateVarOnChange() {
|
function updateVarOnChange() {
|
||||||
this.va.value = this.type !== 'checkbox' ? this.value : this.checked ? '1' : '0';
|
if (this.type === 'range') {
|
||||||
|
this.va.value = Number(this.value);
|
||||||
|
updateRangeCurrentValue(this.va, this.va.value);
|
||||||
|
} else if (this.type === 'number') {
|
||||||
|
if (this.reportValidity()) {
|
||||||
|
this.va.value = Number(this.value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.va.value = this.type !== 'checkbox' ? this.value : this.checked ? '1' : '0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateRangeCurrentValue(va, value) {
|
||||||
|
const span = $('.current-value', va.input.closest('.config-range'));
|
||||||
|
if (span) {
|
||||||
|
span.textContent = value + (va.units || '');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateVarOnInput(event, debounced = false) {
|
function updateVarOnInput(event, debounced = false) {
|
||||||
|
@ -297,8 +345,15 @@ function configDialog(style) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function selectAllOnFocus(event) {
|
||||||
|
event.target.select();
|
||||||
|
}
|
||||||
|
|
||||||
function renderValues(varsToRender = vars) {
|
function renderValues(varsToRender = vars) {
|
||||||
for (const va of varsToRender) {
|
for (const va of varsToRender) {
|
||||||
|
if (va.input === document.activeElement) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const value = isDefault(va) ? va.default : va.value;
|
const value = isDefault(va) ? va.default : va.value;
|
||||||
if (va.type === 'color') {
|
if (va.type === 'color') {
|
||||||
va.input.style.backgroundColor = value;
|
va.input.style.backgroundColor = value;
|
||||||
|
@ -307,6 +362,9 @@ function configDialog(style) {
|
||||||
}
|
}
|
||||||
} else if (va.type === 'checkbox') {
|
} else if (va.type === 'checkbox') {
|
||||||
va.input.checked = Number(value);
|
va.input.checked = Number(value);
|
||||||
|
} else if (va.type === 'range') {
|
||||||
|
va.input.value = value;
|
||||||
|
updateRangeCurrentValue(va, va.input.value);
|
||||||
} else {
|
} else {
|
||||||
va.input.value = value;
|
va.input.value = value;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user