This commit is contained in:
wangjinlei
2023-05-18 09:42:12 +08:00
commit 6e7ee3dd44
1214 changed files with 103535 additions and 0 deletions

162
style/combobox/combobox.css Normal file
View File

@@ -0,0 +1,162 @@
.content-box {
background: #fff;
}
/*去掉input默认样式*/
.filter-box input {
background: none;
outline: none;
border: 0px;
}
/**
* selectFilter --v1.0
*
**/
.filter-disabled {
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
.filter-box {
position: relative;
padding-top: 10px;
}
.filter-box select {
display: none;
}
.filter-text {
height: 100%;
overflow: hidden;
position: relative;
cursor: pointer;
padding: 0 20px 0 10px;
background: #fff;
border: 1px solid #024393;
border-radius: 4px;
}
.filter-text input {
font-size: 14px;
}
.filter-text .filter-title {
width: 100%;
height: 26px;
line-height: 26px;
border: 0;
background-color: transparent;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
padding: 0;
cursor: pointer;
}
.filter-text[disabled="disabled"], .ui-combobox-disabled, span[disabled="disabled"]:hover {
cursor: not-allowed!important;
background-color: #fff;
}
.hide {
display: none;
}
.filter-list {
display: none;
width: 100%;
background-color: #fff;
font-size: 14px;
position: absolute;
top: 42px;
left: 0;
z-index: 99;
border: 1px solid #e6e6e6;
max-height: 180px;
overflow: auto;
}
.filter-list li.filter-null a {
color: #d2d2d2;
}
.filter-list li a {
display: block;
padding: 0 10px;
line-height: 36px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
cursor: pointer;
}
.filter-list li:hover {
background-color: #f2f2f2;
}
.filter-list li.filter-selected {
background-color: #006699;
}
.filter-list li.filter-selected a{
display: block;
color: #fff;
}
.filter-list li.filter-disabled {
background-color: #fff;
}
.filter-list li.filter-disabled a{
display: block;
color: #d2d2d2;
}
.filter-list li.filter-disabled:hover a {
cursor: not-allowed!important;
background-color: #fff;
}
.icon {
position: absolute;
}
.icon-filter-arrow {
width: 9px;
height: 6px;
background-repeat: no-repeat;
background-image: url(./icon_arrow_down.png);
background-image: image-set(url(./icon_arrow_down.png) 1x,url(./icon_arrow_down_x2.png) 2x);
background-image: -webkit-image-set(url(./icon_arrow_down.png) 1x,url(./icon_arrow_down_x2.png) 2x);
background-size: 100%;
right: 5px;
top: 10px;
transition: all .2s;
}
.icon-filter-arrow.filter-show {
transform: rotate(-180deg);
}
/*滚动条样式*/
*::-webkit-scrollbar {/*滚动条整体样式*/
width: 4px; /*高宽分别对应横竖滚动条的尺寸*/
height: 4px;
}
*::-webkit-scrollbar-thumb {/*滚动条里面小方块*/
border-radius: 5px;
-webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
background: rgba(0,0,0,0.2);
}
*::-webkit-scrollbar-track {/*滚动条里面轨道*/
-webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
border-radius: 0;
background: rgba(0,0,0,0.1);
}

342
style/combobox/combobox.js Normal file
View File

@@ -0,0 +1,342 @@
!(function($) {
var iconHtml = '<span class="icon icon-filter-arrow"></span>';
var wrapHtml = `<div class="filter-box">` +
`<div class="filter-text">` +
`</div>` +
`</div>`;
var ulHtml = `<ul class="filter-list"></ul>`;
$.widget('ui.combobox', {
options: {
/**
* @cfg {String} placeholder 为空时的提示信息
*/
placeholder: '-- Please Select --',
/**
* @cfg {Boolean} editable 是否手动输入,默认为 true
*/
editable: true,
/**
* @cfg {String} [dataTextField='name'] 数据源显示字段
*/
dataTextField: "name",
/**
* @cfg {String} [dataValueField='value'] 数据源取值字段
*/
dataValueField: "value",
/**
* @cfg {Array} [dataSource='name'] 数据源
*/
dataSource: [],
/**
* @cfg {Number} [delay=500] 延迟搜索避免过多无效搜索单位毫秒ms默认是500ms
*/
delay: 500,
/**
* @cfg {Function} [change=null] 定义改变下拉框值事件函数事件名称combobox:change
*/
change: null
},
/**
jQueryUI Widget生命周期方法生成HTML事件绑定
*/
_create: function() {
console.log('--- create ---');
// 包装节点
this.element.addClass('filter-title').attr('placeholder', this.options.placeholder);
this.element.wrap(wrapHtml);
this.element.after(iconHtml);
this.element.parent().after(ulHtml);
this.$filterText = this.element.parent();
this.$ul = this.element.parent().siblings('ul');
this.$icon = this.element.siblings('span');
// 存放输入框搜索的定时器
this.timeoutArr = [];
// 设置是否可编辑
this.setEditable(this.options.editable);
// 读取 dataSource处理数据
this._initDataSource();
// 绑定事件
this._delegateEvent();
},
/**
jQueryUI Widget生命周期方法
*/
_init: function() {
console.log('--- init ---');
},
_setOptions: function(options) {
for (var key in options) {
this._setOption(key, options[key]);
}
return this;
},
_setOption: function (key, value) {
$.Widget.prototype._setOption.apply(this, arguments);
if (key === 'editable') {
this.setEditable(value);
}
if (key === 'disabled') {
this.$filterText.attr('disabled', value);
this.element.attr('disabled', value);
this.$icon.attr('disabled', value);
}
return this;
},
setEditable: function (editable) {
editable = !!editable;
this.options.editable = editable;
if (editable) {
this.element.removeAttr('readonly');
this._on(this.element, {
'keydown': '_onKeyDown'
});
} else {
this.element.attr("readonly", true);
this._off(this.element);
}
return this;
},
_destroy: function() {
// 移除属性
this.element.removeClass('input-combobox filter-title').removeAttr('data-value')
.attr('readonly', false).val('');
// 移除 dom
this.$filterText.parent().after(this.element);
this.$filterText.parent().remove();
},
_onKeyDown: function(e) {
console.log('--- keydown ---');
var timeout = setTimeout(function(context) {
return function() {
context.timeoutArr.shift();
var inputVal = context.element.val();
if (inputVal) {
context.$ul.find('li').addClass('hide').not('.filter-disabled')
.filter(function(index, item) {
return item.firstChild.text.indexOf(inputVal) > -1;
}).removeClass('hide');
} else {
context.$ul.find('li').removeClass('hide');
}
console.log('--- delay ' + context.options.delay + 'ms search ---');
};
}(this), this.options.delay);
if (this.timeoutArr.length > 0) {
var preTimeout = this.timeoutArr.shift();
clearTimeout(preTimeout);
}
this.timeoutArr.push(timeout);
},
_initDataSource: function() {
// dataSource没有数据不处理
if (!this.options.dataSource || this.options.dataSource.length <= 0) {
this.options.dataSource = [];
return;
}
// 过滤掉 dataSource中键值对与 dataTextField、dataValueField不符合的记录
this.options.dataSource = this.options.dataSource.filter(function(currentValue, index, arr) {
return currentValue[this.options.dataTextField] != null
&& currentValue[this.options.dataValueField] != null;
}, this);
// 清空掉 item选项
this.$ul.empty();
if (this.options.dataSource && this.options.dataSource.length) {
$.each(this.options.dataSource, function (i, item) {
this._appendToUl(item);
}.bind(this));
}
},
_appendToUl: function(item) {
// 处理dataTextField的值为非字符串的问题
item[this.options.dataTextField] += "";
// 组建 item
var liHtml =
`<li data-value="#{value}" class="#{class}"><a title="#{title}">#{text}</a></li>`;
liHtml = $.fn.format(liHtml, {
value: item[this.options.dataValueField],
text: item[this.options.dataTextField],
title: item[this.options.dataTextField],
class: ((item.selected ? 'filter-selected' : '')
+ ' ' + (item.disabled ? 'filter-disabled' : '')).trim()
});
this.$ul.append(liHtml);
if (item.selected) {
// 设置 item选中
this._select(item);
}
},
_delegateEvent: function() {
// 展示/隐藏 组件内容
this.$filterText.on('click.combobox', 'input, span', function() {
if (!this.options.disabled) {
this.$ul.slideToggle(100);
this.$ul.toggleClass('filter-open');
this.$icon.toggleClass('filter-show');
}
}.bind(this));
$(this.document).on('mousedown.combobox', function(e) {
var target = e.target ? e.target : e.srcElement;
// 过滤某些元素,点击后不触发
if (target.parentNode !== this.$filterText.get(0) && target !== this.$filterText.get(0)
&& target.parentNode.parentNode !== this.$ul.get(0)) {
this.$ul.slideUp(100);
this.$ul.removeClass('filter-open');
this.$icon.removeClass('filter-show');
}
}.bind(this));
// 选择某一项内容,回显
$(this.$ul).on('click.combobox', 'li:not(.filter-disabled)', function(e) {
var currentTarget = e.currentTarget;
// 设置其选中样式
this._select({
value: $(currentTarget).attr('data-value'),
name: currentTarget.firstChild.text
});
// 隐藏选项组
this.$ul.slideToggle(100);
this.$ul.toggleClass('filter-open');
this.$icon.toggleClass('filter-show');
this.$ul.find('li').removeClass('hide');
}.bind(this));
},
/**
* @method value 取值或者赋值
* @param {String} [value] 设置值选中,为空则取控件值
* @return {String} 控件值,赋值操作则没有返回值
*/
value: function(value) {
if (arguments.length === 0) { // 取值操作
console.log('--- get value ---');
return this.$ul.find('li[class="filter-selected"]').attr('data-value');
}
// 赋值操作
console.log('--- set value ---');
var selectedItem = null;
for(var i = 0, len = this.options.dataSource.length; i < len; i++) {
var item = this.options.dataSource[i], isSelected = item.selected;
if (item[this.options.dataValueField] === value && !item.disabled) {
selectedItem = item;
break;
}
}
this._select(selectedItem);
},
_select: function(item) {
if (item) {
var value = item[this.options.dataValueField],
text = item[this.options.dataTextField];
this.element.val(text);
// 判断选择的节点是否和上一个选择的节点相同
if (this.element.attr('data-value') !== value) {
this.$ul.find('li').removeClass('filter-selected').filter(function(index, element) {
return $(element).attr('data-value') === value;
}.bind(this)).addClass('filter-selected');
this.element.attr('data-value', value);
this._trigger('change', null, {
value: value,
text: text
});
}
} else {
this.$ul.find('li').removeClass('filter-selected');
this.element.val('');
this.element.removeAttr('data-value');
this._trigger('change');
}
},
/**
* @method clear 清空选择内容
*/
clear: function() {
this._select(null);
},
/**
* @method getSelectedItem 获取被选中的项键值对
* @return 键值对
*/
getSelectedItem: function() {
console.log('--- getSelectedItem ---');
return {
value: this.element.attr('data-value'),
text: this.element.val()
}
},
/**
* @method append 向 dataSource里追加数据显示在页面上
* @param {Array} [items] 追加的内容
* @return this
*/
append: function(items) {
// 传入参数不是数组,直接返回控件对象 this
if (!(items instanceof Array)) {
return this;
}
// 过滤掉键值对与 options参数不一致的内容
items = items.filter(function(item, index) {
return item.hasOwnProperty(this.options.dataValueField)
&& item.hasOwnProperty(this.options.dataTextField);
}.bind(this));
if (items.length === 0) {
return this;
}
// 将追加的数据放入到 options里并追加到 ul元素里面
Array.prototype.push.apply(this.options.dataSource, items);
$.each(items, function(index, item) {
this._appendToUl(item);
}.bind(this));
return this;
},
/**
* @method remove 从 dataSource中移除某些项
* @param {Array} [items] 移除的内容
* @return this
*/
remove: function(items) {
// 传入参数不是数组,直接返回控件对象 this
if (!(items instanceof Array)) {
return this;
}
// 过滤掉键值对与 options参数不一致的内容
items = items.filter(function(item, index) {
return item.hasOwnProperty(this.options.dataValueField)
&& item.hasOwnProperty(this.options.dataTextField);
}.bind(this));
if (items.length === 0) {
return this;
}
// 从 options里移除并从 ul元素里面移除
$.each(items, function(index, item) {
var $target = this.$ul.find('li[data-value=' + item[this.options.dataValueField] + ']')
.find('a[title='+ item[this.options.dataTextField] +']').end().addClass('hide');
var pos = $target.prevAll().length;
this.options.dataSource.splice(pos, 1);
// 若移除的元素被选中,则需要清空选中
if ($target.hasClass('filter-selected')) {
this._select(null);
}
}.bind(this));
return this;
}
});
/**
在 jQuery的原型链上新增一个格式化函数
*/
jQuery.fn.format = function(str) {
var args = Array.prototype.slice.call(arguments, 1);
var reg = /\#{([^{}]+)}/gm;
return str.replace(reg, function(match, name, index, str) {
// 判断括号匹配的内容是否是数字
var content = Number(name);
if (content >= 0) {
return args[content];
}
// 不是数字的话,应该就是对象
var object = args[0];
if (object && object !== void(0)) {
return object[name];
}
// 未匹配到,返回空串
return '';
});
}
})(jQuery)

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 B