Skip to content

Commit

Permalink
feat: 新建Cascader组件
Browse files Browse the repository at this point in the history
  • Loading branch information
HuYuee committed May 19, 2017
1 parent 38584dd commit b40e512
Show file tree
Hide file tree
Showing 13 changed files with 677 additions and 2 deletions.
2 changes: 2 additions & 0 deletions lib/index.js
Expand Up @@ -13,6 +13,7 @@ import { compMgr } from 'compox/src/compMgr';
//Neoui import //Neoui import
import { Autocomplete } from './neoui-autocomplete'; import { Autocomplete } from './neoui-autocomplete';
import { Button } from './neoui-button'; import { Button } from './neoui-button';
import { Cascader } from './neoui-cascader';
import { Checkbox } from './neoui-checkbox'; import { Checkbox } from './neoui-checkbox';
import { Combo } from './neoui-combo'; import { Combo } from './neoui-combo';
import { showCollapse } from './neoui-collapse'; import { showCollapse } from './neoui-collapse';
Expand Down Expand Up @@ -50,6 +51,7 @@ var ex = {
BaseComponent: BaseComponent, BaseComponent: BaseComponent,
Autocomplete: Autocomplete, Autocomplete: Autocomplete,
Button: Button, Button: Button,
Cascader: Cascader,
Checkbox: Checkbox, Checkbox: Checkbox,
Combo: Combo, Combo: Combo,
showCollapse: showCollapse, showCollapse: showCollapse,
Expand Down
271 changes: 271 additions & 0 deletions lib/neoui-cascader.js
@@ -0,0 +1,271 @@
/**
* Module : neoui-cascader
* Author : huyueb(huyueb@yonyou.com)
* Date : 2017-05-19 13:19:10
*/
import { closest } from 'tinper-sparrow/src/dom';
import { on, off, trigger } from 'tinper-sparrow/src/event';

var Cascader = u.BaseComponent.extend({
// 入口方法
init: function init() {
var self = this,
data = self.options['data'],
id = '';
this._data = data;
this.order = [];
this.current = [];
if (!this.options['id']) {
this.options['id'] = new Date().getTime() + '' + parseInt(Math.random() * 10 + 1, 10);
}
id = this.options['id'];

$(this.element).append('<div id="' + id + '-input" class="cascader-input" style="width:100%;height:100%;"><input/></div><div id="' + id + '" class="cascader-show"></div>');
this.focusFunc();
$(this.element).children('.cascader-input').off().on('mouseenter', function () {
var $this = $(this);
if ($this.children('input').val()) {
$this.append('<i class="icon uf uf-close-bold"></i>');
}
$this.off('mouseleave').on('mouseleave', function () {
$this.children('i').remove();
}).children('i').on('click', function () {
var $this_ = $(this);
$this_.siblings('input').val('').attr('tovalue', '').end().parent().next().html('').end().end().remove();
});
});
},
triggerChange: function triggerChange(value) {
this.trigger('change', {
value: value
});
},
setData: function setData(data) {
var self = this;
self._data = data;
},

setValue: function setValue(value) {
var self = this,
arr = value.split(',') || [],
names = '';
if (arr && arr.length > 1) {
names = self.transName(arr, self._data);
}
if (names.length > 1) {
names = names.substring(0, names.length - 1);
$(this.element).children('.cascader-input').children('input').val(names).attr('tovalue', value);
}
},
//通过设置的value值能去data中查找到对应的name值
transName: function transName(arr, data) {
var names = '',
self = this,
flag = -1;
for (var j = 0; j < data.length; j++) {
if (data[j].value == arr[0]) {
flag = j;
names += data[j].name + ',';
}
}
if (arr.length > 1) {
data = data[flag].children;
arr.shift();

names += self.transName(arr, data);
}
return names;
},

//还原之前节点的位置
transHtml: function transHtml(arr, data, index) {
var html = "",
self = this,
index = index || 0,
flag = -1;

html += "<ul col = " + index + " >";

for (var j = 0; j < data.length; j++) {
if (data[j].value == arr[0]) {
flag = j;
}

if (data[j].children) {
html += "<li class='" + (flag === j ? 'active' : '') + "' row = " + j + " value=" + data[j].value + ">" + data[j].name + "<i class='icon uf uf-arrow-right'></i></li>";
} else {
html += "<li class='" + (flag === j ? 'active' : '') + "' row = " + j + " value=" + data[j].value + ">" + data[j].name + "</li>";
}
}
html += "</ul>";
if (arr.length > 1) {
data = data[flag].children;
arr.shift();

html += self.transHtml(arr, data, ++index);
}

return html;
},
//根据传入的data来动态的生成级联组件的列表
formData: function formData(data, index, arg) {
var self = this,
data = data || self._data,
html = "",
index = index || 0,
//来记录是第几个ul,方便进行查找和删除
arr = [],
trigger_type = self.options['trigger_type'] || 'click';
//判断输入框中是否有数据
if (!arg) {
//当输入框中没有数据,就认为是第一次
if ($('#' + self.options['id'] + '>ul').length) {
$('#' + self.options['id'] + '>ul[col="' + index + '"]~').remove();
index = $('#' + self.options['id'] + '>ul').length;
}

html += "<ul col = " + index + " >";

for (var i = 0; i < data.length; i++) {
if (data[i].children) {
html += "<li row = " + i + " value=" + data[i].value + ">" + data[i].name + "<i class='icon uf uf-arrow-right'></i></li>";
} else {
html += "<li row = " + i + " value=" + data[i].value + ">" + data[i].name + "</li>";
}
}
html += "</ul>";
if ($('#' + self.options['id'] + '>ul').length) {

$('#' + self.options['id']).append(html);
} else {
$('#' + self.options['id']).append(html);
}

current = data;

index++;
} else {
//当输入框中有数据的时候,就根据输入框的数据,来显示出相应的列表
arr = arg.split(',');
html = self.transHtml(arr, data);
if ($('#' + self.options['id'] + '>ul').length) {

$('#' + self.options['id']).append(html);
} else {
$('#' + self.options['id']).append(html);
}
current = data;
index++;
}

if (trigger_type == "mouseenter") {
//当触发方式是mouseenter的时候,需要额外定义点击事件。点击则将选中的数据写入input输入框
$('#' + self.options['id'] + '>ul>li').off('click').on('click', function (e) {
var $this = $(this),
$content = $('#' + self.options['id']),
col = $this.parent().attr('col'),
text = "",
//最后选中之后的input输入框中的文字,如:"浙江,杭州"
value = ""; //最后选中之后的原始序列,如:"01,11"
$.each($content.find('li.active'), function (key, val) {
var $val = $(val);
if (key < col - -1) {
text += val.innerText + ',';
value += $val.attr('value') + ',';
}
});
text = text.substring(0, text.length - 1);
value = value.substring(0, value.length - 1);

$content.prev().children('input').val(text).attr('tovalue', value).end().end().html('');

//触发adapter层的change事件
self.triggerChange(value);
});
}

//为级联组件的列表的每个li绑定事件
$('#' + self.options['id'] + '>ul>li').off(trigger_type).on(trigger_type, function (e) {
var $this = $(this),
col = $this.parent().attr('col'),
row = $this.attr('row'),
data = self._data,
$content = $('#' + self.options['id']),
text = "",
//最后选中之后的input输入框中的文字,如:"浙江,杭州"
value = ""; //最后选中之后的原始序列,如:"01,11"

$this.siblings().removeClass('active');
$this.addClass('active');

//把超过col+1的ul砍掉,之后的就不显示了
self.order.length = col - -1;
self.order[col] = row;

for (var i = 0; i < self.order.length; i++) {
//判断此条数据是否还有子数据
if (data[self.order[i]].children) {
data = data[self.order[i]].children;
} else {

if (trigger_type != 'mouseenter') {
//当此条数据没有子数据时,并且是click方式触发,就将之前选择的数据展示到input框中
$.each($content.find('li.active'), function (key, val) {
var $val = $(val);
if (key < col - -1) {
text += val.innerText + ',';
value += $val.attr('value') + ',';
}
});
text = text.substring(0, text.length - 1);
value = value.substring(0, value.length - 1);

$content.prev().children('input').val(text).attr('tovalue', value).end().end().html('');
//触发adapter层的change事件
self.triggerChange(value);
} else {
//当此条数据没有子数据时,如果是mouseenter触发,就只是将该条列表后面的内容删掉
$this.parent().nextAll().remove();
}
return;
}
}
if (data) {
self.formData(data, col);
}
});
//当点击级联组件的之外的区域时,删除级联组件的显示
var callback = function (e) {
if (e.target === this._input || self._inputFocus == true) return;
if (closest(e.target, 'cascader-show') === self._ul || closest(e.target, 'u-cascader')) return;
off(document, 'click', callback);
$('#' + self.options['id']).html('');
}.bind(this);
this.callback = callback;
on(document, 'click', callback);
},
//当input输入框有点击事件的时候就生成级联组件的列表
focusFunc: function focusFunc() {
var self = this;
var caret = $(this.element).find('input')[0];
on(caret, 'click', function (e) {
var $this = $(this);
if (!$('#' + self.options['id']).html()) {
self.formData('', '', $this.attr('tovalue'));
}
if (e.stopPropagation) {
e.stopPropagation();
} else {
e.cancelBubble = true;
}
});
}
});

if (u.compMgr) u.compMgr.regComp({
comp: Cascader,
compAsString: 'u.cascader',
css: 'u-cascader'
});

export { Cascader };
5 changes: 3 additions & 2 deletions lib/neoui-combo.js
Expand Up @@ -395,7 +395,8 @@ var Combo = u.BaseComponent.extend({
}, },


_updateItemSelect: function _updateItemSelect() { _updateItemSelect: function _updateItemSelect() {
var lis = this._ul.querySelectorAll('.u-combo-li'); var lis = this._ul.querySelectorAll('.u-combo-li'),
val = this.value;
if (this.mutilSelect) { if (this.mutilSelect) {
var values = this.value.split(','); var values = this.value.split(',');
for (var i = 0; i < lis.length; i++) { for (var i = 0; i < lis.length; i++) {
Expand All @@ -414,7 +415,7 @@ var Combo = u.BaseComponent.extend({
}*/ }*/
} else { } else {
for (var i = 0; i < lis.length; i++) { for (var i = 0; i < lis.length; i++) {
if (this.value == this.comboDatas[i].value) { if (val != '' && val != null && typeof val != 'undefined' && val == this.comboDatas[i].value) {
addClass(lis[i], 'is-selected'); addClass(lis[i], 'is-selected');
} else { } else {
removeClass(lis[i], 'is-selected'); removeClass(lis[i], 'is-selected');
Expand Down
53 changes: 53 additions & 0 deletions scss/ui/neoui-cascader.scss
@@ -0,0 +1,53 @@
@import "../core/minxin-variables";
@import "../core/minxin-mixins";




.u-cascader {
position: relative;
display: inline-block;
.cascader-input{
i {
position: absolute;
top: 2px;
right: 2px;
cursor: pointer;
}
}
.cascader-show {
width: 1000px;
position: absolute;
ul {
display: inline-block;
border: 1px solid #ccc;
border-left: 0;
min-height: 120px;
min-width: 100px;
vertical-align: middle;
border-radius: 4px;
padding: 0px;
margin-top: 0;
li {
position: relative;
padding: 6px 6px 0px;
list-style: none;
cursor: pointer;
margin-bottom: 5px;
&:hover {
background-color: #e7f4fd;
font-weight: 700;
}
&.active{
background-color: #e7f4fd;
font-weight: 700;
}
i {
position: absolute;
right: 5px;
}
}
}
}

}
3 changes: 3 additions & 0 deletions snippets/plugin/cascader/base.md
@@ -0,0 +1,3 @@
## 级联组件

级联组件
4 changes: 4 additions & 0 deletions snippets/plugin/cascader/demo/1-base/codeWidget.html
@@ -0,0 +1,4 @@
<label class="u-checkbox">
<input type="checkbox" class="u-checkbox-input" checked>
<span class="u-checkbox-label">Checkbox</span>
</label>
17 changes: 17 additions & 0 deletions snippets/plugin/cascader/demo/1-base/widget.html
@@ -0,0 +1,17 @@

<label class="u-checkbox">
<input type="checkbox" class="u-checkbox-input" checked>
<span class="u-checkbox-label">Checkbox</span>
</label>
<label class="u-checkbox">
<input type="checkbox" class="u-checkbox-input" >
<span class="u-checkbox-label">Checkbox</span>
</label>
<label class="u-checkbox" >
<input type="checkbox" class="u-checkbox-input" disabled>
<span class="u-checkbox-label">Checkbox</span>
</label>
<label class="u-checkbox">
<input type="checkbox" class="u-checkbox-input" disabled checked>
<span class="u-checkbox-label">Checkbox</span>
</label>
5 changes: 5 additions & 0 deletions snippets/plugin/cascader/demo/1-base/说明.md
@@ -0,0 +1,5 @@
### 基础checkbox
在复选框中input元素添加如下属性来实现多种效果

- `checked` 选中
- `disabled` 不可用

0 comments on commit b40e512

Please sign in to comment.