Files
zszq-trs/YLErpWeb/wwwroot/Scripts/fast/fastVue.base.js
T
2024-05-09 14:06:26 +08:00

585 lines
21 KiB
JavaScript

(function (window, $) {
function FastVue() {
}
FastVue.noop = function (a, b, c) { };
//解析数字,返回值:NAN或正常数字或''(输入参数为空)
FastVue.parseNumber = function (val,percent) {
switch (typeof val) {
case 'number': return val;
case 'string':
{
val = val.trim();
if (val === '') return '';
let isPercent = val.endsWith('%') || percent==true;
if (isPercent) {
val = val.replace(/%+$/, '');
if (val === '') return '';
}
if (val.endsWith('‱')) {
val = val.replace(/‱+$/, '');
if (val === '') return '';
}
let number = new Number(val);
return isPercent ? number / 100 : number;
}
default: return Number.NaN;
}
};
FastVue.extend = $.extend;
FastVue.setWidth = function (el, width) {
width && (el.style.width = typeof width === 'number' ? width + 'px' : width);
};
FastVue.getDomElement = function (el) {
if (!el) return null;
if (typeof el === 'string') {
return document.getElementById(el.startsWith('#') ? el.substring(1) : el);
}
el instanceof jQuery && (el = el[0]);
return el;
};
function Form(options) {
if (!(this instanceof Form)) {
throw 'FastVue.Form is a constructor and should be called with the `new` keyword';
}
this.data = {};
this.layout = {
display: 'inline',
title: {
width: 100
},
input: {
width: '165px'
}
};
this.submit = {
url: '',
before() { },
after() { }
};
this.fields = {};
this.view = {};
this.init(options);
}
FastVue.Form = Form;
window.FastVue = FastVue;
}(window, jQuery));
//autocomplete
(function (window, $) {
function __resetLookup(options, context) {
if (options.lookupFn) {
let lookupFn = options.lookupFn;
return options.lookup = function (query, callback) {
let queryLowerCase = (query || '').toLowerCase();
let suggestions = lookupFn.call(context) || [];
if (queryLowerCase) {
if (options.searchField) {
suggestions = suggestions.filter(data => {
return options.searchField.some(x => (data[x] || '').toLowerCase().indexOf(queryLowerCase) !== -1);
});
} else {
suggestions = suggestions.filter(data => {
return (data[options.valueField] || '').toLowerCase().indexOf(queryLowerCase) !== -1;
});
}
}
if (typeof suggestions[0] !== 'object') {
suggestions = suggestions.map(x => new Object({ value: x, data: x }));
} else {
suggestions = suggestions ? suggestions.map(x => {
return { value: x[options.nameField], data: x };
}) : [];
}
callback({ suggestions: suggestions });
};
}
if (!options.lookup) return;
if (typeof options.lookup === 'function') {
let lookupFn = options.lookup;
return options.lookup = function (query, callback) {
let queryLowerCase = (query || '').toLowerCase();
let suggestions = lookupFn.call(context, queryLowerCase) || [];
if (typeof suggestions[0] !== 'object') {
suggestions = suggestions.map(x => new Object({ value: x, data: x }));
} else {
suggestions = suggestions.map(x => {
return { value: x[options.nameField], data: x };
});
}
callback({ suggestions: suggestions });
};
}
if (Array.isArray(options.lookup)) {
let lookup = options.lookup;
if (typeof lookup[0] !== 'object') {
return options.lookup = lookup.map(x => new Object({ value: x, data: x }));
}
options.lookup = lookup.map(x => {
return { value: x[options.nameField], data: x };
});
if (options.searchField) {
options.lookupFilter = function (suggestion, originalQuery, queryLowerCase) {
return options.searchField.some(x => (suggestion.data[x] || '').toLowerCase().indexOf(queryLowerCase) !== -1);
};
} else {
options.lookupFilter = function (suggestion, originalQuery, queryLowerCase) {
return (suggestion.value || '').toLowerCase().indexOf(queryLowerCase) !== -1;
};
}
} else {
throw '[autocomplete.lookup]必须为数组或函数';
}
}
FastVue.autocomplete = function (el, options, context) {
!context && (context = this);
el = FastVue.getDomElement(el)
if (!el) throw '[FastVue.autocomplete]el is null or undefined:' + (options ? options.debugInfo : '');
let _el = el;//_el对应nameField
options = Object.assign({ minChars: 0, autoSelectFirst: true }, options);
!options.valueField && (options.valueField = options.nameField || 'value');
!options.nameField && (options.nameField = options.valueField);
if (options.nameField !== options.valueField) {
_el = el.cloneNode(true);
_el.setAttribute('name', '');
_el.setAttribute('value', '');
_el.id && _el.setAttribute('id', _el.id + '_auto');
el.setAttribute('type', 'hidden');
if (!el.parentNode) {
document.createElement("div").append(el);
}
el.parentNode.insertBefore(_el, el);
el.dataset.autocompleteClone = _el;
}
__resetLookup(options, context);
const onSelectFn = options.onSelect;
options.onSelect = function (suggestion) {
_el.dataset.select = '1';
if (options.nameField !== options.valueField) {
el.value = suggestion.data[options.valueField];
}
onSelectFn && onSelectFn(suggestion.data);
};
$(_el).autocomplete('dispose');
$(_el).on('focus', function () {
this.setAttribute("placeholder", this.value);
this.value = '';
this.dataset.select = '';
}).on('blur', function () {
!this.dataset.select && (this.value = this.getAttribute("placeholder"));
this.setAttribute("placeholder", '');
}).on('keydown', function (event) {
if ((event.which || event.keyCode) === 13) {
event.preventDefault();
event.stopPropagation();
$(this).blur();
}
}).autocomplete(options);
return {
setData(data) {
if (options.nameField === options.valueField) {
_el.value = (typeof data === 'object' ? data[options.nameField] : data) || '';
} else if (data) {
el.value = data[options.valueField] || '';
_el.value = data[options.nameField] || '';
} else {
_el.value = el.value = '';
}
},
dispose() {
$(_el).autocomplete('dispose');
$(_el).remove();
},
toggleDisabled(disabled) {
_el.disabled = typeof disabled === 'undefined' ? !_el.disabled : !!disabled;
},
clearCache() {
$(_el).autocomplete('clearCache');
},
setOptions(newOptions) {
$(_el).autocomplete('setOptions', Object.assign({}, options, newOptions));
}
};
};
//静态dispose方法
FastVue.autocomplete.dispose = function (el) {
(el instanceof jQuery) && (el = el.get(0));
if (!el) return;
$(el).autocomplete('dispose');
el.dataset && $(el.dataset.autocompleteClone).autocomplete('dispose');
};
}(FastVue, jQuery));
//numberInput
(function (window, $) {
FastVue.numberInput = function (el, options) {
let _el = typeof el === 'string' ? document.getElementById(el.replace(/^#/, '')) : el instanceof jQuery ? el[0] : el;
if (!_el) {
throw "[FastVue.numberInput]not found el:" + el;
}
let _ctrlV = false, _chnInput = -1;
let _options = { append: '', precision: 2, negative: false, grouping: false };
function getValue() {
let val = _el.value;
if (val && val !== _options.append) {
_options.append && _options.append !== '%' && _options.append !== '‱' && (val = val.replace(new RegExp(_options.append + "$"), ''));
return FastVue.parseNumber(val, _options.percent);
}
return '';
}
function setOptions(options) {
options = Object.assign(_options, options);
!options.append && (options.append = '');
let precision = parseInt(options.precision) || 0;
options.precision = precision < 0 ? 0 : precision;
options.negative = !!options.negative;
_options = options;
setValue(getValue());
}
function setValue(value) {
if (value || value === 0) {
let oval = parseFloat(value) || 0;
if (_options.append === '%' || _options.percent == true) {
oval *= 100;
}
else if (_options.append ==="‱") {
oval *= 10000;
}
if (_options.precision > 0) {
let str = main.formatNumber(oval, _options.precision, { grouping: _options.grouping });
if (typeof value === 'number' && str.endsWith("0") && str.includes('.')) {
str = str.replace(/\.?0+$/, '');
}
_el.value = str + _options.append;
} else {
let str = main.formatNumber(Math.floor(oval), 0, { grouping: _options.grouping });
_el.value = str + _options.append;
}
} else {
_el.value = '';
}
}
function checkDotInput() {
if (this.selectionStart >= this.value.length) {
return _options.append && this.value.endsWith(_options.append) ? false : this.value.indexOf('.') < 0;
}
if (this.value.length - _options.append.length - this.selectionEnd > _options.precision) {
return false;
}
return this.value.substring(0, this.selectionStart).indexOf('.') < 0 && this.value.substring(this.selectionEnd, this.value.length).indexOf('.') < 0;
}
function __keyHandle(event) {
if (!event) return false;
_chnInput = -1;
let charCode = event.which || event.keyCode;
switch (charCode) {
case 8: //break space
return !_options.append || !this.value.endsWith(_options.append) || this.selectionStart < this.value.length - _options.append.length + 1;
case 9: //tab
case 35: //end
case 36: //home
case 37: //left arrow
case 39: //right arrow
case 42: //print
case 116: //F5
return true;
case 46: //del
return !_options.append || !this.value.endsWith(_options.append) || this.selectionStart < this.value.length - _options.append.length;
case 229:
return _chnInput = this.selectionStart;
}
if (event.shiftKey) return false;
switch (charCode) {
case 109: //negative sign(-)
return _options.negative && this.selectionStart < 1 && this.value.charAt(0) !== '-';
case 189: //negative sign(-_)
return _options.negative && !event.shiftKey && this.selectionStart < 1 && this.value.charAt(0) !== '-';
case 110: //dot(.)
return _options.precision > 0 && checkDotInput.call(this);
case 190: //dot(.>)
return _options.precision > 0 && !event.shiftKey && checkDotInput.call(this);
case 13: //enter
case 108: //enter
$(this).blur();
return true;
case 67: //ctrl+c
return event.ctrlKey;
case 86: //ctrl+v
return event.ctrlKey && (_ctrlV = true);
default:
if (charCode < 48 || charCode > 57 && (charCode < 96 || charCode > 105)) {
return false;
}
if (this.selectionStart === 0) {
return !this.value || this.value.charAt(this.selectionEnd) !== '-';
}
if (_options.precision < 1) {
return true;
}
if (this.selectionStart >= this.value.length && _options.append && this.value.endsWith(_options.append)) {
return false;
}
if (this.selectionEnd > this.selectionStart) {
return /\d/.test(this.value.substring(this.selectionStart, this.selectionEnd));
} else {
let dotIndex = this.value.lastIndexOf('.', this.selectionStart - 1);
return dotIndex < 0 || !/\d/.test(this.value[dotIndex + _options.precision]);
}
}
}
//处理中文字符输入
function __onChineseInput(chnPos) {
if (this.value.length < chnPos) {
chnPos = this.value.length - 1;
}
let ch = this.value.charCodeAt(chnPos);
if (ch > 47 && ch < 58) {
chnPos += 1;
}
else if (ch === 46 || ch === 12290) {
if (_options.precision > 0 && !/\d/.test(this.value[this.selectionStart + _options.precision])
&& this.value.lastIndexOf('.', chnPos - 1) < 0 && this.value.indexOf('.', this.selectionStart) < 0) {
if (ch === 12290) {
this.value = this.value.substring(0, chnPos) + '.' + this.value.substring(this.selectionStart);
this.setSelectionRange(chnPos + 1, chnPos + 1);
return;
}
chnPos += 1;
}
}
else if (chnPos === 0 && ch === 45 && _options.negative && this.value[this.selectionStart] !== '-') { //负号
return;
} else {
for (; chnPos >= 0; chnPos--) {
ch = this.value.charCodeAt(chnPos);
if (ch === 46 || ch > 47 && ch < 58 || chnPos === 0 && ch === 45 && _options.negative) {
chnPos += 1;
break;
}
}
}
this.value = this.value.substring(0, chnPos) + this.value.substring(this.selectionStart);
this.setSelectionRange(chnPos, chnPos);
}
//处理字符输入
function __onInput() {
if (_ctrlV) {
_ctrlV = false;
return setValue(this.value);
}
if (_chnInput >= 0) {
__onChineseInput.call(this, _chnInput);
}
if (!_options.append || !this.value) return;
let appended = true;
if (this.value !== _options.append) {
appended = this.value.endsWith(_options.append);
}
if (!appended) {
let caretPos = this.selectionStart;
this.value += _options.append;
this.setSelectionRange(caretPos, caretPos);
} else if (_options.negative && this.selectionStart === 2 && this.value[1] === '-') {
this.value = this.value.substring(1);
this.setSelectionRange(1, 1);
}
}
//输入完成处理
function __change() {
let f = '';
if (this.value && this.value !== _options.append) {
f = parseFloat(this.value.replaceAll(",", "")) || 0;
if (_options.append === '%' || _options.percent == true) f /= 100;
else if (_options.append === '‱') f /= 10000;
}
_options.onchange && _options.onchange(f, this.value);
}
//功能禁用
function __disable() {
return false;
}
setOptions(options);
$(_el).on('keydown', __keyHandle).on('dragenter', __disable).on('input', __onInput).on('change', __change);
return {
isEmpty() {
return !_el.value || _el.value === _options.append;
},
getValue: getValue,
setValue: setValue,
setOptions: setOptions,
getOptions() {
return Object.assign({}, _options);
},
dispose() {
$(_el).off();
}
};
};
//静态dispose方法
FastVue.numberInput.dispose = function (el) {
(el instanceof jQuery ? el : $(el)).off();
};
}(FastVue, jQuery));
//FastVue.vueNumberInput
//数字输入组件(借助FastVue.numberInput)
(function (global) {
global.vueNumberInput = function () {
return {
props: {
value: {
type: Number,
default: ''
},
format: {
type: Object,
default: {
append: '',
precision: 2,
negative: false,
grouping: false,
percent: false
}
},
disabled: {
type: Boolean
},
ret_type: {
type: Number,
default: 0
}
},
data() {
return { inputctrl: null,init:true};
},
mounted() {
let self = this;
let options = FastVue.extend({ onchange: this.onchange }, this.format);
this.inputctrl = FastVue.numberInput(this.$el, options);
this.inputctrl.setValue(this.value)
},
methods: {
onchange(value, text) {
this.init = false;
this.$emit('input', this.ret_type === 1 ? text : value);
}
},
watch: {
value(val, old) {
let val1 = '';
switch (typeof val) {
case 'number':
val1 = val || 0; break;
case 'string':
if (val) {
val1 = parseFloat(val) || 0;
if (val1 && (val.trimEnd().endsWith('%') || (this.format.percent && !this.init))) {
val1 /= 100;
} else if (val1 && (val.trimEnd().endsWith('‱'))){
val1 /= 10000;
}
}
break;
}
if (!this.inputctrl.isEmpty()) {
let val2 = this.inputctrl.getValue();
if (Math.abs(val1 - val2) < 1e-10) return;
}
this.$nextTick(function () {
this.inputctrl.setValue(val1);
});
},
format: {
deep: true,
handler(val) {
this.inputctrl.setOptions(val);
this.$nextTick(function () {
this.inputctrl.setValue(this.value);
});
}
}
},
destroyed() {
FastVue.numberInput.dispose(this.$el);
},
template: '<input type="text" v-bind:disabled="disabled">'
};
};
}(window.FastVue));