diff --git a/js/usercss.js b/js/usercss.js index aef83144..edaff43b 100644 --- a/js/usercss.js +++ b/js/usercss.js @@ -177,7 +177,6 @@ var usercss = (() => { result.label = state.value; const {re, type, text} = state; - let defaultValue; switch (type === 'image' && state.key === 'var' ? '@image@var' : type) { case 'checkbox': { @@ -195,25 +194,34 @@ var usercss = (() => { state.errorPrefix = 'Invalid JSON: '; parseJSONValue(state); state.errorPrefix = ''; + const extractDefault = text => { + if (text.endsWith('*')) { + return text.slice(0, -1); + } + return false; + }; if (Array.isArray(state.value)) { result.options = state.value.map(text => { - if (text.endsWith('*')) { - text = text.slice(0, -1); - defaultValue = text; + const isDefault = extractDefault(text); + if (isDefault) { + result.default = isDefault; } - return createOption(text); + return createOption(isDefault || text); }); } else { result.options = Object.keys(state.value).map(k => { - if (k.endsWith('*')) { - state.value[k] = state.value[k].slice(0, -1); - k = k.slice(0, -1); - defaultValue = k; + const isDefault = extractDefault(k); + const value = state.value[k]; + if (isDefault) { + k = isDefault; + result.default = k; } - return createOption(k, state.value[k]); + return createOption(k, value); }); } - result.default = typeof defaultValue !== 'undefined' ? defaultValue : (result.options[0] || {}).name || ''; + if (result.default === null) { + result.default = (result.options[0] || {}).name || ''; + } break; } @@ -224,13 +232,10 @@ var usercss = (() => { state.errorPrefix = ''; // [default, start, end, step, units] (start, end, step & units are optional) if (Array.isArray(state.value) && state.value.length) { - result.default = parseFloat(state.value.shift()); - const nonDigit = /[^\d.+-]/; + result.default = state.value.shift(); // label may be placed anywhere after default value - const labelIndex = state.value.findIndex(item => nonDigit.test(item)); - // but should not contain any numbers '4px' => 'px' - result.units = labelIndex < 0 ? '' : state.value.splice(labelIndex, 1)[0].toString().replace(/[\d.+-]/g, ''); - result.range = state.value.filter(item => !nonDigit.test(item)); + result.units = (state.value.find(i => typeof i === 'string') || '').replace(/[\d.+-]/g, ''); + result.range = state.value.filter(i => typeof i === 'number'); } break; } @@ -615,7 +620,7 @@ var usercss = (() => { va[value] = colorConverter.format(colorConverter.parse(va[value]), 'rgb'); } else if ( (va.type === 'number' || va.type === 'range') && - !(typeof va[value] === 'number' || Array.isArray(va.range)) + (typeof va[value] !== 'number' || !Array.isArray(va.range)) ) { throw new Error(chrome.i18n.getMessage('styleMetaErrorRangeOrNumber', va.type)); } diff --git a/manage/config-dialog.css b/manage/config-dialog.css index 97b8a0bf..da1fd7d0 100644 --- a/manage/config-dialog.css +++ b/manage/config-dialog.css @@ -99,10 +99,9 @@ } .current-value { - outline: 1px solid rgba(128, 128, 128, 0.5); padding: 2px 4px; margin-right: 4px; -} + } .config-number span, .config-range span { line-height: 22px; diff --git a/manage/config-dialog.js b/manage/config-dialog.js index ae920966..6ff8ceac 100644 --- a/manage/config-dialog.js +++ b/manage/config-dialog.js @@ -201,25 +201,18 @@ function configDialog(style) { return va.value === null || va.value === undefined || va.value === va.default; } - function handleRangeAndNumberInputs(va, options) { + function rangeToProps(range = []) { const dataset = {}; - options.value = va.default; - if (typeof va.range[0] !== 'undefined') { - options.min = dataset.min = va.range[0]; + if (range.length > 0) { + dataset.min = range[0]; } - if (typeof va.range[1] !== 'undefined') { - options.max = dataset.max = va.range[1]; + if (range.length > 1) { + dataset.max = range[1]; } - if (va.range[2]) { - options.step = va.range[2]; + if (range[2]) { + dataset.step = range[2]; } - const children = va.type === 'range' ? [$create('span.current-value', {textContent: va.value + va.units})] : []; - children.push( - $create(`span.current-${va.type}`, {dataset}, [ - va.input = $create('input.config-value', options), - ]) - ); - return children; + return dataset; } function buildConfigForm() { @@ -279,6 +272,21 @@ function configDialog(style) { ]; break; + case 'range': + case 'number': { + children = [ + va.type === 'range' && $create('span.current-value', {textContent: va.value + va.units}), + va.input = $create('input.config-value', { + va, + type: va.type, + value: va.default, + ...rangeToProps(va.range), + onchange: updateVarOnChange + }) + ]; + break; + } + default: { const options = { va, @@ -287,13 +295,9 @@ function configDialog(style) { oninput: updateVarOnInput, onfocus: selectAllOnFocus, }; - if (va.type === 'range' || va.type === 'number') { - children = handleRangeAndNumberInputs(va, options); - } else { - children = [ - va.input = $create('input.config-value', options), - ]; - } + children = [ + va.input = $create('input.config-value', options), + ]; } } @@ -314,26 +318,29 @@ function configDialog(style) { } function updateVarOnChange() { + console.log('updateVar', this.type) if (this.type === 'number') { this.value = this.va.value = clampValue(this.value, this.va.range); } else if (this.type === 'range') { - $('.current-value', this.closest('.config-range')).textContent = this.va.value + (this.va.units || ''); this.va.value = parseFloat(this.value); + $('.current-value', this.closest('.config-range')).textContent = this.va.value + (this.va.units || ''); } else { this.va.value = this.type !== 'checkbox' ? this.value : this.checked ? '1' : '0'; } + console.log(this.va.value); } // Clamp input[type=number] to a valid range function clampValue(value, [min = 0, max = 100, step]) { if (value < min) { return min; - } else if (value > max) { + } + if (value > max) { return max; } - const remainder = value % (step || 1); + const inv = 1 / (step || 1); // Don't restrict to integer values if step is undefined. - return typeof step !== 'undefined' && remainder !== 0 ? value - remainder : value; + return typeof step !== 'undefined' ? Math.floor(inv * value) / inv : value; } function updateVarOnInput(event, debounced = false) {