import { utils } from './utils';
import { checkboxBooleanHandler } from './handler/checkbox-boolean-handler';
import { defaultDataHandler } from './handler/default-data-handler';
"use strict";
/* SOURCE-CODE-START */
/**
* @class
* @param {(Document|Element)} baseElement
* @param {object} [opts]
*/
function Model(baseElement, opts) {
opts = (opts || {});
var config = Model.config;
this._baseElement = baseElement;
this._dataHandlers = (opts.dataHandlers || {});
this._nameAttributeName = (opts.nameAttributeName || config.defaultNameAttributeName);
this._typeAttributeName = (opts.typeAttributeName || config.defaultTypeAttributeName);
this._initDataHandlers = config.initDataHandlers;
}
Model.config = {
defaultNameAttributeName: 'data-name',
defaultTypeAttributeName: 'data-type',
initDataHandlers: {
'default': defaultDataHandler,
'checkbox-boolean': checkboxBooleanHandler
}
};
/**
* @description 获取对应的元素
* @returns {(Document|Element)}
*/
Model.prototype.getBaseElement = function () {
return this._baseElement;
};
/**
* @description 获取指定表达式对应元素的数据
* @param {(string|string[])} expression 表达式
* @param {function} [skipFn] 判断是否跳过值,比如 (targetValue) => (targetValue == null)
* @returns {*} 值
*/
Model.prototype.getData = function (expression, skipFn) {
// 表达式只能是字符串或数组
if ((typeof expression !== 'string') && !(expression instanceof Array)) {
throw new Error('argument#0 "expression" required string or Array');
}
// 转换表达式成选择器
var selector = this.convertExpressionToSelector(expression);
// 查找指定选择器对应的元素
var elements = this.queryElementsBySelector(selector);
// 转换成数据名称和元素的映射
var elementArrays = this.groupElementsByName(elements);
// 若表达式是数组或者"*"结尾的字符串,则是获取多个元素的值
if ((expression instanceof Array)
|| (expression.charAt(expression.length - 1) === '*')) {
var elementValues = {};
for (var dataName in elementArrays) {
if (dataName === '') {
continue;
}
var elementArray = elementArrays[dataName];
// 获取元素的值
var dataValue = this.doGetDataValue(elementArray, skipFn);
if (utils.isNullOrUndefined(skipFn) || !skipFn(dataValue)) {
elementValues[dataName] = dataValue;
}
}
return elementValues;
} else {
if (elements.length <= 0) {
return null;
}
for (var dataName in elementArrays) {
if (dataName === '') {
continue;
}
var elementArray = elementArrays[dataName];
// 获取元素的值
return this.doGetDataValue(elementArray, skipFn);
}
}
};
/**
* @description 设置指定表达式对应元素的数据
* @param {string|string[]} expression 表达式
* @param {*} value 值
* @param {boolean} [notSkipSetIfValueAbsent=false] 是否跳过没有指定值的元素,默认 false 跳过没有指定值的元素
*/
Model.prototype.setData = function (expression, value, notSkipSetIfValueAbsent) {
// 表达式只能是字符串或数组
if ((typeof expression !== 'string') && !(expression instanceof Array)) {
throw new Error('argument#0 "expression" required string or Array');
}
notSkipSetIfValueAbsent = (notSkipSetIfValueAbsent === true);
// 转换表达式成选择器
var selector = this.convertExpressionToSelector(expression);
// 查找指定选择器对应的元素
var elements = this.queryElementsBySelector(selector);
// 转换成数据名称和元素的映射
var elementArrays = this.groupElementsByName(elements);
// 若表达式是数组或者"*"结尾的字符串,则是设置多个元素的值
if ((expression instanceof Array)
|| (expression.charAt(expression.length - 1) === '*')) {
value = (value || {});
for (var dataName in elementArrays) {
var elementArray = elementArrays[dataName];
var dataValue = value[dataName];
if ((dataName in value) || notSkipSetIfValueAbsent) {
// 设置元素的值
this.doSetDataValue(elementArray, dataValue, notSkipSetIfValueAbsent);
}
}
} else {
if (elements.length <= 0) {
return;
}
for (var dataName in elementArrays) {
var elementArray = elementArrays[dataName];
// 设置元素的值
this.doSetDataValue(elementArray, value, notSkipSetIfValueAbsent);
}
}
};
/**
* @description 获取元素的值
* @param {Element[]} elements DOM元素
* @param {function} [skipFn] 判断是否跳过值
* @returns {*} 值
*/
Model.prototype.doGetDataValue = function (elements, skipFn) {
if (!(elements instanceof Array)) {
throw new Error('argument#0 "elements required Array');
}
if (elements.length <= 0) {
throw new Error('argument#0 "elements is empty');
}
// 获取组件处理器
var handler = this.getDataHandlerByElement(elements[0]);
// 获取元素的值
return handler.getValue(elements, skipFn);
};
/**
* @description 设置元素的值
* @param {Element[]} elements DOM元素
* @param {*} value 值
* @param {boolean} [notSkipSetIfValueAbsent] 是否默认 null 值
*/
Model.prototype.doSetDataValue = function (elements, value, notSkipSetIfValueAbsent) {
if (!(elements instanceof Array)) {
throw new Error('argument#0 "elements required Array');
}
if (elements.length <= 0) {
throw new Error('argument#0 "elements is empty');
}
// 获取组件处理器
var handler = this.getDataHandlerByElement(elements[0]);
// 设置元素的值
handler.setValue(elements, value, (notSkipSetIfValueAbsent === true));
};
/**
* @description 获取组件处理器
* @param {Element} element DOM元素
* @returns {Object} 组件处理器
*/
Model.prototype.getDataHandlerByElement = function (element) {
if (utils.isNullOrUndefined(element)) {
throw new Error('argument#0 "element is null/undefined');
}
var handler;
var handlerName = element.getAttribute(this._typeAttributeName);
// 先获取自定义的组件处理器
if (!utils.isNullOrUndefined(handlerName)) {
handler = (this._dataHandlers[handlerName]
|| this._initDataHandlers[handlerName]);
if (utils.isNullOrUndefined(handler)) {
throw new Error('not found handler "' + handlerName + '"');
}
return handler;
}
// 如果没有自定义的处理器,则获取标签对应的处理器
var tagName = element.tagName.toLowerCase();
handlerName = '@' + tagName;
handler = (this._dataHandlers[handlerName]
|| this._initDataHandlers[handlerName]);
// 如果没有找到自定义的处理器和标签对应的处理器,则取默认处理器
if (utils.isNullOrUndefined(handler)) {
handler = (this._dataHandlers['default']
|| this._initDataHandlers['default']);
}
return handler;
};
/**
* @description 查找指定选择器对应的元素
* @param {(string|string[])} selector 选择器
* @returns {(Element[])} DOM元素
*/
Model.prototype.queryElementsBySelector = function (selector) {
// 表达式只能是字符串或数组
if ((typeof selector !== 'string') && !(selector instanceof Array)) {
throw new Error('argument#0 "selector" required string or Array');
}
var selectorStr;
if (selector instanceof Array) {
selectorStr = selector.join(',');
} else {
selectorStr = selector;
}
return this._baseElement.querySelectorAll(selectorStr);
};
/**
* @description 转换表达式成选择器
* @param {(string|string[])} expression 表达式
* @returns {string[]} 选择器数组
*/
Model.prototype.convertExpressionToSelector = function (expression) {
// 表达式只能是字符串或数组
if ((typeof expression !== 'string') && !(expression instanceof Array)) {
throw new Error('argument#0 "expression" required string or Array');
}
var selectorArray = [];
var expressionArray;
if (expression instanceof Array) {
expressionArray = expression;
} else {
expressionArray = [expression];
}
for (var index = 0; index < expressionArray.length; index++) {
var expressionStr = expressionArray[index];
if (expressionStr !== '') {
var selectorStr;
if (expressionStr === '*') {
// 表达式是"*"的情况,则匹配所有的元素
selectorStr = '[' + this._nameAttributeName + ']';
} else if (expressionStr.charAt(expressionStr.length - 1) === '*') {
// 表达式是"*"结尾的情况,则匹配指定前缀数据名称的元素
var prefixStr = expressionStr.slice(0, -1);
selectorStr = '[' + this._nameAttributeName + '^="' + prefixStr + '"]';
} else {
// 匹配指定数据名称的元素
selectorStr = '[' + this._nameAttributeName + '="' + expressionStr + '"]';
}
selectorArray.push(selectorStr);
}
}
return selectorArray;
};
/**
* @description 转换成数据名称和元素的映射
* @param {Object} elements DOM元素
* @returns {Object} 结果
*/
Model.prototype.groupElementsByName = function (elements) {
if (utils.isNullOrUndefined(elements)) {
throw new Error('argument#0 "elements is null/undefined');
}
var elementArrays = {};
for (var index = 0; index < elements.length; index++) {
var element = elements[index];
var dataName = element.getAttribute(this._nameAttributeName);
dataName = (dataName || '');
var elementArray = elementArrays[dataName];
if (utils.isNullOrUndefined(elementArray)) {
elementArray = [];
elementArrays[dataName] = elementArray;
}
elementArray.push(element);
}
return elementArrays;
};
/* SOURCE-CODE-END */
export { Model };