StackGenVis: Alignment of Data, Algorithms, and Models for Stacking Ensemble Learning Using Performance Metrics
https://doi.org/10.1109/TVCG.2020.3030352
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
277 lines
8.2 KiB
277 lines
8.2 KiB
4 years ago
|
import { isFunction } from '../utils/inspect';
|
||
|
import { toInteger, toFloat } from '../utils/number';
|
||
|
import { toString } from '../utils/string'; // @vue/component
|
||
|
|
||
|
export default {
|
||
|
model: {
|
||
|
prop: 'value',
|
||
|
event: 'update'
|
||
|
},
|
||
|
props: {
|
||
|
value: {
|
||
|
type: [String, Number],
|
||
|
default: ''
|
||
|
},
|
||
|
ariaInvalid: {
|
||
|
type: [Boolean, String],
|
||
|
default: false
|
||
|
},
|
||
|
readonly: {
|
||
|
type: Boolean,
|
||
|
default: false
|
||
|
},
|
||
|
plaintext: {
|
||
|
type: Boolean,
|
||
|
default: false
|
||
|
},
|
||
|
autocomplete: {
|
||
|
type: String,
|
||
|
default: null
|
||
|
},
|
||
|
placeholder: {
|
||
|
type: String,
|
||
|
default: null
|
||
|
},
|
||
|
formatter: {
|
||
|
type: Function,
|
||
|
default: null
|
||
|
},
|
||
|
lazyFormatter: {
|
||
|
type: Boolean,
|
||
|
default: false
|
||
|
},
|
||
|
trim: {
|
||
|
type: Boolean,
|
||
|
default: false
|
||
|
},
|
||
|
number: {
|
||
|
type: Boolean,
|
||
|
default: false
|
||
|
},
|
||
|
lazy: {
|
||
|
// Only update the `v-model` on blur/change events
|
||
|
type: Boolean,
|
||
|
default: false
|
||
|
},
|
||
|
debounce: {
|
||
|
// Debounce timout (in ms). Not applicable with `lazy` prop
|
||
|
type: [Number, String],
|
||
|
default: 0
|
||
|
}
|
||
|
},
|
||
|
data: function data() {
|
||
|
return {
|
||
|
localValue: toString(this.value),
|
||
|
vModelValue: this.value
|
||
|
};
|
||
|
},
|
||
|
computed: {
|
||
|
computedClass: function computedClass() {
|
||
|
return [{
|
||
|
// Range input needs class `custom-range`
|
||
|
'custom-range': this.type === 'range',
|
||
|
// `plaintext` not supported by `type="range"` or `type="color"`
|
||
|
'form-control-plaintext': this.plaintext && this.type !== 'range' && this.type !== 'color',
|
||
|
// `form-control` not used by `type="range"` or `plaintext`
|
||
|
// Always used by `type="color"`
|
||
|
'form-control': !this.plaintext && this.type !== 'range' || this.type === 'color'
|
||
|
}, this.sizeFormClass, this.stateClass];
|
||
|
},
|
||
|
computedAriaInvalid: function computedAriaInvalid() {
|
||
|
if (!this.ariaInvalid || this.ariaInvalid === 'false') {
|
||
|
// `this.ariaInvalid` is `null` or `false` or 'false'
|
||
|
return this.computedState === false ? 'true' : null;
|
||
|
}
|
||
|
|
||
|
if (this.ariaInvalid === true) {
|
||
|
// User wants explicit `:aria-invalid="true"`
|
||
|
return 'true';
|
||
|
} // Most likely a string value (which could be the string 'true')
|
||
|
|
||
|
|
||
|
return this.ariaInvalid;
|
||
|
},
|
||
|
computedDebounce: function computedDebounce() {
|
||
|
// Ensure we have a positive number equal to or greater than 0
|
||
|
return Math.max(toInteger(this.debounce) || 0, 0);
|
||
|
},
|
||
|
hasFormatter: function hasFormatter() {
|
||
|
return isFunction(this.formatter);
|
||
|
}
|
||
|
},
|
||
|
watch: {
|
||
|
value: function value(newVal) {
|
||
|
var stringifyValue = toString(newVal);
|
||
|
|
||
|
if (stringifyValue !== this.localValue && newVal !== this.vModelValue) {
|
||
|
// Clear any pending debounce timeout, as we are overwriting the user input
|
||
|
this.clearDebounce(); // Update the local values
|
||
|
|
||
|
this.localValue = stringifyValue;
|
||
|
this.vModelValue = newVal;
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
mounted: function mounted() {
|
||
|
// Create non-reactive property and set up destroy handler
|
||
|
this.$_inputDebounceTimer = null;
|
||
|
this.$on('hook:beforeDestroy', this.clearDebounce); // Preset the internal state
|
||
|
|
||
|
var value = this.value;
|
||
|
var stringifyValue = toString(value);
|
||
|
/* istanbul ignore next */
|
||
|
|
||
|
if (stringifyValue !== this.localValue && value !== this.vModelValue) {
|
||
|
this.localValue = stringifyValue;
|
||
|
this.vModelValue = value;
|
||
|
}
|
||
|
},
|
||
|
methods: {
|
||
|
clearDebounce: function clearDebounce() {
|
||
|
clearTimeout(this.$_inputDebounceTimer);
|
||
|
this.$_inputDebounceTimer = null;
|
||
|
},
|
||
|
formatValue: function formatValue(value, evt) {
|
||
|
var force = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
||
|
value = toString(value);
|
||
|
|
||
|
if (this.hasFormatter && (!this.lazyFormatter || force)) {
|
||
|
value = this.formatter(value, evt);
|
||
|
}
|
||
|
|
||
|
return value;
|
||
|
},
|
||
|
modifyValue: function modifyValue(value) {
|
||
|
// Emulate `.trim` modifier behaviour
|
||
|
if (this.trim) {
|
||
|
value = value.trim();
|
||
|
} // Emulate `.number` modifier behaviour
|
||
|
|
||
|
|
||
|
if (this.number) {
|
||
|
var number = toFloat(value);
|
||
|
value = isNaN(number) ? value : number;
|
||
|
}
|
||
|
|
||
|
return value;
|
||
|
},
|
||
|
updateValue: function updateValue(value) {
|
||
|
var _this = this;
|
||
|
|
||
|
var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
||
|
var lazy = this.lazy;
|
||
|
|
||
|
if (lazy && !force) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
value = this.modifyValue(value);
|
||
|
|
||
|
if (value !== this.vModelValue) {
|
||
|
this.clearDebounce();
|
||
|
|
||
|
var doUpdate = function doUpdate() {
|
||
|
_this.vModelValue = value;
|
||
|
|
||
|
_this.$emit('update', value);
|
||
|
};
|
||
|
|
||
|
var debounce = this.computedDebounce; // Only debounce the value update when a value greater than `0`
|
||
|
// is set and we are not in lazy mode or this is a forced update
|
||
|
|
||
|
if (debounce > 0 && !lazy && !force) {
|
||
|
this.$_inputDebounceTimer = setTimeout(doUpdate, debounce);
|
||
|
} else {
|
||
|
// Immediately update the v-model
|
||
|
doUpdate();
|
||
|
}
|
||
|
} else if (this.hasFormatter) {
|
||
|
// When the `vModelValue` hasn't changed but the actual input value
|
||
|
// is out of sync, make sure to change it to the given one
|
||
|
// Usually caused by browser autocomplete and how it triggers the
|
||
|
// change or input event, or depending on the formatter function
|
||
|
// https://github.com/bootstrap-vue/bootstrap-vue/issues/2657
|
||
|
// https://github.com/bootstrap-vue/bootstrap-vue/issues/3498
|
||
|
|
||
|
/* istanbul ignore next: hard to test */
|
||
|
var $input = this.$refs.input;
|
||
|
/* istanbul ignore if: hard to test out of sync value */
|
||
|
|
||
|
if ($input && value !== $input.value) {
|
||
|
$input.value = value;
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
onInput: function onInput(evt) {
|
||
|
// `evt.target.composing` is set by Vue
|
||
|
// https://github.com/vuejs/vue/blob/dev/src/platforms/web/runtime/directives/model.js
|
||
|
// TODO: Is this needed now with the latest Vue?
|
||
|
|
||
|
/* istanbul ignore if: hard to test composition events */
|
||
|
if (evt.target.composing) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var value = evt.target.value;
|
||
|
var formattedValue = this.formatValue(value, evt); // Exit when the `formatter` function strictly returned `false`
|
||
|
// or prevented the input event
|
||
|
|
||
|
/* istanbul ignore next */
|
||
|
|
||
|
if (formattedValue === false || evt.defaultPrevented) {
|
||
|
evt.preventDefault();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
this.localValue = formattedValue;
|
||
|
this.updateValue(formattedValue);
|
||
|
this.$emit('input', formattedValue);
|
||
|
},
|
||
|
onChange: function onChange(evt) {
|
||
|
var value = evt.target.value;
|
||
|
var formattedValue = this.formatValue(value, evt); // Exit when the `formatter` function strictly returned `false`
|
||
|
// or prevented the input event
|
||
|
|
||
|
/* istanbul ignore next */
|
||
|
|
||
|
if (formattedValue === false || evt.defaultPrevented) {
|
||
|
evt.preventDefault();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
this.localValue = formattedValue;
|
||
|
this.updateValue(formattedValue, true);
|
||
|
this.$emit('change', formattedValue);
|
||
|
},
|
||
|
onBlur: function onBlur(evt) {
|
||
|
// Apply the `localValue` on blur to prevent cursor jumps
|
||
|
// on mobile browsers (e.g. caused by autocomplete)
|
||
|
var value = evt.target.value;
|
||
|
var formattedValue = this.formatValue(value, evt, true);
|
||
|
|
||
|
if (formattedValue !== false) {
|
||
|
// We need to use the modified value here to apply the
|
||
|
// `.trim` and `.number` modifiers properly
|
||
|
this.localValue = toString(this.modifyValue(formattedValue)); // We pass the formatted value here since the `updateValue` method
|
||
|
// handles the modifiers itself
|
||
|
|
||
|
this.updateValue(formattedValue, true);
|
||
|
} // Emit native blur event
|
||
|
|
||
|
|
||
|
this.$emit('blur', evt);
|
||
|
},
|
||
|
focus: function focus() {
|
||
|
// For external handler that may want a focus method
|
||
|
if (!this.disabled) {
|
||
|
this.$el.focus();
|
||
|
}
|
||
|
},
|
||
|
blur: function blur() {
|
||
|
// For external handler that may want a blur method
|
||
|
if (!this.disabled) {
|
||
|
this.$el.blur();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|