Merge remote-tracking branch 'eleme/dev' into es-doc

# Conflicts:
#	examples/app.vue
pull/8230/head
Leopoldthecoder 2017-11-13 17:32:12 +08:00
commit de86b737e3
41 changed files with 655 additions and 125 deletions

View File

@ -6,7 +6,7 @@
"expect": true,
"sinon": true
},
"plugins": ['vue'],
"plugins": ['vue','json'],
"extends": 'elemefe',
"parserOptions": {
"ecmaFeatures": {

View File

@ -1,5 +1,15 @@
## Changelog
### 2.0.4
*2017-11-10*
- Improved accessibility for Cascader, Dropdown, Message, Notification, Popover, Tooltip and Tree
- Fixed Container resize when the width of viewport decreases, #8042
- Fixed Tree's `updateKeyChildren` incorrectly deleting child nodes, #8100
- Fixed bordered CheckboxButton's height when nested in a Form, #8100
- Fixed Menu's parsing error for custom colors, #8153 (by @zhouyixiang)
### 2.0.3
*2017-11-03*

View File

@ -1,5 +1,15 @@
## 更新日志
### 2.0.4
*2017-11-10*
- 提升 Cascader、Dropdown、Message、Notification、Popover、Tooltip、Tree 的可访问性
- 修复当视口变窄时 Container 无法同步更新其宽度的问题,#8042
- 修复 Tree 的 `updateKeyChildren` 在删除子节点时的行为错误,#8100
- 修复带有边框的 CheckboxButton 在 Form 中高度错误的问题,#8100
- 修复 Menu 在解析自定义颜色时的错误,#8153by @zhouyixiang
### 2.0.3
*2017-11-03*

View File

@ -191,7 +191,6 @@
const lang = location.hash.replace('#', '').split('/')[1] || 'zh-CN';
const localize = lang => {
console.log(lang);
switch (lang) {
case 'zh-CN':
use(zhLocale);
@ -232,6 +231,7 @@
const preferGithub = localStorage.getItem('PREFER_GITHUB');
if (href.indexOf('element-cn') > -1 || preferGithub) return;
setTimeout(() => {
if (this.lang !== 'zh-CN') return;
this.$confirm('建议大陆用户访问部署在国内的站点,是否跳转?', '提示')
.then(() => {
location.href = location.href.replace('element.', 'element-cn.');
@ -249,12 +249,12 @@
this.suggestJump();
}
setTimeout(() => {
const notified = localStorage.getItem('RELEASE_NOTIFIED');
if (!notified) {
const notified = localStorage.getItem('ES_NOTIFIED');
if (!notified && this.lang !== 'zh-CN') {
const h = this.$createElement;
const title = this.lang === 'zh-CN'
? '2.0 正式发布'
: '2.0 available now';
? '帮助我们完成西班牙语文档'
: 'Help us with Spanish docs';
const messages = this.lang === 'zh-CN'
? ['点击', '这里', '查看详情']
: ['Click ', 'here', ' to learn more'];
@ -266,13 +266,13 @@
h('a', {
attrs: {
target: '_blank',
href: `https://github.com/ElemeFE/element/issues/${ this.lang === 'zh-CN' ? '7755' : '7756' }`
href: 'https://github.com/ElemeFE/element/issues/8074'
}
}, messages[1]),
messages[2]
]),
onClose() {
localStorage.setItem('RELEASE_NOTIFIED', 1);
localStorage.setItem('ES_NOTIFIED', 1);
}
});
}

View File

@ -101,6 +101,7 @@
value8: '',
value9: [],
value10: [],
value11: [],
loading: false,
states: ["Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "Delaware", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming"]
};
@ -320,7 +321,7 @@ You can clear Select using a clear icon.
Multiple select uses tags to display selected options.
:::demo Set `multiple` attribute for `el-select` to enable multiple mode. In this case, the value of `v-model` will be an array of selected options.
:::demo Set `multiple` attribute for `el-select` to enable multiple mode. In this case, the value of `v-model` will be an array of selected options. By default the selected options will be displayed as Tags. You can collapse them to a text by using `collapse-tags` attribute.
```html
<template>
<el-select v-model="value5" multiple placeholder="Select">
@ -331,6 +332,20 @@ Multiple select uses tags to display selected options.
:value="item.value">
</el-option>
</el-select>
<el-select
v-model="value11"
multiple
collapse-tags
style="margin-left: 20px;"
placeholder="Select">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</template>
<script>
@ -650,6 +665,7 @@ If the binding value of Select is an object, make sure to assign `value-key` as
| value-key | unique identity key name for value, required when value is an object | string | — | value |
| size | size of Input | string | large/small/mini | — |
| clearable | whether single select can be cleared | boolean | — | false |
| collapse-tags | whether to collapse tags to a text when multiple selecting | boolean | — | false |
| multiple-limit | maximum number of options user can select when `multiple` is `true`. No limit when set to 0 | number | — | 0 |
| name | the name attribute of select input | string | — | — |
| placeholder | placeholder | string | — | Select |

View File

@ -101,6 +101,7 @@
value8: '',
value9: '',
value10: [],
value11: [],
loading: false,
states: ["Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "Delaware", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming"]
};
@ -319,7 +320,7 @@
适用性较广的基础多选,用 Tag 展示已选项
:::demo 为`el-select`设置`multiple`属性即可启用多选,此时`v-model`的值为当前选中值所组成的数组
:::demo 为`el-select`设置`multiple`属性即可启用多选,此时`v-model`的值为当前选中值所组成的数组。默认情况下选中值会以 Tag 的形式展现,你也可以设置`collapse-tags`属性将它们合并为一段文字。
```html
<template>
<el-select v-model="value5" multiple placeholder="请选择">
@ -330,6 +331,20 @@
:value="item.value">
</el-option>
</el-select>
<el-select
v-model="value11"
multiple
collapse-tags
style="margin-left: 20px;"
placeholder="请选择">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</template>
<script>
@ -645,6 +660,7 @@
| value-key | 作为 value 唯一标识的键名,绑定值为对象类型时必填 | string | — | value |
| size | 输入框尺寸 | string | large/small/mini | — |
| clearable | 单选时是否可以清空选项 | boolean | — | false |
| collapse-tags | 多选时是否将选中值按文字的形式展示 | boolean | — | false |
| multiple-limit | 多选时用户最多可以选择的项目数,为 0 则不限制 | number | — | 0 |
| name | select input 的 name 属性 | string | — | — |
| placeholder | 占位符 | string | — | 请选择 |

View File

@ -10,7 +10,7 @@
},
{
"name": "Element Angular",
"href": "https://eleme.github.io/element-angular/"
"href": "https://element-angular.faas.ele.me/"
},
{
"name": "开发指南",
@ -260,7 +260,7 @@
},
{
"name": "Element Angular",
"href": "https://eleme.github.io/element-angular/"
"href": "https://element-angular.faas.ele.me/"
},
{
"name": "Development",

View File

@ -1 +1 @@
{"1.0.9":"1.0","1.1.6":"1.1","1.2.9":"1.2","1.3.7":"1.3","1.4.9":"1.4","2.0.3":"2.0"}
{"1.0.9":"1.0","1.1.6":"1.1","1.2.9":"1.2","1.3.7":"1.3","1.4.9":"1.4","2.0.4":"2.0"}

View File

@ -1,6 +1,6 @@
{
"name": "element-ui",
"version": "2.0.3",
"version": "2.0.4",
"description": "A Component Library for Vue.js.",
"main": "lib/element-ui.common.js",
"files": [
@ -82,6 +82,7 @@
"css-loader": "^0.28.7",
"es6-promise": "^4.0.5",
"eslint": "^3.10.2",
"eslint-plugin-json": "^1.2.0",
"extract-text-webpack-plugin": "^3.0.1",
"file-loader": "^1.1.5",
"file-save": "^0.2.0",

View File

@ -10,9 +10,12 @@
]"
@click="handleClick"
@mouseenter="inputHover = true"
@focus="inputHover = true"
@mouseleave="inputHover = false"
@blur="inputHover = false"
ref="reference"
v-clickoutside="handleClickoutside"
@keydown="handleKeydown"
>
<el-input
ref="input"
@ -63,6 +66,7 @@ import emitter from 'element-ui/src/mixins/emitter';
import Locale from 'element-ui/src/mixins/locale';
import { t } from 'element-ui/src/locale';
import debounce from 'throttle-debounce/debounce';
import { generateId } from 'element-ui/src/utils/util';
const popperMixin = {
props: {
@ -149,6 +153,10 @@ export default {
beforeFilter: {
type: Function,
default: () => (() => {})
},
hoverThreshold: {
type: Number,
default: 500
}
},
@ -191,11 +199,15 @@ export default {
},
cascaderSize() {
return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
},
id() {
return generateId();
}
},
watch: {
menuVisible(value) {
this.$refs.input.$refs.input.setAttribute('aria-expanded', value);
value ? this.showMenu() : this.hideMenu();
},
value(value) {
@ -204,6 +216,10 @@ export default {
currentValue(value) {
this.dispatch('ElFormItem', 'el.form.change', [value]);
},
currentLabels(value) {
const inputLabel = this.showAllLevels ? value.join('/') : value[value.length - 1] ;
this.$refs.input.$refs.input.setAttribute('value', inputLabel);
},
options: {
deep: true,
handler(value) {
@ -224,10 +240,13 @@ export default {
this.menu.expandTrigger = this.expandTrigger;
this.menu.changeOnSelect = this.changeOnSelect;
this.menu.popperClass = this.popperClass;
this.menu.hoverThreshold = this.hoverThreshold;
this.popperElm = this.menu.$el;
this.menu.$refs.menus[0].setAttribute('id', `cascader-menu-${this.id}`);
this.menu.$on('pick', this.handlePick);
this.menu.$on('activeItemChange', this.handleActiveItemChange);
this.menu.$on('menuLeave', this.doDestroy);
this.menu.$on('closeInside', this.handleClickoutside);
},
showMenu() {
if (!this.menu) {
@ -245,6 +264,7 @@ export default {
hideMenu() {
this.inputValue = '';
this.menu.visible = false;
this.$refs.input.focus();
},
handleActiveItemChange(value) {
this.$nextTick(_ => {
@ -252,6 +272,23 @@ export default {
});
this.$emit('active-item-change', value);
},
handleKeydown(e) {
const keyCode = e.keyCode;
if (keyCode === 13) {
this.handleClick();
} else if (keyCode === 40) { // down
this.menuVisible = true; //
setTimeout(() => {
const firstMenu = this.popperElm.querySelectorAll('.el-cascader-menu')[0];
firstMenu.querySelectorAll("[tabindex='-1']")[0].focus();
});
e.stopPropagation();
e.preventDefault();
} else if (keyCode === 27 || keyCode === 9) { // esc tab
this.inputValue = '';
if (this.menu) this.menu.visible = false;
}
},
handlePick(value, close = true) {
this.currentValue = value;
this.$emit('input', value);

View File

@ -1,6 +1,7 @@
<script>
import { isDef } from 'element-ui/src/utils/shared';
import scrollIntoView from 'element-ui/src/utils/scroll-into-view';
import { generateId } from 'element-ui/src/utils/util';
const copyArray = (arr, props) => {
if (!arr || !Array.isArray(arr) || !props) return arr;
@ -39,7 +40,8 @@
value: [],
expandTrigger: 'click',
changeOnSelect: false,
popperClass: ''
popperClass: '',
hoverTimer: 0
};
},
@ -94,6 +96,9 @@
formatOptions(optionsCopy);
return loadActiveOptions(optionsCopy);
}
},
id() {
return generateId();
}
},
@ -135,11 +140,41 @@
activeOptions,
visible,
expandTrigger,
popperClass
popperClass,
hoverThreshold
} = this;
let itemId = null;
let itemIndex = 0;
let hoverMenuRefs = {};
const hoverMenuHandler = e => {
const offsetX = e.offsetX;
const width = hoverMenuRefs.activeMenu.offsetWidth;
const height = hoverMenuRefs.activeMenu.offsetHeight;
if (e.target === hoverMenuRefs.activeItem) {
clearTimeout(this.hoverTimer);
const {activeItem} = hoverMenuRefs;
const offsetY_top = activeItem.offsetTop;
const offsetY_Bottom = offsetY_top + activeItem.offsetHeight;
hoverMenuRefs.hoverZone.innerHTML = `
<path style="pointer-events: auto;" fill="transparent" d="M${offsetX} ${offsetY_top} L${width} 0 V${offsetY_top} Z" />
<path style="pointer-events: auto;" fill="transparent" d="M${offsetX} ${offsetY_Bottom} L${width} ${height} V${offsetY_Bottom} Z" />
`;
} else {
if (!this.hoverTimer) {
this.hoverTimer = setTimeout(() => {
hoverMenuRefs.hoverZone.innerHTML = '';
}, hoverThreshold);
}
}
};
const menus = this._l(activeOptions, (menu, menuIndex) => {
let isFlat = false;
const menuId = `menu-${this.id}-${ menuIndex}`;
const ownsId = `menu-${this.id}-${ menuIndex + 1 }`;
const items = this._l(menu, item => {
const events = {
on: {}
@ -148,12 +183,52 @@
if (item.__IS__FLAT__OPTIONS) isFlat = true;
if (!item.disabled) {
// keydown up/down/left/right/enter
events.on.keydown = (ev) => {
const keyCode = ev.keyCode;
if (![37, 38, 39, 40, 13, 9, 27].indexOf(keyCode) > -1) {
return;
}
const currentEle = ev.target;
const parentEle = this.$refs.menus[menuIndex];
const menuItemList = parentEle.querySelectorAll("[tabindex='-1']");
const currentIndex = Array.prototype.indexOf.call(menuItemList, currentEle); //
let nextIndex, nextMenu;
if ([38, 40].indexOf(keyCode) > -1) {
if (keyCode === 38) { // up
nextIndex = currentIndex !== 0 ? (currentIndex - 1) : currentIndex;
} else if (keyCode === 40) { // down
nextIndex = currentIndex !== (menuItemList.length - 1) ? currentIndex + 1 : currentIndex;
}
menuItemList[nextIndex].focus();
} else if (keyCode === 37) { // left
if (menuIndex !== 0) {
const previousMenu = this.$refs.menus[menuIndex - 1];
previousMenu.querySelector('[aria-expanded=true]').focus();
}
} else if (keyCode === 39) { // right
if (item.children) {
// menu menumenuitem
nextMenu = this.$refs.menus[menuIndex + 1];
nextMenu.querySelectorAll("[tabindex='-1']")[0].focus();
}
} else if (keyCode === 13) {
if (!item.children) {
const id = currentEle.getAttribute('id');
parentEle.setAttribute('aria-activedescendant', id);
this.select(item, menuIndex);
this.$nextTick(() => this.scrollMenu(this.$refs.menus[menuIndex]));
}
} else if (keyCode === 9 || keyCode === 27) { // esc tab
this.$emit('closeInside');
}
};
if (item.children) {
let triggerEvent = {
click: 'click',
hover: 'mouseenter'
}[expandTrigger];
events.on[triggerEvent] = () => {
events.on[triggerEvent] = events.on['focus'] = () => { // focus
this.activeItem(item, menuIndex);
this.$nextTick(() => {
// adjust self and next level
@ -168,7 +243,10 @@
};
}
}
if (!item.disabled && !item.children) { // no children set id
itemId = `${menuId}-${itemIndex}`;
itemIndex++;
}
return (
<li
class={{
@ -177,7 +255,14 @@
'is-active': item.value === activeValue[menuIndex],
'is-disabled': item.disabled
}}
ref={item.value === activeValue[menuIndex] ? 'activeItem' : null}
{...events}
tabindex= { item.disabled ? null : -1 }
role="menuitem"
aria-haspopup={ !!item.children }
aria-expanded={ item.value === activeValue[menuIndex] }
id = { itemId }
aria-owns = { !item.children ? null : ownsId }
>
{item.label}
</li>
@ -188,19 +273,68 @@
menuStyle.minWidth = this.inputWidth + 'px';
}
const isHoveredMenu = expandTrigger === 'hover' && activeValue.length - 1 === menuIndex;
const hoverMenuEvent = {
on: {
}
};
if (isHoveredMenu) {
hoverMenuEvent.on.mousemove = hoverMenuHandler;
menuStyle.position = 'relative';
}
return (
<ul
class={{
'el-cascader-menu': true,
'el-cascader-menu--flexible': isFlat
}}
{...hoverMenuEvent}
style={menuStyle}
refInFor
ref="menus">
ref="menus"
role="menu"
id = { menuId }
>
{items}
{
isHoveredMenu
? (<svg
ref="hoverZone"
style={{
position: 'absolute',
top: 0,
height: '100%',
width: '100%',
left: 0,
pointerEvents: 'none'
}}
></svg>) : null
}
</ul>
);
});
if (expandTrigger === 'hover') {
this.$nextTick(() => {
const activeItem = this.$refs.activeItem;
if (activeItem) {
const activeMenu = activeItem.parentElement;
const hoverZone = this.$refs.hoverZone;
hoverMenuRefs = {
activeMenu,
activeItem,
hoverZone
};
} else {
hoverMenuRefs = {};
}
});
}
return (
<transition name="el-zoom-in-top" on-before-enter={this.handleMenuEnter} on-after-leave={this.handleMenuLeave}>
<div

View File

@ -6,6 +6,8 @@
'el-dropdown-menu__item--divided': divided
}"
@click="handleClick"
:aria-disabled="disabled"
:tabindex="disabled ? null : -1"
>
<slot></slot>
</li>

View File

@ -4,6 +4,7 @@
import Migrating from 'element-ui/src/mixins/migrating';
import ElButton from 'element-ui/packages/button';
import ElButtonGroup from 'element-ui/packages/button-group';
import { generateId } from 'element-ui/src/utils/util';
export default {
name: 'ElDropdown',
@ -61,25 +62,43 @@
return {
timeout: null,
visible: false,
triggerElm: null
triggerElm: null,
menuItems: null,
menuItemsArray: null,
dropdownElm: null,
focusing: false
};
},
computed: {
dropdownSize() {
return this.size || (this.$ELEMENT || {}).size;
},
listId() {
return `dropdown-menu-${generateId()}`;
}
},
mounted() {
this.$on('menu-item-click', this.handleMenuItemClick);
this.initEvent();
this.initAria();
},
watch: {
visible(val) {
this.broadcast('ElDropdownMenu', 'visible', val);
this.$emit('visible-change', val);
},
focusing(val) {
const selfDefine = this.$el.querySelector('.el-dropdown-selfdefine');
if (selfDefine) { //
if (val) {
selfDefine.className += ' focusing';
} else {
selfDefine.className = selfDefine.className.replace('focusing', '');
}
}
}
},
@ -100,6 +119,8 @@
},
hide() {
if (this.triggerElm.disabled) return;
this.removeTabindex();
this.resetTabindex(this.triggerElm);
clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
this.visible = false;
@ -109,18 +130,98 @@
if (this.triggerElm.disabled) return;
this.visible = !this.visible;
},
handleTriggerKeyDown(ev) {
const keyCode = ev.keyCode;
if ([38, 40].indexOf(keyCode) > -1) { // up/down
this.removeTabindex();
this.resetTabindex(this.menuItems[0]);
this.menuItems[0].focus();
ev.preventDefault();
ev.stopPropagation();
} else if (keyCode === 13) { // space enter
this.handleClick();
} else if ([9, 27].indexOf(keyCode) > -1) { // tab || esc
this.hide();
}
return;
},
handleItemKeyDown(ev) {
const keyCode = ev.keyCode;
const target = ev.target;
const currentIndex = this.menuItemsArray.indexOf(target);
const max = this.menuItemsArray.length - 1;
let nextIndex;
if ([38, 40].indexOf(keyCode) > -1) { // up/down
if (keyCode === 38) { // up
nextIndex = currentIndex !== 0 ? currentIndex - 1 : 0;
} else { // down
nextIndex = currentIndex < max ? currentIndex + 1 : max;
}
this.removeTabindex();
this.resetTabindex(this.menuItems[nextIndex]);
this.menuItems[nextIndex].focus();
ev.preventDefault();
ev.stopPropagation();
} else if (keyCode === 13) { // enter
this.triggerElm.focus();
target.click();
if (!this.hideOnClick) { // click
this.visible = false;
}
} else if ([9, 27].indexOf(keyCode) > -1) { // tab // esc
this.hide();
this.triggerElm.focus();
}
return;
},
resetTabindex(ele) { // tab
this.removeTabindex();
ele.setAttribute('tabindex', '0'); //
},
removeTabindex() {
this.triggerElm.setAttribute('tabindex', '-1');
this.menuItemsArray.forEach((item) => {
item.setAttribute('tabindex', '-1');
});
},
initAria() {
this.dropdownElm.setAttribute('id', this.listId);
this.triggerElm.setAttribute('aria-haspopup', 'list');
this.triggerElm.setAttribute('aria-controls', this.listId);
this.menuItems = this.dropdownElm.querySelectorAll("[tabindex='-1']");
this.menuItemsArray = Array.prototype.slice.call(this.menuItems);
if (!this.splitButton) { //
this.triggerElm.setAttribute('role', 'button');
this.triggerElm.setAttribute('tabindex', '0');
this.triggerElm.className += ' el-dropdown-selfdefine'; //
}
},
initEvent() {
let { trigger, show, hide, handleClick, splitButton } = this;
let { trigger, show, hide, handleClick, splitButton, handleTriggerKeyDown, handleItemKeyDown } = this;
this.triggerElm = splitButton
? this.$refs.trigger.$el
: this.$slots.default[0].elm;
let dropdownElm = this.dropdownElm = this.$slots.dropdown[0].elm;
this.triggerElm.addEventListener('keydown', handleTriggerKeyDown); // triggerElm keydown
dropdownElm.addEventListener('keydown', handleItemKeyDown, true); // item keydown
//
if (!splitButton) {
this.triggerElm.addEventListener('focus', () => {
this.focusing = true;
});
this.triggerElm.addEventListener('blur', () => {
this.focusing = false;
});
this.triggerElm.addEventListener('click', () => {
this.focusing = false;
});
}
if (trigger === 'hover') {
this.triggerElm.addEventListener('mouseenter', show);
this.triggerElm.addEventListener('mouseleave', hide);
let dropdownElm = this.$slots.dropdown[0].elm;
dropdownElm.addEventListener('mouseenter', show);
dropdownElm.addEventListener('mouseleave', hide);
} else if (trigger === 'click') {

View File

@ -157,14 +157,14 @@
},
getColorChannels(color) {
color = color.replace('#', '');
if (/^[1-9a-fA-F]{3}$/.test(color)) {
if (/^[0-9a-fA-F]{3}$/.test(color)) {
color = color.split('');
for (let i = 2; i >= 0; i--) {
color.splice(i, 0, color[i]);
}
color = color.join('');
}
if (/^[1-9a-fA-F]{6}$/.test(color)) {
if (/^[0-9a-fA-F]{6}$/.test(color)) {
return {
red: parseInt(color.slice(0, 2), 16),
green: parseInt(color.slice(2, 4), 16),

View File

@ -173,11 +173,13 @@
},
handleTitleMouseenter() {
if (this.mode === 'horizontal' && !this.rootMenu.backgroundColor) return;
this.$refs['submenu-title'].style.backgroundColor = this.rootMenu.hoverBackground;
const title = this.$refs['submenu-title'];
title && (title.style.backgroundColor = this.rootMenu.hoverBackground);
},
handleTitleMouseleave() {
if (this.mode === 'horizontal' && !this.rootMenu.backgroundColor) return;
this.$refs['submenu-title'].style.backgroundColor = this.rootMenu.backgroundColor || '';
const title = this.$refs['submenu-title'];
title && (title.style.backgroundColor = this.rootMenu.backgroundColor || '');
}
},
created() {

View File

@ -9,15 +9,15 @@
v-show="visible"
@mouseenter="clearTimer"
@mouseleave="startTimer"
role="alertdialog"
role="alert"
>
<i :class="iconClass" v-if="iconClass"></i>
<i :class="typeClass" v-else></i>
<slot>
<p v-if="!dangerouslyUseHTMLString" class="el-message__content" tabindex="0">{{ message }}</p>
<p v-else v-html="message" class="el-message__content" tabindex="0"></p>
<p v-if="!dangerouslyUseHTMLString" class="el-message__content">{{ message }}</p>
<p v-else v-html="message" class="el-message__content"></p>
</slot>
<i v-if="showClose" class="el-message__closeBtn el-icon-close" @click="close" tabindex="0" role="button" aria-label="close" @keydown.enter.stop="close"></i>
<i v-if="showClose" class="el-message__closeBtn el-icon-close" @click="close"></i>
</div>
</transition>
</template>
@ -44,9 +44,7 @@
closed: false,
timer: null,
dangerouslyUseHTMLString: false,
center: false,
initFocus: null,
originFocus: null
center: false
};
},
@ -87,18 +85,6 @@
if (typeof this.onClose === 'function') {
this.onClose(this);
}
if (!this.originFocus || !this.originFocus.getBoundingClientRect) return;
// restore keyboard focus
const { top, left, bottom, right } = this.originFocus.getBoundingClientRect();
const viewportHeight = window.innerHeight || document.documentElement.clientHeight;
const viewportWidth = window.innerWidth || document.documentElement.clientWidth;
if (top >= 0 &&
left >= 0 &&
bottom <= viewportHeight &&
right <= viewportWidth) {
this.originFocus.focus();
}
},
clearTimer() {
@ -115,24 +101,15 @@
}
},
keydown(e) {
if (e.keyCode === 46 || e.keyCode === 8) {
this.clearTimer(); // detele
} else if (e.keyCode === 27) { // esc
if (e.keyCode === 27) { // esc
if (!this.closed) {
this.close();
}
} else {
this.startTimer(); //
}
}
},
mounted() {
this.startTimer();
this.originFocus = document.activeElement;
this.initFocus = this.showClose ? this.$el.querySelector('.el-icon-close') : this.$el.querySelector('.el-message__content');
setTimeout(() => {
this.initFocus && this.initFocus.focus();
});
document.addEventListener('keydown', this.keydown);
},
beforeDestroy() {

View File

@ -6,7 +6,9 @@
:style="positionStyle"
@mouseenter="clearTimer()"
@mouseleave="startTimer()"
@click="click">
@click="click"
role="alert"
>
<i
class="el-notification__icon"
:class="[ typeClass, iconClass ]"
@ -119,9 +121,19 @@
}
}, this.duration);
}
},
keydown(e) {
if (e.keyCode === 46 || e.keyCode === 8) {
this.clearTimer(); // detele
} else if (e.keyCode === 27) { // esc
if (!this.closed) {
this.close();
}
} else {
this.startTimer(); //
}
}
},
mounted() {
if (this.duration > 0) {
this.timer = setTimeout(() => {
@ -130,6 +142,11 @@
}
}, this.duration);
}
document.addEventListener('keydown', this.keydown);
},
beforeDestroy() {
document.removeEventListener('keydown', this.keydown);
}
};
</script>

View File

@ -6,7 +6,11 @@
:class="[popperClass, content && 'el-popover--plain']"
ref="popper"
v-show="!disabled && showPopper"
:style="{ width: width + 'px' }">
:style="{ width: width + 'px' }"
role="tooltip"
:id="tooltipId"
:aria-hidden="(disabled || !showPopper) ? 'true' : 'false'"
>
<div class="el-popover__title" v-if="title" v-text="title"></div>
<slot>{{ content }}</slot>
</div>
@ -14,10 +18,11 @@
<slot name="reference"></slot>
</span>
</template>
<script>
import Popper from 'element-ui/src/utils/vue-popper';
import { on, off } from 'element-ui/src/utils/dom';
import { addClass, removeClass } from 'element-ui/src/utils/dom';
import { generateId } from 'element-ui/src/utils/util';
export default {
name: 'ElPopover',
@ -49,25 +54,35 @@ export default {
}
},
computed: {
tooltipId() {
return `el-popover-${generateId()}`;
}
},
watch: {
showPopper(newVal, oldVal) {
newVal ? this.$emit('show') : this.$emit('hide');
},
'$refs.reference': {
deep: true,
handler(val) {
console.log(val);
}
showPopper(val) {
val ? this.$emit('show') : this.$emit('hide');
}
},
mounted() {
let reference = this.reference || this.$refs.reference;
let reference = this.referenceElm = this.reference || this.$refs.reference;
const popper = this.popper || this.$refs.popper;
if (!reference && this.$slots.reference && this.$slots.reference[0]) {
reference = this.referenceElm = this.$slots.reference[0].elm;
}
// 访
if (reference) {
addClass(reference, 'el-popover__reference');
reference.setAttribute('aria-describedby', this.tooltipId);
reference.setAttribute('tabindex', 0); // tab
this.trigger !== 'click' && on(reference, 'focus', this.handleFocus);
this.trigger !== 'click' && on(reference, 'blur', this.handleBlur);
on(reference, 'keydown', this.handleKeydown);
on(reference, 'click', this.handleClick);
}
if (this.trigger === 'click') {
on(reference, 'click', this.doToggle);
on(document, 'click', this.handleDocumentClick);
@ -114,6 +129,17 @@ export default {
doClose() {
this.showPopper = false;
},
handleFocus() {
addClass(this.referenceElm, 'focusing');
this.showPopper = true;
},
handleClick() {
removeClass(this.referenceElm, 'focusing');
},
handleBlur() {
removeClass(this.referenceElm, 'focusing');
this.showPopper = false;
},
handleMouseEnter() {
clearTimeout(this._timer);
if (this.openDelay) {
@ -124,6 +150,11 @@ export default {
this.showPopper = true;
}
},
handleKeydown(ev) {
if (ev.keyCode === 27) { // esc
this.doClose();
}
},
handleMouseLeave() {
clearTimeout(this._timer);
this._timer = setTimeout(() => {

View File

@ -53,9 +53,10 @@
},
mounted() {
// radioGroupTab
let radios = this.$el.querySelectorAll('[type=radio]');
if (![].some.call(radios, radio => radio.checked)) {
this.$el.querySelectorAll('[role=radio]')[0].tabIndex = 0;
const radios = this.$el.querySelectorAll('[type=radio]');
const firstLabel = this.$el.querySelectorAll('[role=radio]')[0];
if (![].some.call(radios, radio => radio.checked) && firstLabel) {
firstLabel.tabIndex = 0;
}
},
methods: {

View File

@ -1,6 +1,6 @@
<template>
<ul class="el-select-group__wrap">
<li class="el-select-group__title" v-show="visible">{{ label }}</li>
<ul class="el-select-group__wrap" v-show="visible">
<li class="el-select-group__title">{{ label }}</li>
<li>
<ul class="el-select-group">
<slot></slot>

View File

@ -9,7 +9,12 @@
@click.stop="toggleMenu"
ref="tags"
:style="{ 'max-width': inputWidth - 32 + 'px' }">
<transition-group @after-leave="resetInputHeight">
<span
class="el-select__multiple-text"
v-if="collapseTags">
{{ multipleText }}
</span>
<transition-group @after-leave="resetInputHeight" v-if="!collapseTags">
<el-tag
v-for="item in selected"
:key="getValueKey(item)"
@ -29,6 +34,7 @@
:class="[selectSize ? `is-${ selectSize }` : '']"
:disabled="disabled"
@focus="handleFocus"
@click.stop
@keyup="managePlaceholder"
@keydown="resetInputState"
@keydown.down.prevent="navigateOptions('next')"
@ -183,6 +189,14 @@
selectSize() {
return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
},
multipleText() {
const selected = this.selected;
if (!selected || !selected.length) return '';
const length = selected.length;
const countText = length > 1 ? `(+${ selected.length - 1 })` : '';
return `${ selected[0].currentLabel } ${ countText }`;
}
},
@ -231,7 +245,8 @@
valueKey: {
type: String,
default: 'value'
}
},
collapseTags: Boolean
},
data() {
@ -534,6 +549,7 @@
},
resetInputHeight() {
if (this.collapseTags) return;
this.$nextTick(() => {
if (!this.$refs.reference) return;
let inputChildNodes = this.$refs.reference.$el.childNodes;

View File

@ -119,12 +119,10 @@ export default {
{
column.sortable
? <span class="caret-wrapper" on-click={ ($event) => this.handleSortClick($event, column) }>
<span class="sort-caret ascending" on-click={ ($event) => this.handleSortClick($event, column, 'ascending') }>
<i class="el-icon-sort-up"></i>
</span>
<span class="sort-caret descending" on-click={ ($event) => this.handleSortClick($event, column, 'descending') }>
<i class="el-icon-sort-down"></i>
</span>
<i class="sort-caret ascending el-icon-caret-top" on-click={ ($event) => this.handleSortClick($event, column, 'ascending') }>
</i>
<i class="sort-caret descending el-icon-caret-bottom" on-click={ ($event) => this.handleSortClick($event, column, 'descending') }>
</i>
</span>
: ''
}

View File

@ -1,6 +1,6 @@
{
"name": "element-theme-chalk",
"version": "2.0.3",
"version": "2.0.4",
"description": "Element component chalk theme.",
"main": "lib/index.css",
"style": "lib/index.css",
@ -28,7 +28,8 @@
"devDependencies": {
"gulp": "^3.9.1",
"gulp-cssmin": "^0.1.7",
"gulp-sass": "^3.1.0"
"gulp-sass": "^3.1.0",
"gulp-autoprefixer": "^4.0.0"
},
"dependencies": {}
}

View File

@ -128,7 +128,7 @@
line-height: 1.5;
box-sizing: border-box;
cursor: pointer;
outline: none;
@include m(extensible) {
&:after {
font-family: 'element-icons';
@ -154,7 +154,7 @@
color: $--select-option-selected;
}
&:hover {
&:hover, &:focus:not(:active) {
background-color: $--select-option-hover-background;
}

View File

@ -17,6 +17,9 @@
padding: $--checkbox-bordered-padding;
border-radius: $--border-radius-base;
border: $--border-base;
box-sizing: border-box;
line-height: normal;
height: $--checkbox-bordered-height;
&.is-checked {
border-color: $--color-primary;
@ -34,6 +37,7 @@
&.el-checkbox--medium {
padding: $--checkbox-bordered-medium-padding;
border-radius: $--button-medium-border-radius;
height: $--checkbox-bordered-medium-height;
.el-checkbox__label {
line-height: 17px;
@ -49,6 +53,7 @@
&.el-checkbox--small {
padding: $--checkbox-bordered-small-padding;
border-radius: $--button-small-border-radius;
height: $--checkbox-bordered-small-height;
.el-checkbox__label {
line-height: 15px;
@ -69,6 +74,7 @@
&.el-checkbox--mini {
padding: $--checkbox-bordered-mini-padding;
border-radius: $--button-mini-border-radius;
height: $--checkbox-bordered-mini-height;
.el-checkbox__label {
line-height: 12px;

View File

@ -137,16 +137,20 @@ $--checkbox-checked-icon-color: $--fill-base !default;
$--checkbox-input-border-color-hover: $--color-primary !default;
$--checkbox-bordered-height: 40px !default;
$--checkbox-bordered-padding: 9px 20px 9px 10px !default;
$--checkbox-bordered-medium-padding: 7px 20px 7px 10px !default;
$--checkbox-bordered-small-padding: 3px 15px 7px 10px !default;
$--checkbox-bordered-mini-padding: 1px 15px 5px 10px !default;
$--checkbox-bordered-small-padding: 5px 15px 5px 10px !default;
$--checkbox-bordered-mini-padding: 3px 15px 3px 10px !default;
$--checkbox-bordered-medium-input-height: 14px !default;
$--checkbox-bordered-medium-input-width: 14px !default;
$--checkbox-bordered-medium-height: 36px !default;
$--checkbox-bordered-small-input-height: 12px !default;
$--checkbox-bordered-small-input-width: 12px !default;
$--checkbox-bordered-small-height: 32px !default;
$--checkbox-bordered-mini-input-height: 12px !default;
$--checkbox-bordered-mini-input-width: 12px !default;
$--checkbox-bordered-mini-height: 28px !default;
$--checkbox-button-font-size: $--font-size-base !default;
$--checkbox-button-checked-fill: $--color-primary !default;
@ -183,16 +187,20 @@ $--radio-checked-icon-color: $--color-primary !default;
$--radio-input-border-color-hover: $--color-primary !default;
$--radio-bordered-padding: 10px 20px 10px 10px !default;
$--radio-bordered-medium-padding: 8px 20px 8px 10px !default;
$--radio-bordered-small-padding: 6px 15px 6px 10px !default;
$--radio-bordered-mini-padding: 4px 15px 4px 10px !default;
$--radio-bordered-height: 40px !default;
$--radio-bordered-padding: 12px 20px 0 10px !default;
$--radio-bordered-medium-padding: 10px 20px 0 10px !default;
$--radio-bordered-small-padding: 8px 15px 0 10px !default;
$--radio-bordered-mini-padding: 6px 15px 0 10px !default;
$--radio-bordered-medium-input-height: 14px !default;
$--radio-bordered-medium-input-width: 14px !default;
$--radio-bordered-medium-height: 36px !default;
$--radio-bordered-small-input-height: 12px !default;
$--radio-bordered-small-input-width: 12px !default;
$--radio-bordered-small-height: 32px !default;
$--radio-bordered-mini-input-height: 12px !default;
$--radio-bordered-mini-input-width: 12px !default;
$--radio-bordered-mini-height: 28px !default;
$--radio-button-font-size: $--font-size-base !default;
$--radio-button-checked-fill: $--color-primary !default;

View File

@ -50,6 +50,12 @@
font-size: 12px;
margin: 0 3px;
}
.el-dropdown-selfdefine { //
&:focus:active, &:focus:not(.focusing) {
outline-width: 0;
}
}
}
@include b(dropdown-menu) {
@ -72,8 +78,8 @@
font-size: $--font-size-base;
color: $--color-text-regular;
cursor: pointer;
&:not(.is-disabled):hover {
outline: none;
&:not(.is-disabled):hover, &:focus {
background-color: $--dropdown-menuItem-hover-fill;
color: $--dropdown-menuItem-hover-color;
}

View File

@ -27,4 +27,10 @@
line-height: 1;
margin-bottom: 12px;
}
@include e(reference) {
&:focus:not(.focusing), &:focus:hover {
outline-width: 0;
}
}
}

View File

@ -19,6 +19,8 @@
padding: $--radio-bordered-padding;
border-radius: $--border-radius-base;
border: $--border-base;
box-sizing: border-box;
height: $--radio-bordered-height;
&.is-checked {
border-color: $--color-primary;
@ -38,6 +40,7 @@
&.is-bordered {
padding: $--radio-bordered-medium-padding;
border-radius: $--button-medium-border-radius;
height: $--radio-bordered-medium-height;
.el-radio__label {
font-size: $--button-medium-font-size;
}
@ -51,6 +54,7 @@
&.is-bordered {
padding: $--radio-bordered-small-padding;
border-radius: $--button-small-border-radius;
height: $--radio-bordered-small-height;
.el-radio__label {
font-size: $--button-small-font-size;
}
@ -64,6 +68,7 @@
&.is-bordered {
padding: $--radio-bordered-mini-padding;
border-radius: $--button-mini-border-radius;
height: $--radio-bordered-mini-height;
.el-radio__label {
font-size: $--button-mini-font-size;
}

View File

@ -1,4 +1,5 @@
@import "mixins/mixins";
@import "mixins/utils";
@import "common/var";
@import "select-dropdown";
@import "input";
@ -88,6 +89,14 @@
}
}
@include e(multiple-text) {
margin-left: 15px;
color: $--input-color;
font-size: $--font-size-base;
display: block;
@include utils-ellipsis;
}
@include e(close) {
cursor: pointer;
position: absolute;

View File

@ -426,20 +426,29 @@
}
.caret-wrapper {
position: relative;
display: inline-flex;
align-items: center;
height: 13px;
width: 24px;
position: absolute;
display: inline-block;
height: 100%;
vertical-align: middle;
cursor: pointer;
overflow: initial;
}
.sort-caret {
color: $--icon-color-base;
color: $--color-text-placeholder;
width: 14px;
overflow: hidden;
font-size: 13px;
font-size: 15px;
position: absolute;
left: 4px;
&.ascending {
top: 1px;
}
&.descending {
bottom: 1px;
}
}
.ascending .sort-caret.ascending {

View File

@ -2,6 +2,9 @@
@import "common/var";
@include b(tooltip) {
&:focus:not(.focusing), &:focus:hover {
outline-width: 0;
}
@include e(popper) {
position: absolute;
border-radius: 4px;

View File

@ -25,7 +25,12 @@
@include b(tree-node) {
white-space: nowrap;
outline: none;
&:focus { /* focus */
> .el-tree-node__content {
background-color: $--tree-node-hover-color;
}
}
@include e(content) {
display: flex;
align-items: center;

View File

@ -1,6 +1,7 @@
import Popper from 'element-ui/src/utils/vue-popper';
import debounce from 'throttle-debounce/debounce';
import { getFirstComponentChild } from 'element-ui/src/utils/vdom';
import { generateId } from 'element-ui/src/utils/util';
import Vue from 'vue';
export default {
@ -48,10 +49,15 @@ export default {
data() {
return {
timeoutPending: null
timeoutPending: null,
focusing: false
};
},
computed: {
tooltipId() {
return `el-tooltip-${generateId()}`;
}
},
beforeCreate() {
if (this.$isServer) return;
@ -75,6 +81,9 @@ export default {
onMouseleave={ () => { this.setExpectedState(false); this.debounceClose(); } }
onMouseenter= { () => { this.setExpectedState(true); } }
ref="popper"
role="tooltip"
id={this.tooltipId}
aria-hidden={ (this.disabled || !this.showPopper) ? 'true' : 'false' }
v-show={!this.disabled && this.showPopper}
class={
['el-tooltip__popper', 'is-' + this.effect, this.popperClass]
@ -87,24 +96,38 @@ export default {
if (!this.$slots.default || !this.$slots.default.length) return this.$slots.default;
const vnode = getFirstComponentChild(this.$slots.default);
if (!vnode) return vnode;
const data = vnode.data = vnode.data || {};
const on = vnode.data.on = vnode.data.on || {};
const nativeOn = vnode.data.nativeOn = vnode.data.nativeOn || {};
data.staticClass = this.concatClass(data.staticClass, 'el-tooltip');
on.mouseenter = this.addEventHandle(on.mouseenter, this.show);
on.mouseleave = this.addEventHandle(on.mouseleave, this.hide);
nativeOn.mouseenter = this.addEventHandle(nativeOn.mouseenter, this.show);
nativeOn.mouseleave = this.addEventHandle(nativeOn.mouseleave, this.hide);
nativeOn.mouseenter = on.mouseenter = this.addEventHandle(on.mouseenter, this.show);
nativeOn.mouseleave = on.mouseleave = this.addEventHandle(on.mouseleave, this.hide);
nativeOn.focus = on.focus = this.addEventHandle(on.focus, this.handleFocus);
nativeOn.blur = on.blur = this.addEventHandle(on.blur, this.handleBlur);
nativeOn.click = on.click = this.addEventHandle(on.click, () => { this.focusing = false; });
return vnode;
},
mounted() {
this.referenceElm = this.$el;
if (this.$el.nodeType === 1) {
this.$el.setAttribute('aria-describedby', this.tooltipId);
this.$el.setAttribute('tabindex', 0);
}
},
watch: {
focusing(val) {
if (val) {
this.referenceElm.className += ' focusing';
} else {
this.referenceElm.className = this.referenceElm.className.replace('focusing', '');
}
}
},
methods: {
show() {
this.setExpectedState(true);
@ -115,7 +138,14 @@ export default {
this.setExpectedState(false);
this.debounceClose();
},
handleFocus() {
this.focusing = true;
this.show();
},
handleBlur() {
this.focusing = false;
this.hide();
},
addEventHandle(old, fn) {
if (!old) {
return fn;

View File

@ -198,9 +198,10 @@ export default class TreeStore {
const node = this.nodesMap[key];
if (!node) return;
const childNodes = node.childNodes;
childNodes.forEach(child => {
for (let i = childNodes.length - 1; i >= 0; i--) {
const child = childNodes[i];
this.remove(child.data);
});
}
for (let i = 0, j = data.length; i < j; i++) {
const child = data[i];
this.append(child, node.data);

View File

@ -1,12 +1,21 @@
<template>
<div class="el-tree-node"
<div
class="el-tree-node"
@click.stop="handleClick"
v-show="node.visible"
:class="{
'is-expanded': expanded,
'is-current': tree.store.currentNode === node,
'is-hidden': !node.visible
}">
'is-hidden': !node.visible,
'is-focusable': !node.disabled,
'is-checked': !node.disabled && node.checked
}"
role="treeitem"
tabindex="-1"
:aria-expanded="expanded"
:aria-disabled="node.disabled"
:aria-checked="node.checked"
>
<div class="el-tree-node__content"
:style="{ 'padding-left': (node.level - 1) * tree.indent + 'px' }">
<span
@ -20,7 +29,8 @@
:indeterminate="node.indeterminate"
:disabled="!!node.disabled"
@click.native.stop
@change="handleCheckChange">
@change="handleCheckChange"
>
</el-checkbox>
<span
v-if="node.loading"
@ -32,7 +42,10 @@
<div
class="el-tree-node__children"
v-if="childNodeRendered"
v-show="expanded">
v-show="expanded"
role="group"
:aria-expanded="expanded"
>
<el-tree-node
:render-content="renderContent"
v-for="child in node.childNodes"

View File

@ -1,5 +1,9 @@
<template>
<div class="el-tree" :class="{ 'el-tree--highlight-current': highlightCurrent }">
<div
class="el-tree"
:class="{ 'el-tree--highlight-current': highlightCurrent }"
role="tree"
>
<el-tree-node
v-for="child in root.childNodes"
:node="child"
@ -33,7 +37,9 @@
return {
store: null,
root: null,
currentNode: null
currentNode: null,
treeItems: null,
checkboxItems: []
};
},
@ -101,6 +107,9 @@
get() {
return this.data;
}
},
treeItemArray() {
return Array.prototype.slice.call(this.treeItems);
}
},
@ -115,6 +124,11 @@
},
data(newVal) {
this.store.setData(newVal);
},
checkboxItems(val) {
Array.prototype.forEach.call(val, (checkbox) => {
checkbox.setAttribute('tabindex', -1);
});
}
},
@ -171,6 +185,42 @@
updateKeyChildren(key, data) {
if (!this.nodeKey) throw new Error('[Tree] nodeKey is required in updateKeyChild');
this.store.updateChildren(key, data);
},
initTabindex() {
this.treeItems = this.$el.querySelectorAll('.is-focusable[role=treeitem]');
this.checkboxItems = this.$el.querySelectorAll('input[type=checkbox]');
const checkedItem = this.$el.querySelectorAll('.is-checked[role=treeitem]');
if (checkedItem.length) {
checkedItem[0].setAttribute('tabindex', 0);
return;
}
this.treeItems[0].setAttribute('tabindex', 0);
},
handelKeydown(ev) {
const currentItem = ev.target;
const keyCode = ev.keyCode;
this.treeItems = this.$el.querySelectorAll('.is-focusable[role=treeitem]');
const currentIndex = this.treeItemArray.indexOf(currentItem);
let nextIndex;
if ([38, 40].indexOf(keyCode) > -1) { // updown
if (keyCode === 38) { // up
nextIndex = currentIndex !== 0 ? currentIndex - 1 : 0;
} else {
nextIndex = (currentIndex < this.treeItemArray.length - 1) ? currentIndex + 1 : 0;
}
this.treeItemArray[nextIndex].focus(); //
}
const hasInput = currentItem.querySelector('[type="checkbox"]');
if ([37, 39].indexOf(keyCode) > -1) { // leftright
currentItem.click(); //
}
if ([13, 32].indexOf(keyCode) > -1) { // space entercheckbox
if (hasInput) {
hasInput.click();
}
ev.stopPropagation();
ev.preventDefault();
}
}
},
@ -194,6 +244,14 @@
});
this.root = this.store.root;
},
mounted() {
this.initTabindex();
this.$el.addEventListener('keydown', this.handelKeydown);
},
updated() {
this.treeItems = this.$el.querySelectorAll('[role=treeitem]');
this.checkboxItems = this.$el.querySelectorAll('input[type=checkbox]');
}
};
</script>

View File

@ -1,9 +1,9 @@
function getError(action, option, xhr) {
let msg;
if (xhr.response) {
msg = `${xhr.status} ${xhr.response.error || xhr.response}`;
msg = `${xhr.response.error || xhr.response}`;
} else if (xhr.responseText) {
msg = `${xhr.status} ${xhr.responseText}`;
msg = `${xhr.responseText}`;
} else {
msg = `fail to post ${action} ${xhr.status}`;
}

View File

@ -173,7 +173,7 @@ if (typeof window !== 'undefined' && window.Vue) {
};
module.exports = {
version: '2.0.3',
version: '2.0.4',
locale: locale.use,
i18n: locale.i18n,
install,

View File

@ -65,5 +65,6 @@ export default {
break;
}
}
delete el[ctx];
}
};

View File

@ -41,7 +41,7 @@ describe('ajax', () => {
});
it('40x code should be error', done => {
option.onError = e => {
expect(e.toString()).to.contain('404 Not found');
expect(e.toString()).to.contain('Not found');
done();
};