kdayun-compnent-develop/kdayun-compnent-pack/dist/libs/layui/lay/modules/transfer.js

484 lines
17 KiB
JavaScript
Raw Normal View History

2022-02-19 20:37:32 +08:00
/**
@Namelayui.transfer 穿梭框
@Author贤心
@LicenseMIT
*/
layui.define(['laytpl', 'form'], function (exports) {
"use strict";
var $ = layui.$
, laytpl = layui.laytpl
, form = layui.form
//模块名
, MOD_NAME = 'transfer'
//外部接口
, transfer = {
config: {}
, index: layui[MOD_NAME] ? (layui[MOD_NAME].index + 10000) : 0
//设置全局项
, set: function (options) {
var that = this;
that.config = $.extend({}, that.config, options);
return that;
}
//事件监听
, on: function (events, callback) {
return layui.onevent.call(this, MOD_NAME, events, callback);
}
}
//操作当前实例
, thisModule = function () {
var that = this
, options = that.config
, id = options.id || that.index;
thisModule.that[id] = that; //记录当前实例对象
thisModule.config[id] = options; //记录当前实例配置项
return {
config: options
//重置实例
, reload: function (options) {
that.reload.call(that, options);
}
//获取右侧数据
, getData: function () {
return that.getData.call(that);
}
}
}
//获取当前实例配置项
, getThisModuleConfig = function (id) {
var config = thisModule.config[id];
if (!config) hint.error('The ID option was not found in the ' + MOD_NAME + ' instance');
return config || null;
}
//字符常量
, ELEM = 'layui-transfer', HIDE = 'layui-hide', DISABLED = 'layui-btn-disabled', NONE = 'layui-none'
, ELEM_BOX = 'layui-transfer-box', ELEM_HEADER = 'layui-transfer-header', ELEM_SEARCH = 'layui-transfer-search', ELEM_ACTIVE = 'layui-transfer-active', ELEM_DATA = 'layui-transfer-data'
//穿梭框模板
, TPL_BOX = function (obj) {
obj = obj || {};
return ['<div class="layui-transfer-box" data-index="' + obj.index + '">'
, '<div class="layui-transfer-header">'
, '<input type="checkbox" name="' + obj.checkAllName + '" lay-filter="layTransferCheckbox" lay-type="all" lay-skin="primary" title="{{ d.data.title[' + obj.index + '] || \'list' + (obj.index + 1) + '\' }}">'
, '</div>'
, '{{# if(d.data.showSearch){ }}'
, '<div class="layui-transfer-search">'
, '<i class="layui-icon layui-icon-search"></i>'
, '<input type="input" class="layui-input" placeholder="关键词搜索">'
, '</div>'
, '{{# } }}'
, '<ul class="layui-transfer-data"></ul>'
, '</div>'].join('');
}
//主模板
, TPL_MAIN = ['<div class="layui-transfer layui-form layui-border-box" lay-filter="LAY-transfer-{{ d.index }}">'
, TPL_BOX({
index: 0
, checkAllName: 'layTransferLeftCheckAll'
})
, '<div class="layui-transfer-active">'
, '<button type="button" class="layui-btn layui-btn-sm layui-btn-primary layui-btn-disabled" data-index="0">'
, '<i class="layui-icon layui-icon-next"></i>'
, '</button>'
, '<button type="button" class="layui-btn layui-btn-sm layui-btn-primary layui-btn-disabled" data-index="1">'
, '<i class="layui-icon layui-icon-prev"></i>'
, '</button>'
, '</div>'
, TPL_BOX({
index: 1
, checkAllName: 'layTransferRightCheckAll'
})
, '</div>'].join('')
//构造器
, Class = function (options) {
var that = this;
that.index = ++transfer.index;
that.config = $.extend({}, that.config, transfer.config, options);
that.render();
};
//默认配置
Class.prototype.config = {
title: ['列表一', '列表二']
, width: 200
, height: 360
, data: [] //数据源
, value: [] //选中的数据
, showSearch: false //是否开启搜索
, id: '' //唯一索引,默认自增 index
, text: {
none: '无数据'
, searchNone: '无匹配数据'
}
};
//重载实例
Class.prototype.reload = function (options) {
var that = this;
layui.each(options, function (key, item) {
if (item.constructor === Array) delete that.config[key];
});
that.config = $.extend(true, {}, that.config, options);
that.render();
};
//渲染
Class.prototype.render = function () {
var that = this
, options = that.config;
//解析模板
var thisElem = that.elem = $(laytpl(TPL_MAIN).render({
data: options
, index: that.index //索引
}));
var othis = options.elem = $(options.elem);
if (!othis[0]) return;
//初始化属性
options.data = options.data || [];
options.value = options.value || [];
//索引
that.key = options.id || that.index;
//插入组件结构
othis.html(that.elem);
//各级容器
that.layBox = that.elem.find('.' + ELEM_BOX)
that.layHeader = that.elem.find('.' + ELEM_HEADER)
that.laySearch = that.elem.find('.' + ELEM_SEARCH)
that.layData = thisElem.find('.' + ELEM_DATA);
that.layBtn = thisElem.find('.' + ELEM_ACTIVE + ' .layui-btn');
//初始化尺寸
that.layBox.css({
width: options.width
, height: options.height
});
that.layData.css({
height: function () {
return options.height - that.layHeader.outerHeight() - that.laySearch.outerHeight() - 2
}()
});
that.renderData(); //渲染数据
that.events(); //事件
};
//渲染数据
Class.prototype.renderData = function () {
var that = this
, options = that.config;
//左右穿梭框差异数据
var arr = [{
checkName: 'layTransferLeftCheck'
, views: []
}, {
checkName: 'layTransferRightCheck'
, views: []
}];
//解析格式
that.parseData(function (item) {
//标注为 selected 的为右边的数据
var _index = item.selected ? 1 : 0
, listElem = ['<li>'
, '<input type="checkbox" name="' + arr[_index].checkName + '" lay-skin="primary" lay-filter="layTransferCheckbox" title="' + item.title + '"' + (item.disabled ? ' disabled' : '') + (item.checked ? ' checked' : '') + ' value="' + item.value + '">'
, '</li>'].join('');
arr[_index].views.push(listElem);
delete item.selected;
});
// 扩展赋值的顺序跟勾选的顺序一致
var newArr = [];
layui.each(options.value, function (index, item1) {
layui.each(arr[1].views, function (index2, item2) {
var getValue = $(item2).find('input').attr('value');
if (item1 == getValue) {
newArr.push(item2);
}
});
});
// 扩展赋值的顺序跟勾选的顺序一致 end
that.layData.eq(0).html(arr[0].views.join(''));
that.layData.eq(1).html(newArr.join(''));
that.renderCheckBtn();
}
//渲染表单
Class.prototype.renderForm = function (type) {
form.render(type, 'LAY-transfer-' + this.index);
};
//同步复选框和按钮状态
Class.prototype.renderCheckBtn = function (obj) {
var that = this
, options = that.config;
obj = obj || {};
that.layBox.each(function (_index) {
var othis = $(this)
, thisDataElem = othis.find('.' + ELEM_DATA)
, allElemCheckbox = othis.find('.' + ELEM_HEADER).find('input[type="checkbox"]')
, listElemCheckbox = thisDataElem.find('input[type="checkbox"]');
//同步复选框和按钮状态
var nums = 0
, haveChecked = false;
listElemCheckbox.each(function () {
var isHide = $(this).data('hide');
if (this.checked || this.disabled || isHide) {
nums++;
}
if (this.checked && !isHide) {
haveChecked = true;
}
});
allElemCheckbox.prop('checked', haveChecked && nums === listElemCheckbox.length); //全选复选框状态
that.layBtn.eq(_index)[haveChecked ? 'removeClass' : 'addClass'](DISABLED); //对应的按钮状态
//无数据视图
if (!obj.stopNone) {
var isNone = thisDataElem.children('li:not(.' + HIDE + ')').length
that.noneView(thisDataElem, isNone ? '' : options.text.none);
}
});
that.renderForm('checkbox');
};
//无数据视图
Class.prototype.noneView = function (thisDataElem, text) {
var createNoneElem = $('<p class="layui-none">' + (text || '') + '</p>');
if (thisDataElem.find('.' + NONE)[0]) {
thisDataElem.find('.' + NONE).remove();
}
text.replace(/\s/g, '') && thisDataElem.append(createNoneElem);
};
//同步 value 属性值
Class.prototype.setValue = function () {
var that = this
, options = that.config
, arr = [];
that.layBox.eq(1).find('.' + ELEM_DATA + ' input[type="checkbox"]').each(function () {
var isHide = $(this).data('hide');
isHide || arr.push(this.value);
});
options.value = arr;
return that;
};
//解析数据
Class.prototype.parseData = function (callback) {
var that = this
, options = that.config
, newData = [];
layui.each(options.data, function (index, item) {
//解析格式
item = (typeof options.parseData === 'function'
? options.parseData(item)
: item) || item;
newData.push(item = $.extend({}, item))
layui.each(options.value, function (index2, item2) {
if (item2 == item.value) {
item.selected = true;
}
});
callback && callback(item);
});
options.data = newData;
return that;
};
//获得右侧面板数据
Class.prototype.getData = function (value) {
var that = this
, options = that.config
, selectedData = [];
that.setValue();
layui.each(value || options.value, function (index, item) {
layui.each(options.data, function (index2, item2) {
delete item2.selected;
if (item == item2.value) {
selectedData.push(item2);
};
});
});
return selectedData;
};
//事件
Class.prototype.events = function () {
var that = this
, options = that.config;
//左右复选框
that.elem.on('click', 'input[lay-filter="layTransferCheckbox"]+', function () {
var thisElemCheckbox = $(this).prev()
, checked = thisElemCheckbox[0].checked
, thisDataElem = thisElemCheckbox.parents('.' + ELEM_BOX).eq(0).find('.' + ELEM_DATA);
if (thisElemCheckbox[0].disabled) return;
//判断是否全选
if (thisElemCheckbox.attr('lay-type') === 'all') {
if (options.limit == undefined || options.limit == 0) {
thisDataElem.find('input[type="checkbox"]').each(function () {
if (this.disabled) return;
this.checked = checked;
});
} else if (thisElemCheckbox.parent().parent().data('index') != 0) {
thisDataElem.find('input[type="checkbox"]').each(function () {
if (this.disabled) return;
this.checked = checked;
});
}
}
if (options.limit != undefined && options.limit > 0 && checked) {
var selectCount = 0;
thisDataElem.find('input[type="checkbox"]').each(function () {
if (this.checked) {
selectCount++;
}
});
var selectedCount = 0;
if (thisElemCheckbox.parent().parent().parent().data('index') == 0) {
selectedCount = thisElemCheckbox.parent().parent().parent().next('div').next('div').find('ul li').length;
}
selectCount += selectedCount;
if (options.limit < selectCount) {
thisElemCheckbox[0].checked = false;
layer.msg('最多选' + options.limit + "个", { icon: 0, time: 1500, shade: 0.3 });
}
//获取右侧数据
if (selectedCount == options.limit) {
thisElemCheckbox[0].checked = false;
layer.msg('最多选' + options.limit + "个", { icon: 0, time: 1500, shade: 0.3 });
}
}
that.renderCheckBtn({ stopNone: true });
});
//按钮事件
that.layBtn.on('click', function () {
var othis = $(this)
, _index = othis.data('index')
, thisBoxElem = that.layBox.eq(_index)
, arr = [];
if (othis.hasClass(DISABLED)) return;
that.layBox.eq(_index).each(function (_index) {
var othis = $(this)
, thisDataElem = othis.find('.' + ELEM_DATA);
thisDataElem.children('li').each(function () {
var thisList = $(this)
, thisElemCheckbox = thisList.find('input[type="checkbox"]')
, isHide = thisElemCheckbox.data('hide');
if (thisElemCheckbox[0].checked && !isHide) {
thisElemCheckbox[0].checked = false;
thisBoxElem.siblings('.' + ELEM_BOX).find('.' + ELEM_DATA).append(thisList.clone());
thisList.remove();
//记录当前穿梭的数据
arr.push(thisElemCheckbox[0].value);
}
that.setValue();
});
});
that.renderCheckBtn();
//穿梭时,如果另外一个框正在搜索,则触发匹配
var siblingInput = thisBoxElem.siblings('.' + ELEM_BOX).find('.' + ELEM_SEARCH + ' input')
siblingInput.val() === '' || siblingInput.trigger('keyup');
//穿梭时的回调
options.onchange && options.onchange(that.getData(arr), _index);
});
//搜索
that.laySearch.find('input').on('keyup', function () {
var value = this.value
, thisDataElem = $(this).parents('.' + ELEM_SEARCH).eq(0).siblings('.' + ELEM_DATA)
, thisListElem = thisDataElem.children('li');
thisListElem.each(function () {
var thisList = $(this)
, thisElemCheckbox = thisList.find('input[type="checkbox"]')
, isMatch = thisElemCheckbox[0].title.indexOf(value) !== -1;
thisList[isMatch ? 'removeClass' : 'addClass'](HIDE);
thisElemCheckbox.data('hide', isMatch ? false : true);
});
that.renderCheckBtn();
//无匹配数据视图
var isNone = thisListElem.length === thisDataElem.children('li.' + HIDE).length;
that.noneView(thisDataElem, isNone ? options.text.searchNone : '');
});
};
//记录所有实例
thisModule.that = {}; //记录所有实例对象
thisModule.config = {}; //记录所有实例配置项
//重载实例
transfer.reload = function (id, options) {
var that = thisModule.that[id];
that.reload(options);
return thisModule.call(that);
};
//获得选中的数据(右侧面板)
transfer.getData = function (id) {
var that = thisModule.that[id];
return that.getData();
};
//核心入口
transfer.render = function (options) {
var inst = new Class(options);
return thisModule.call(inst);
};
exports(MOD_NAME, transfer);
});