Compare commits

..

73 Commits

Author SHA1 Message Date
Leopoldthecoder
beec4739a3 [release] 2.0.5 2017-11-17 15:27:07 +08:00
Leopoldthecoder
46bd165fb1 [build] 2.0.5 2017-11-17 15:27:06 +08:00
Leopoldthecoder
0820daf0dd Changelog: update for 2.0.5 2017-11-17 15:08:28 +08:00
Leopoldthecoder
5406a97359 Chore: misc updates 2017-11-17 12:46:52 +08:00
Leopoldthecoder
23e86bcf1a Table: fix high CPU consumption 2017-11-17 12:28:55 +08:00
ChangJoo Park(박창주)
1af6989544 Update ko.js (#8348) 2017-11-17 12:14:06 +08:00
ChangJoo Park(박창주)
d65249e744 Update ko.js 2017-11-17 12:12:35 +08:00
Stefan de Vogelaere
ecbaea7839 Complete Dutch Translation (#8320)
* Complete Dutch Translation

* Update nl.js
2017-11-16 17:10:40 +08:00
Lengxu
6f1fc76e30 Select: fix input height resetting in default size
* dropdown 组件 新增触发下拉框显示隐藏时, 触发visible事件,传递当前下拉框显示状态

* Dropdown 修改事件名称,新增文档

* Dropdown 统一事件名称,修改文档

* Dropdown 统一事件名称,修改文档

* 完善form表单prop字段介绍

* Repair of multiple height calculation bug
2017-11-16 16:02:41 +08:00
杨奕
217b48338f Update FAQ.md 2017-11-16 11:08:10 +08:00
杨奕
1707bae9f7 Update CONTRIBUTING.en-US.md 2017-11-16 10:59:22 +08:00
Leopoldthecoder
bd55a5a593 Cascader: fix active-item-change event 2017-11-15 21:29:13 +08:00
Ryan.xu
292ad8efec Table: fix table column show-overflow-tooltip bug
Table: fix table column show-overflow-tooltip bug, low version Firefox without innerText, add textContent
2017-11-15 14:10:28 +08:00
wacky6.AriesMBP
c7d3de95b0 input: fix focus 2017-11-15 11:28:22 +08:00
Leopoldthecoder
2884984097 Tree: fix keyboard event 2017-11-15 11:15:26 +08:00
Leopoldthecoder
37f4ce0b30 MessageBox: ensure to get input element 2017-11-15 11:01:09 +08:00
lyh2668
4f00d7dea8 Update table-body.js
添加一个this.$refs.tooltip是否存在的判断
2017-11-15 10:54:19 +08:00
Jingkun Hua
6db51156b1 types: add missing definition 2017-11-14 12:18:12 +08:00
Jingkun Hua
c3cbfb1d4c types: fix #8068 2017-11-14 12:18:12 +08:00
wuzhuyu5
d419e260d0 clickoutside: fix memory leak 2017-11-14 12:15:47 +08:00
Leopoldthecoder
ed511e9219 Tree & Breadcrumb: fix setAttribute to undefined bug 2017-11-13 17:29:16 +08:00
Leopoldthecoder
f24aeeca00 Select: add collapse-tags 2017-11-12 21:03:34 +08:00
Leopoldthecoder
9611079d4d Table: sort arrow nostalgia 2017-11-12 21:03:34 +08:00
Leopoldthecoder
8fa549894b Popover: fix click trigger 2017-11-12 20:13:19 +08:00
Leopoldthecoder
64f154839c Chore: replace includes with indexOf 2017-11-12 14:27:20 +08:00
Leopoldthecoder
1833db26d8 Select: fix divider and focus issue 2017-11-12 14:27:20 +08:00
medice
ac39df84c0 clickoutside: fix memory leak 2017-11-11 10:51:08 +08:00
Leopoldthecoder
c3ee5fc0df [release] 2.0.4 2017-11-10 16:39:46 +08:00
Leopoldthecoder
33bf6f9cd9 [build] 2.0.4 2017-11-10 16:39:45 +08:00
Leopoldthecoder
c0c0e728ca Changelog: update for 2.0.4 2017-11-10 16:33:02 +08:00
Bunker13
2260a3bab3 Update package.json
missing devDependencies gulp-autoprefixer
2017-11-10 14:43:27 +08:00
carl
010b09891a fix invalid hover color of nav menu when background color contains 0 2017-11-10 12:25:02 +08:00
Leopoldthecoder
9f2ea7eab0 Chore: doc updates 2017-11-09 15:19:09 +08:00
Leopoldthecoder
aa02b42022 Radio: fix console error of RadioGroup 2017-11-09 15:19:09 +08:00
Leopoldthecoder
cbfd9cfab3 Menu: fix console error 2017-11-09 15:19:09 +08:00
Leopoldthecoder
73184399ed fix bordered checkbox and radio height 2017-11-09 15:19:09 +08:00
Leopoldthecoder
7f8991a664 Tree: fix updateChildren 2017-11-09 15:19:09 +08:00
maranran
363a80b184 Accessibility for Popover, Tooltip, Message & Notification (#8009)
* Accessibility for Tooltip & Popover

* Accessibility for message & notification

* fixbug for popover with nodeType
2017-11-09 11:21:20 +08:00
maranran
6c77cd9716 Accessibility for Tree (#8049)
* tree

* Update yarn.lock
2017-11-09 11:19:52 +08:00
maranran
81011d1c48 Accessibility for Cascader & Dropdown (#7973) 2017-11-09 10:21:27 +08:00
Joe Wong
4ea53ab896 Cascader: optimize hover to expand experience (#8010)
* Cascader: optimize hover to expand experience

pass eslint

* Cascader: hoverThreshold configuable
2017-11-08 12:24:29 +08:00
alexdee2007
651b517fd0 Core: Add plugin eslint-plugin-json (#7869)
* Add plugin eslint-plugin-json

Add plugin eslint-plugin-json for parse build/salad.config.json

* Add plugin eslint-plugin-json

Add plugin eslint-plugin-json for parse build/salad.config.json
2017-11-08 12:20:52 +08:00
Mathieu TUDISCO
839dda529e Complete french translation 🇫🇷 2017-11-07 10:43:12 +08:00
Leopoldthecoder
4d71e2f3af Container: add min-width 2017-11-06 19:24:50 +08:00
Pan
c8477c815a Breadcrumb: use provide/inject instead of this.this.$parent 2017-11-06 19:20:05 +08:00
wubaiqing
38e320b8cc Add spaces between Chinese, English and numbers. 2017-11-05 20:19:42 +08:00
butschster
cee4542c36 Update ru-RU.js
Added missed translates
2017-11-05 11:19:42 +08:00
Jordan Pickwell
fb066a6e45 Fix #7656 2017-11-04 09:30:27 +08:00
Leopoldthecoder
513294d159 Chalk: fix styles for vertical Slider and nested Tabs 2017-11-03 16:47:07 +08:00
Leopoldthecoder
5e37f18166 [release] 2.0.3 2017-11-03 15:59:16 +08:00
Leopoldthecoder
44849f7998 [build] 2.0.3 2017-11-03 15:59:15 +08:00
Leopoldthecoder
a32e793845 Changelog: update for 2.0.3 2017-11-03 15:56:17 +08:00
Leopoldthecoder
fa522dd2bc Tree: fix updateKeyChildren 2017-11-03 14:11:19 +08:00
Leopoldthecoder
03ccdb4fbc Menu: register el-tooltip 2017-11-03 13:21:06 +08:00
Leopoldthecoder
c30d4b11d2 Pagination: fix current-change 2017-11-03 13:21:06 +08:00
Leopoldthecoder
eefa2c907a Select: show dropdown on input focus 2017-11-03 10:27:13 +08:00
Chris Anderson
52bbf4f3e1 Fixes #7959 by providing aria labels for buttons 2017-11-03 10:26:30 +08:00
Riku Inoue
c1da7a5c86 Notification: fix unnecessary required types 2017-11-03 10:17:51 +08:00
Leopoldthecoder
08b80ca467 Steps: fix style for last step when vertical 2017-11-02 19:16:36 +08:00
Leopoldthecoder
88868eebf7 Theme: releasing all variables 2017-11-02 14:01:58 +08:00
Leopoldthecoder
9553e1edba Chore: misc fixes and updates 2017-11-02 14:01:58 +08:00
hjkcai
664b3fb401 Module: add default entry in exports (#7939, #7940) 2017-11-01 17:49:53 +08:00
Leopoldthecoder
194874b3b2 Message: restore focus only when target in viewport 2017-11-01 17:42:25 +08:00
Leopoldthecoder
aa09c460ff Tabs: fix padding-left for nested tabs 2017-11-01 17:32:41 +08:00
Div
06112e51da upload: Increase support for Blob types 2017-11-01 15:58:11 +08:00
maran
6a5a3aaa2f remove outline for collapse & upload 2017-11-01 15:01:27 +08:00
cinwell.li
bd545e4554 chore: remove cooking
✌️
2017-11-01 12:23:57 +08:00
Leopoldthecoder
1d37197f0b fix unlink-panels test 2017-11-01 11:51:37 +08:00
Leopoldthecoder
343e9fa438 DatePicker: fix editable and readonly in range pick 2017-11-01 11:51:37 +08:00
wubaiqing
98bf5d7f28 Fix the code style issue to pass eslint 2017-11-01 11:47:33 +08:00
WittBulter
2c34b3c804 Notification: improve position attr (en-US) 2017-11-01 10:18:05 +08:00
WittBulter
4403fdc251 Notification: improve position attr 2017-11-01 10:18:05 +08:00
spiritree
1582da7c53 FAQ: update attribute slot-scope for Vue 2.5.0+ 2017-11-01 10:16:40 +08:00
139 changed files with 1980 additions and 1203 deletions

View File

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

View File

@@ -8,7 +8,7 @@ We are excited that you are interested in contributing to Element. Before submit
## Issue Guidelines
- Issues are exclusively for bug reports, feature requests and design-related topics. Other questions may be closed directly. If any questions come up when you are using Element, please hit [Gitter](https://gitter.im/ElemeFE/element) for help.
- Issues are exclusively for bug reports, feature requests and design-related topics. Other questions may be closed directly. If any questions come up when you are using Element, please hit [Gitter](https://gitter.im/element-en/Lobby) for help.
- Before submitting an issue, please check if similar problems have already been issued.

1
.gitignore vendored
View File

@@ -14,3 +14,4 @@ fe.element/element-ui
coverage
waiter.config.js
build/bin/algolia-key.js
.envrc

View File

@@ -1,5 +1,36 @@
## Changelog
### 2.0.5
*2017-11-17*
- Fixed Popover, Tree, Breadcrumb and Cascader regression in 2.0.4, #8188 #8217 #8283
- Fixed memory leak of clickoutside directive, #8168 #8225 (by @badpunman @STLighter)
- Fixed multiple Select height when its value is cleared, #8317 (by @luciy)
- Added `collapse-tags` attribute for multiple Select to replace tags with one line of text, #8190
- Fixed high CPU consumption caused by hidden Table, #8351
- Now you can use `doLayout` method of Table to update its layout, #8351
### 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*
- Fixed `editable` and `readonly` attributes for ranged DatePicker, #7922
- Fixed style error of nested Tabs, #7941
- Fixed style error of the last Step of vertical Steps, #7980
- Fixed trigger timing of `current-change` event for Pagination, #7995
- Fixed unregistered Tooltip in Menu, #7995
### 2.0.2
*2017-10-31*

View File

@@ -1,5 +1,36 @@
## 更新日志
### 2.0.5
*2017-11-17*
- 修复上个版本引入的 Popover、Tree、Breadcrumb、Cascader 的 bug#8188 #8217 #8283
- 修复 clickoutside 指令的内存泄露问题,#8168 #8225by @badpunman @STLighter
- 修复默认尺寸的多选 Select 在清空选项后输入框高度不随之更新的问题,#8317by @luciy
- 新增 Select 的 `collapse-tags` 属性,用于在多选时以文字代替 Tag避免组件高度的增大#8190
- 修复被隐藏的 Table 会造成 CPU 占用持续增加的问题,#8351
- 开放 Table 的 `doLayout` 方法,用于重新计算 Table 的布局,#8351
### 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*
- 修复范围选择的 DatePicker `editable``readonly` 属性无法正常工作的问题,#7922
- 修复嵌套的 Tabs 的样式错误,#7941
- 修复纵向 Steps 中最后一个 Step 的样式错误,#7980
- 修复 Pagination 的 `current-change` 事件触发时机错误的问题,#7995
- 修复由于 Menu 使用了未注册的 Tooltip 造成其在按需引入时报错的问题,#7995
### 2.0.2
*2017-10-31*

46
FAQ.md
View File

@@ -22,7 +22,7 @@
使用 [Scoped slot](https://vuejs.org/v2/guide/components.html#Scoped-Slots) 即可:
```html
<el-table-column label="操作">
<template scope="props">
<template slot-scope="props">
<el-button @click.native="showDetail(props.row)">查看详情</el-button>
</template>
</el-table-column>
@@ -36,27 +36,6 @@
请阅读 Vue 文档 [Render Function](http://vuejs.org/v2/guide/render-function.html) 的相关内容。注意,使用 JSX 来写 Render Function 的话,需要安装 `babel-plugin-transform-vue-jsx`,并参照其[文档](https://github.com/vuejs/babel-plugin-transform-vue-jsx)进行配置。
</details>
<details>
<summary>如何使用第三方图标库?</summary>
只要修改第三方图标库的前缀(具体方法参阅第三方库的文档),并编写相应的 CSS即可在 Element 中像使用内置图标一样使用第三方图标。例如,将第三方库的前缀改为 `el-icon-my`,然后在其 CSS 文件中添加:
```css
[class^="el-icon-my"], [class*=" el-icon-my"] {
font-family:"your-font-family" !important;
/* 以下内容参照第三方图标库本身的规则 */
font-size: inherit;
font-style:normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
```
具体使用时,和 Element 内置的图标用法一样。比如在 `el-input` 中:
```html
<el-input icon="my-xxx" />
```
</details>
<details>
<summary>所有组件的任意属性都支持 `.sync` 修饰符吗?</summary>
@@ -115,7 +94,7 @@ For other components, the `.native` modifier is still mandatory.
Just use [Scoped slot](https://vuejs.org/v2/guide/components.html#Scoped-Slots):
```html
<el-table-column label="Operations">
<template scope="props">
<template slot-scope="props">
<el-button @click.native="showDetail(props.row)">Details</el-button>
</template>
</el-table-column>
@@ -129,27 +108,6 @@ The parameter `row` is the data object of corresponding row.
Please refer to [Render Function](http://vuejs.org/v2/guide/render-function.html) in Vue's documentation. In addition, if you are writing render functions with JSX, `babel-plugin-transform-vue-jsx` is required. See [here](https://github.com/vuejs/babel-plugin-transform-vue-jsx) for its configurations.
</details>
<details>
<summary>How do I use third-party icon font library with Element?</summary>
You just need to modify the class name prefix of the third-party library (see their docs for how to do it), and write some CSS, then you can use them just like you use Element built-in icons. For example, change the prefix to `el-icon-my`, and then add the following to its CSS:
```css
[class^="el-icon-my"], [class*=" el-icon-my"] {
font-family:"your-font-family" !important;
/* The following is based on original CSS rules of third-party library */
font-size: inherit;
font-style:normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
```
Now you can use them as you do with built-in icons. For example, in `el-input`:
```html
<el-input icon="my-xxx" />
```
</details>
<details>
<summary>Can I use `.sync` modifier on every attribute?</summary>

View File

@@ -35,7 +35,6 @@
- [Atom helper](https://github.com/ElemeFE/element-helper)
- Starter kit
- [element-starter](https://github.com/ElementUI/element-starter)
- [element-cooking-starter](https://github.com/ElementUI/element-cooking-starter)
- [element-in-laravel-starter](https://github.com/ElementUI/element-in-laravel-starter)
- [Design resources](https://github.com/ElementUI/Resources) (working in progress)
- Boilerplate for bug reports

View File

@@ -59,6 +59,8 @@ module.exports = {
Loading,
{{list}}
};
module.exports.default = module.exports;
`;
delete Components.font;

View File

@@ -1,6 +1,6 @@
var fs = require('fs');
var path = require('path');
var version = process.env.VERSION || require('../../package.json').version;
var content = { '1.0.9': '1.0', '1.1.6': '1.1', '1.2.9': '1.2', '1.3.7': '1.3', '1.4.8': '1.4' };
var content = { '1.0.9': '1.0', '1.1.6': '1.1', '1.2.9': '1.2', '1.3.7': '1.3', '1.4.10': '1.4' };
if (!content[version]) content[version] = '2.0';
fs.writeFileSync(path.resolve(__dirname, '../../examples/versions.json'), JSON.stringify(content));

View File

@@ -219,6 +219,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.');
@@ -232,16 +233,14 @@
mounted() {
this.localize();
if (this.lang === 'zh-CN') {
this.suggestJump();
}
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'];
@@ -253,13 +252,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

@@ -90,8 +90,8 @@
methods: {
setNav() {
let nav = navConfig[this.lang];
this.nav = [nav[0]].concat(nav[2].children);
nav[3].groups.map(group => group.list).forEach(list => {
this.nav = [nav[0]].concat(nav[3].children);
nav[4].groups.map(group => group.list).forEach(list => {
this.nav = this.nav.concat(list);
});
},

View File

@@ -3,9 +3,9 @@
width: 100%;
box-sizing: border-box;
padding-right: 30px;
transition: opacity .5s;
&:hover {
opacity: 1 !important;
transition: opacity .3s;
&.is-fade {
transition: opacity 3s;
}
li {
@@ -22,7 +22,7 @@
margin-top: 15px;
}
> ul > .nav-item:nth-child(-n + 3) > a {
> ul > .nav-item:nth-child(-n + 4) > a {
margin-top: 0;
}
@@ -88,6 +88,7 @@
<div
class="side-nav"
@mouseenter="isFade = false"
:class="{ 'is-fade': isFade }"
:style="navStyle">
<ul>
<li class="nav-item" v-for="item in data">
@@ -167,9 +168,7 @@
if (this.isSmallScreen) {
style.paddingBottom = '60px';
}
if (this.isFade) {
style.opacity = '0.5';
}
style.opacity = this.isFade ? '0.5' : '1';
return style;
},
langConfig() {

View File

@@ -111,7 +111,7 @@ Besides using the `title` attribute, you can customize panel title with named sl
<el-collapse accordion>
<el-collapse-item name="1">
<template slot="title">
Consistency<i class="header-icon el-icon-information"></i>
Consistency<i class="header-icon el-icon-info"></i>
</template>
<div>Consistent with real life: in line with the process and logic of real life, and comply with languages and habits that the users are used to;</div>
<div>Consistent within interface: all elements should be consistent, such as: design style, icons and texts, position of elements, etc.</div>

View File

@@ -28,33 +28,14 @@ import './element-variables.scss'
Vue.use(Element)
```
Note that it is required to override icon font path to the relative path of Element's font files. You can edit the following variables in this way:
:::tip
Note that it is required to override icon font path to the relative path of Element's font files.
:::
| Variable | Description | Default value |
| ------ | ---- | ------ |
| $--sm | `sm` breakpoint for responsive layout | 768px |
| $--md | `md` breakpoint for responsive layout | 992px |
| $--lg | `lg` breakpoint for responsive layout | 1200px |
| $--xl | `xl` breakpoint for responsive layout | 1920px |
| $--color-primary | theme color | #409EFF |
| $--color-success | color for success | #67C23A |
| $--color-warning | color for warning | #EB9E05 |
| $--color-danger | color for danger | #FA5555 |
| $--color-info | color for info | #878D99 |
| $--color-text-primary | color for primary texts | #2D2F33 |
| $--color-text-regular | color for regular texts | #5A5E66 |
| $--color-text-secondary | color for secondary texts | #878D99 |
| $--color-text-placeholder | color for placeholder texts | #B4BCCC |
| $--border-color-base | base border color | #D8DCE5 |
| $--border-color-light | light border color | #DFE4ED |
| $--border-color-lighter | lighter border color | #E6EBF5 |
| $--border-color-extra-light | extra light border color | #EDF2FC |
| $--font-path | icon font file path | 'fonts' |
### CLI theme tool
If you project doesn't use SCSS, you can customize themes with our CLI theme tool:
### More customizations
If you need more customization than just changing the theme color, please follow these steps:
#### <strong>Install related tool</strong>
#### <strong>Install</strong>
First install the theme generator globally or locally. Local install is recommended because in this way, when others clone your project, npm will automatically install it for them.
```shell
npm i element-theme -g
@@ -78,23 +59,25 @@ et -i [custom output file]
> ✔ Generator variables file
```
In `element-variables.scss` you can find all the variables we used to style Element and they are defined in SCSS format:
In `element-variables.scss` you can find all the variables we used to style Element and they are defined in SCSS format. Here's a snippet:
```css
$--color-primary: #409EFF !default;
$--color-primary-light-1: mix($--color-white, $--color-primary, 10%); /* 53a8ff */
$--color-primary-light-2: mix($--color-white, $--color-primary, 20%); /* 66b1ff */
$--color-primary-light-3: mix($--color-white, $--color-primary, 30%); /* 79bbff */
$--color-primary-light-4: mix($--color-white, $--color-primary, 40%); /* 8cc5ff */
$--color-primary-light-5: mix($--color-white, $--color-primary, 50%); /* a0cfff */
$--color-primary-light-6: mix($--color-white, $--color-primary, 60%); /* b3d8ff */
$--color-primary-light-7: mix($--color-white, $--color-primary, 70%); /* c6e2ff */
$--color-primary-light-8: mix($--color-white, $--color-primary, 80%); /* d9ecff */
$--color-primary-light-9: mix($--color-white, $--color-primary, 90%); /* ecf5ff */
$--color-primary-light-1: mix($--color-white, $--color-primary, 10%) !default; /* 53a8ff */
$--color-primary-light-2: mix($--color-white, $--color-primary, 20%) !default; /* 66b1ff */
$--color-primary-light-3: mix($--color-white, $--color-primary, 30%) !default; /* 79bbff */
$--color-primary-light-4: mix($--color-white, $--color-primary, 40%) !default; /* 8cc5ff */
$--color-primary-light-5: mix($--color-white, $--color-primary, 50%) !default; /* a0cfff */
$--color-primary-light-6: mix($--color-white, $--color-primary, 60%) !default; /* b3d8ff */
$--color-primary-light-7: mix($--color-white, $--color-primary, 70%) !default; /* c6e2ff */
$--color-primary-light-8: mix($--color-white, $--color-primary, 80%) !default; /* d9ecff */
$--color-primary-light-9: mix($--color-white, $--color-primary, 90%) !default; /* ecf5ff */
$--color-success: #67c23a !default;
$--color-warning: #eb9e05 !default;
$--color-danger: #fa5555 !default;
$--color-info: #878d99 !default;
...
```
#### <strong>Modify variables</strong>

View File

@@ -3,6 +3,9 @@
data() {
return {
pickerOptions1: {
disabledDate(time) {
return time.getTime() > Date.now();
},
shortcuts: [{
text: 'Today',
onClick(picker) {
@@ -127,6 +130,9 @@ Basic date picker measured by 'day'.
data() {
return {
pickerOptions1: {
disabledDate(time) {
return time.getTime() > Date.now();
},
shortcuts: [{
text: 'Today',
onClick(picker) {

View File

@@ -324,6 +324,13 @@ It includes all kinds of input items, such as `input`, `select`, `radio` and `ch
```
:::
:::tip
[W3C](https://www.w3.org/MarkUp/html-spec/html-spec_8.html#SEC8.2) regulates that
> <i>When there is only one single-line text input field in a form, the user agent should accept Enter in that field as a request to submit the form.</i>
To prevent this behavior, you can add `@submit.native.prevent` on `<el-form>`.
:::
### Inline form
When the vertical space is limited and the form is relatively simple, you can put it in one line.

View File

@@ -644,10 +644,10 @@ Search data from server-side.
| Name | Description |
|------|--------|
| prefix | content as Input prefix |
| suffix | content as Input suffix |
| prepend | content to prepend before Input |
| append | content to append after Input |
| prefix | content as Input prefix, only works when `type` is 'text' |
| suffix | content as Input suffix, only works when `type` is 'text' |
| prepend | content to prepend before Input, only works when `type` is 'text' |
| append | content to append after Input, only works when `type` is 'text' |
### Input Events

View File

@@ -17,6 +17,10 @@ Get the latest version from [unpkg.com/element-ui](https://unpkg.com/element-ui/
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
```
:::tip
We recommend our users to lock Element's version when using CDN. Please refer to [unpkg.com](https://unpkg.com) for more information.
:::
### Hello world
If you are using CDN, a hello-world page is easy with Element. [Online Demo](https://jsfiddle.net/hzfpyvg6/14/)

View File

@@ -233,7 +233,9 @@ Loading.service(options);
The parameter `options` is the configuration of Loading, and its details can be found in the following table. `LoadingService` returns a Loading instance, and you can close it by invoking its `close` method:
```javascript
let loadingInstance = Loading.service(options);
loadingInstance.close();
this.$nextTick(() => { // Loading should be closed asynchronously
loadingInstance.close();
});
```
Note that in this case the full screen Loading is singleton. If a new full screen Loading is invoked before an existing one is closed, the existing full screen Loading instance will be returned instead of actually creating another Loading instance:
```javascript

View File

@@ -409,6 +409,7 @@ In this case you should call `Notification(options)`. We have also registered me
| iconClass | custom icon's class. It will be overridden by `type` | string | — | — |
| customClass | custom class name for Notification | string | — | — |
| duration | duration before close. It will not automatically close if set 0 | number | — | 4500 |
| position | custom position | string | top-right/top-left/bottom-right/bottom-left | top-right |
| showClose | whether to show a close button | boolean | — | true |
| onClose | callback function when closed | function | — | — |
| onClick | callback function when notification clicked | function | — | — |

View File

@@ -86,7 +86,7 @@ new Vue({
})
```
Full example (Component list reference [components.json](https://github.com/ElemeFE/element/blob/carbon/components.json))
Full example (Component list reference [components.json](https://github.com/ElemeFE/element/blob/master/components.json))
```javascript
import Vue from 'vue'

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

@@ -1990,6 +1990,7 @@ You can customize row index in `type=index` columns.
| setCurrentRow | used in single selection Table, set a certain row selected. If called without any parameter, it will clear selection. | row |
| clearSort | clear sorting, restore data to the original order | — |
| clearFilter | clear filter | — |
| doLayout | Refresh the layout of Table. When the visibility of Table changes, you may need to call this method to get a correct layout | — |
### Table Slot
| Name | Description |

View File

@@ -219,7 +219,7 @@ In fact, Tooltip is an extension based on [Vue-popper](https://github.com/elemen
:::tip
The `router-link` component is not supported in tooltip, please use `vm.$router.push`.
Disabled form elements are not supported in tooltip, see more information at [MDN](https://developer.mozilla.org/en-US/docs/Web/Events/mouseenter), please wrap disabled form elements.
Disabled form elements are not supported for Tooltip, more information can be found at [MDN](https://developer.mozilla.org/en-US/docs/Web/Events/mouseenter). You need to wrap the disabled form element with a container element for Tooltip to work.
:::

View File

@@ -18,7 +18,7 @@
position: relative;
overflow: hidden;
&:hover {
&:hover, &:focus {
border-color: #409EFF;
}
}
@@ -247,7 +247,7 @@ Use `list-type` to change the fileList style.
:on-remove="handleRemove">
<i class="el-icon-plus"></i>
</el-upload>
<el-dialog v-model="dialogVisible" size="tiny">
<el-dialog :visible.sync="dialogVisible" size="tiny">
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
<script>

View File

@@ -110,7 +110,7 @@
<el-collapse accordion>
<el-collapse-item>
<template slot="title">
一致性 Consistency<i class="header-icon el-icon-information"></i>
一致性 Consistency<i class="header-icon el-icon-info"></i>
</template>
<div>与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;</div>
<div>在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。</div>

View File

@@ -27,31 +27,12 @@ import './element-variables.scss'
Vue.use(Element)
```
需要注意的是,覆盖字体路径变量是必需的,将其赋值为 Element 中 icon 图标所在的相对路径即可。使用这种方式可以自定义的变量为:
:::tip
需要注意的是,覆盖字体路径变量是必需的,将其赋值为 Element 中 icon 图标所在的相对路径即可。
:::
| 变量名 | 含义 | 默认值 |
| ------ | ---- | ------ |
| $--sm | 响应式布局中 `sm` 的断点值 | 768px |
| $--md | 响应式布局中 `md` 的断点值 | 992px |
| $--lg | 响应式布局中 `lg` 的断点值 | 1200px |
| $--xl | 响应式布局中 `xl` 的断点值 | 1920px |
| $--color-primary | 主题色 | #409EFF |
| $--color-success | 表示「成功」的状态色 | #67C23A |
| $--color-warning | 表示「警告」的状态色 | #EB9E05 |
| $--color-danger | 表示「危险」的状态色 | #FA5555 |
| $--color-info | 表示「信息」的状态色 | #878D99 |
| $--color-text-primary | 主要文字色 | #2D2F33 |
| $--color-text-regular | 常规文字色 | #5A5E66 |
| $--color-text-secondary | 次要文字色 | #878D99 |
| $--color-text-placeholder | 占位文字色 | #B4BCCC |
| $--border-color-base | 一级边框 | #D8DCE5 |
| $--border-color-light | 二级边框 | #DFE4ED |
| $--border-color-lighter | 三级边框 | #E6EBF5 |
| $--border-color-extra-light | 四级边框 | #EDF2FC |
| $--font-path | icon 字体图标路径 | 'fonts' |
### 深层次的定制
如果仅仅改变以上变量不能满足你的需求,请按以下步骤进行更深层次的主题定制:
### 命令行主题工具
如果你的项目没有使用 SCSS那么可以使用命令行主题工具进行深层次的主题定制
#### <strong>安装工具</strong>
首先安装「主题生成工具」,可以全局安装或者安装在当前项目下,推荐安装在项目里,方便别人 clone 项目时能直接安装依赖并启动,这里以全局安装做演示。
@@ -80,20 +61,22 @@ et -i [可以自定义变量文件]
如果使用默认配置,执行后当前目录会有一个 `element-variables.scss` 文件。内部包含了主题所用到的所有变量,它们使用 SCSS 的格式定义。大致结构如下:
```css
$--color-primary: #409EFF !default;
$--color-primary-light-1: mix($--color-white, $--color-primary, 10%); /* 53a8ff */
$--color-primary-light-2: mix($--color-white, $--color-primary, 20%); /* 66b1ff */
$--color-primary-light-3: mix($--color-white, $--color-primary, 30%); /* 79bbff */
$--color-primary-light-4: mix($--color-white, $--color-primary, 40%); /* 8cc5ff */
$--color-primary-light-5: mix($--color-white, $--color-primary, 50%); /* a0cfff */
$--color-primary-light-6: mix($--color-white, $--color-primary, 60%); /* b3d8ff */
$--color-primary-light-7: mix($--color-white, $--color-primary, 70%); /* c6e2ff */
$--color-primary-light-8: mix($--color-white, $--color-primary, 80%); /* d9ecff */
$--color-primary-light-9: mix($--color-white, $--color-primary, 90%); /* ecf5ff */
$--color-primary-light-1: mix($--color-white, $--color-primary, 10%) !default; /* 53a8ff */
$--color-primary-light-2: mix($--color-white, $--color-primary, 20%) !default; /* 66b1ff */
$--color-primary-light-3: mix($--color-white, $--color-primary, 30%) !default; /* 79bbff */
$--color-primary-light-4: mix($--color-white, $--color-primary, 40%) !default; /* 8cc5ff */
$--color-primary-light-5: mix($--color-white, $--color-primary, 50%) !default; /* a0cfff */
$--color-primary-light-6: mix($--color-white, $--color-primary, 60%) !default; /* b3d8ff */
$--color-primary-light-7: mix($--color-white, $--color-primary, 70%) !default; /* c6e2ff */
$--color-primary-light-8: mix($--color-white, $--color-primary, 80%) !default; /* d9ecff */
$--color-primary-light-9: mix($--color-white, $--color-primary, 90%) !default; /* ecf5ff */
$--color-success: #67c23a !default;
$--color-warning: #eb9e05 !default;
$--color-danger: #fa5555 !default;
$--color-info: #878d99 !default;
...
```
#### <strong>修改变量</strong>

View File

@@ -2,14 +2,9 @@
module.exports = {
data() {
return {
pickerOptions0: {
disabledDate(time) {
return time.getTime() > Date.now();
}
},
pickerOptions1: {
disabledDate(time) {
return time.getTime() < Date.now() - 8.64e7;
return time.getTime() > Date.now();
},
shortcuts: [{
text: '今天',
@@ -115,8 +110,7 @@
<el-date-picker
v-model="value1"
type="date"
placeholder="选择日期"
:picker-options="pickerOptions0">
placeholder="选择日期">
</el-date-picker>
</div>
<div class="block">
@@ -135,12 +129,10 @@
export default {
data() {
return {
pickerOptions0: {
pickerOptions1: {
disabledDate(time) {
return time.getTime() > Date.now();
}
},
pickerOptions1: {
},
shortcuts: [{
text: '今天',
onClick(picker) {

View File

@@ -318,6 +318,13 @@
```
:::
:::tip
W3C 标准中有如下[规定](https://www.w3.org/MarkUp/html-spec/html-spec_8.html#SEC8.2)
> <i>When there is only one single-line text input field in a form, the user agent should accept Enter in that field as a request to submit the form.</i>
即:当一个 form 元素中只有一个输入框时,在该输入框中按下回车应提交该表单。如果希望阻止这一默认行为,可以在 `<el-form>` 标签上添加 `@submit.native.prevent`
:::
### 行内表单
当垂直方向空间受限且表单较简单时,可以在一行内放置表单。

View File

@@ -799,10 +799,10 @@ export default {
### Input slots
| name | 说明 |
|------|--------|
| prefix | 输入框头部内容 |
| suffix | 输入框尾部内容 |
| prepend | 输入框前置内容 |
| append | 输入框后置内容 |
| prefix | 输入框头部内容,只对 `type="text"` 有效 |
| suffix | 输入框尾部内容,只对 `type="text"` 有效 |
| prepend | 输入框前置内容,只对 `type="text"` 有效 |
| append | 输入框后置内容,只对 `type="text"` 有效 |
### Input Events
| 事件名称 | 说明 | 回调参数 |

View File

@@ -17,6 +17,10 @@ npm i element-ui -S
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
```
:::tip
我们建议使用 CDN 引入 Element 的用户在链接地址上锁定版本,以免将来 Element 升级时受到非兼容性更新的影响。锁定版本的方法请查看 [unpkg.com](https://unpkg.com)。
:::
### Hello world
通过 CDN 的方式我们可以很容易地使用 Element 写出一个 Hello world 页面。[在线演示](https://jsfiddle.net/hzfpyvg6/14/)

View File

@@ -231,7 +231,9 @@ Loading.service(options);
其中 `options` 参数为 Loading 的配置项,具体见下表。`LoadingService` 会返回一个 Loading 实例,可通过调用该实例的 `close` 方法来关闭它:
```javascript
let loadingInstance = Loading.service(options);
loadingInstance.close();
this.$nextTick(() => { // 以服务的方式调用的 Loading 需要异步关闭
loadingInstance.close();
});
```
需要注意的是,以服务的方式调用的全屏 Loading 是单例的:若在前一个全屏 Loading 关闭前再次调用全屏 Loading并不会创建一个新的 Loading 实例,而是返回现有全屏 Loading 的实例:
```javascript

View File

@@ -410,6 +410,7 @@ import { Notification } from 'element-ui';
| iconClass | 自定义图标的类名。若设置了 `type`,则 `iconClass` 会被覆盖 | string | — | — |
| customClass | 自定义类名 | string | — | — |
| duration | 显示时间, 毫秒。设为 0 则不会自动关闭 | number | — | 4500 |
| position | 自定义弹出位置 | string | top-right/top-left/bottom-right/bottom-left | top-right |
| showClose | 是否显示关闭按钮 | boolean | — | true |
| onClose | 关闭时的回调函数 | function | — | — |
| onClick | 点击 Notification 时的回调函数 | function | — | — |

View File

@@ -86,7 +86,7 @@ new Vue({
})
```
完整组件列表和引入方式(完整组件列表以 [components.json](https://github.com/ElemeFE/element/blob/carbon/components.json) 为准)
完整组件列表和引入方式(完整组件列表以 [components.json](https://github.com/ElemeFE/element/blob/master/components.json) 为准)
```javascript
import Vue from 'vue'

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

@@ -2053,6 +2053,7 @@
| setCurrentRow | 用于单选表格,设定某一行为选中行,如果调用时不加参数,则会取消目前高亮行的选中状态。 | row |
| clearSort | 用于清空排序条件,数据会恢复成未排序的状态 | — |
| clearFilter | 用于清空过滤条件,数据会恢复成未过滤的状态 | — |
| doLayout | 对 Table 进行重新布局。当 Table 或其祖先元素由隐藏切换为显示时,可能需要调用此方法 | — |
### Table Slot
| name | 说明 |

View File

@@ -18,7 +18,7 @@
position: relative;
overflow: hidden;
&:hover {
&:hover, &:focus {
border-color: #409EFF;
}
}
@@ -247,7 +247,7 @@
:on-remove="handleRemove">
<i class="el-icon-plus"></i>
</el-upload>
<el-dialog v-model="dialogVisible" size="tiny">
<el-dialog :visible.sync="dialogVisible" size="tiny">
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
<script>

View File

@@ -8,6 +8,10 @@
"name": "Element React",
"href": "https://eleme.github.io/element-react/"
},
{
"name": "Element Angular",
"href": "https://element-angular.faas.ele.me/"
},
{
"name": "开发指南",
"children": [
@@ -254,6 +258,10 @@
"name": "Element React",
"href": "https://eleme.github.io/element-react/"
},
{
"name": "Element Angular",
"href": "https://element-angular.faas.ele.me/"
},
{
"name": "Development",
"children": [

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.8":"1.4","2.0.2":"2.0"}
{"1.0.9":"1.0","1.1.6":"1.1","1.2.9":"1.2","1.3.7":"1.3","1.4.10":"1.4","2.0.5":"2.0"}

View File

@@ -1,6 +1,6 @@
{
"name": "element-ui",
"version": "2.0.2",
"version": "2.0.5",
"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

@@ -20,9 +20,12 @@
separatorClass: ''
};
},
inject: ['elBreadcrumb'],
mounted() {
this.separator = this.$parent.separator;
this.separatorClass = this.$parent.separatorClass;
this.separator = this.elBreadcrumb.separator;
this.separatorClass = this.elBreadcrumb.separatorClass;
let self = this;
if (this.to) {
let link = this.$refs.link;

View File

@@ -17,9 +17,18 @@
default: ''
}
},
provide() {
return {
elBreadcrumb: this
};
},
mounted() {
const items = this.$el.querySelectorAll('.el-breadcrumb__item');
items[items.length - 1].setAttribute('aria-current', 'page');
if (items.length) {
items[items.length - 1].setAttribute('aria-current', 'page');
}
}
};
</script>

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,9 @@
value: [],
expandTrigger: 'click',
changeOnSelect: false,
popperClass: ''
popperClass: '',
hoverTimer: 0,
clicking: false
};
},
@@ -94,6 +97,9 @@
formatOptions(optionsCopy);
return loadActiveOptions(optionsCopy);
}
},
id() {
return generateId();
}
},
@@ -135,11 +141,43 @@
activeOptions,
visible,
expandTrigger,
popperClass
popperClass,
hoverThreshold
} = this;
let itemId = null;
let itemIndex = 0;
let hoverMenuRefs = {};
const hoverMenuHandler = e => {
const activeMenu = hoverMenuRefs.activeMenu;
if (!activeMenu) return;
const offsetX = e.offsetX;
const width = activeMenu.offsetWidth;
const height = 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 +186,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) < 0) {
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 选择子menu的第一个menuitem
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] = () => {
const triggerHandler = () => {
this.activeItem(item, menuIndex);
this.$nextTick(() => {
// adjust self and next level
@@ -161,6 +239,17 @@
this.scrollMenu(this.$refs.menus[menuIndex + 1]);
});
};
events.on[triggerEvent] = triggerHandler;
events.on['mousedown'] = () => {
this.clicking = true;
};
events.on['focus'] = () => { // focus 选中
if (this.clicking) {
this.clicking = false;
return;
}
triggerHandler();
};
} else {
events.on.click = () => {
this.select(item, menuIndex);
@@ -168,7 +257,10 @@
};
}
}
if (!item.disabled && !item.children) { // no children set id
itemId = `${menuId}-${itemIndex}`;
itemIndex++;
}
return (
<li
class={{
@@ -177,7 +269,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 +287,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

@@ -49,31 +49,37 @@
<button
type="button"
@click="prevYear"
:aria-label="t(`el.datepicker.prevYear`)"
class="el-picker-panel__icon-btn el-date-picker__prev-btn el-icon-d-arrow-left">
</button>
<button
type="button"
@click="prevMonth"
v-show="currentView === 'date'"
:aria-label="t(`el.datepicker.prevMonth`)"
class="el-picker-panel__icon-btn el-date-picker__prev-btn el-icon-arrow-left">
</button>
<span
@click="showYearPicker"
role="button"
class="el-date-picker__header-label">{{ yearLabel }}</span>
<span
@click="showMonthPicker"
v-show="currentView === 'date'"
role="button"
class="el-date-picker__header-label"
:class="{ active: currentView === 'month' }">{{t(`el.datepicker.month${ month + 1 }`)}}</span>
<button
type="button"
@click="nextYear"
:aria-label="t(`el.datepicker.nextYear`)"
class="el-picker-panel__icon-btn el-date-picker__next-btn el-icon-d-arrow-right">
</button>
<button
type="button"
@click="nextMonth"
v-show="currentView === 'date'"
:aria-label="t(`el.datepicker.nextMonth`)"
class="el-picker-panel__icon-btn el-date-picker__next-btn el-icon-arrow-right">
</button>
</div>
@@ -508,7 +514,7 @@
dateFormat() {
if (this.format) {
return this.format.replace('HH', '').replace(':mm', '').replace(':ss', '').trim();
return this.format.replace('HH', '').replace(/[^a-zA-Z]*mm/, '').replace(/[^a-zA-Z]*ss/, '').trim();
} else {
return 'yyyy-MM-dd';
}

View File

@@ -49,6 +49,7 @@
:value="displayValue && displayValue[0]"
:disabled="disabled"
:id="id && id[0]"
:readonly="!editable || readonly"
:name="name && name[0]"
@input="handleStartInput"
@change="handleStartChange"
@@ -60,6 +61,7 @@
:value="displayValue && displayValue[1]"
:disabled="disabled"
:id="id && id[1]"
:readonly="!editable || readonly"
:name="name && name[1]"
@input="handleEndInput"
@change="handleEndChange"

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.setAttribute('class', this.triggerElm.getAttribute('class') + ' 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

@@ -77,7 +77,6 @@
</template>
<script>
import emitter from 'element-ui/src/mixins/emitter';
import Focus from 'element-ui/src/mixins/focus';
import Migrating from 'element-ui/src/mixins/migrating';
import calcTextareaHeight from './calcTextareaHeight';
import merge from 'element-ui/src/utils/merge';
@@ -87,7 +86,7 @@
componentName: 'ElInput',
mixins: [emitter, Focus('input'), Migrating],
mixins: [emitter, Migrating],
inject: {
elForm: {
@@ -183,6 +182,9 @@
},
methods: {
focus() {
(this.$refs.input || this.$refs.textarea).focus();
},
getMigratingConfig() {
return {
props: {
@@ -201,7 +203,7 @@
}
},
inputSelect() {
this.$refs.input.select();
(this.$refs.input || this.$refs.textarea).select();
},
resizeTextarea() {
if (this.$isServer) return;

View File

@@ -30,6 +30,7 @@
</template>
<script>
import Menu from './menu-mixin';
import ElTooltip from 'element-ui/packages/tooltip';
import Emitter from 'element-ui/src/mixins/emitter';
export default {
@@ -39,13 +40,15 @@
mixins: [Menu, Emitter],
components: { ElTooltip },
props: {
index: {
type: String,
required: true
},
route: {
type: Object,
type: [String, Object],
required: false
},
disabled: {

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),
@@ -207,6 +207,7 @@
let openedMenus = this.openedMenus;
if (openedMenus.indexOf(index) !== -1) return;
// 将不在该菜单路径下的其余菜单收起
// collapse all menu that are not under current menu item
if (this.uniqueOpened) {
this.openedMenus = openedMenus.filter(index => {
return indexPath.indexOf(index) !== -1;
@@ -246,6 +247,7 @@
}
},
// 初始化展开菜单
// initialize opened menu
initOpenedMenu() {
const index = this.activeIndex;
const activeItem = this.items[index];
@@ -254,6 +256,7 @@
let indexPath = activeItem.indexPath;
// 展开该菜单项的路径上所有子菜单
// expand all submenus of the menu item
indexPath.forEach(index => {
let submenu = this.submenus[index];
submenu && this.openMenu(index, submenu.indexPath);

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

@@ -216,7 +216,7 @@
var inputPattern = this.inputPattern;
if (inputPattern && !inputPattern.test(this.inputValue || '')) {
this.editorErrorMessage = this.inputErrorMessage || t('el.messagebox.error');
addClass(this.$refs.input.$el.querySelector('input'), 'invalid');
addClass(this.getInputElement(), 'invalid');
return false;
}
var inputValidator = this.inputValidator;
@@ -224,7 +224,7 @@
var validateResult = inputValidator(this.inputValue);
if (validateResult === false) {
this.editorErrorMessage = this.inputErrorMessage || t('el.messagebox.error');
addClass(this.$refs.input.$el.querySelector('input'), 'invalid');
addClass(this.getInputElement(), 'invalid');
return false;
}
if (typeof validateResult === 'string') {
@@ -234,13 +234,17 @@
}
}
this.editorErrorMessage = '';
removeClass(this.$refs.input.$el.querySelector('input'), 'invalid');
removeClass(this.getInputElement(), 'invalid');
return true;
},
getFistFocus() {
const $btns = this.$el.querySelector('.el-message-box__btns .el-button');
const $title = this.$el.querySelector('.el-message-box__btns .el-message-box__title');
return $btns && $btns[0] || $title;
},
getInputElement() {
const inputRefs = this.$refs.input.$refs;
return inputRefs.input || inputRefs.textarea;
}
},
@@ -266,19 +270,19 @@
}
this.focusAfterClosed = document.activeElement;
messageBox = new Dialog(this.$el, this.focusAfterClosed, this.getFistFocus());
};
}
// prompt
if (this.$type !== 'prompt') return;
if (val) {
setTimeout(() => {
if (this.$refs.input && this.$refs.input.$el) {
this.$refs.input.$el.querySelector('input').focus();
this.getInputElement().focus();
}
}, 500);
} else {
this.editorErrorMessage = '';
removeClass(this.$refs.input.$el.querySelector('input'), 'invalid');
removeClass(this.getInputElement(), 'invalid');
}
}
},

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,7 +85,6 @@
if (typeof this.onClose === 'function') {
this.onClose(this);
}
this.originFocus && this.originFocus.focus(); // 键盘焦点回归
},
clearTimer() {
@@ -104,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

@@ -242,7 +242,7 @@ export default {
value={ this.$parent.internalCurrentPage }
domPropsValue={ this.$parent.internalCurrentPage }
type="number"
onInput={ this.handleChange }
onChange={ this.handleChange }
onFocus={ this.handleFocus }
onBlur={ this.handleBlur }
nativeOnKeyup={ this.handleKeyUp }/>

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() {
// 当radioGroup没有默认选项时第一个可以选中Tab导航
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)"
@@ -28,6 +33,8 @@
class="el-select__input"
:class="[selectSize ? `is-${ selectSize }` : '']"
:disabled="disabled"
@focus="handleFocus"
@click.stop
@keyup="managePlaceholder"
@keydown="resetInputState"
@keydown.down.prevent="navigateOptions('next')"
@@ -82,7 +89,7 @@
tag="ul"
wrap-class="el-select-dropdown__wrap"
view-class="el-select-dropdown__list"
:class="{ 'is-empty': !allowCreate && filteredOptionsCount === 0 }"
:class="{ 'is-empty': !allowCreate && query && filteredOptionsCount === 0 }"
v-show="options.length > 0 && !loading">
<el-option
:value="query"
@@ -164,7 +171,7 @@
return this.loadingText || this.t('el.select.loading');
} else {
if (this.remote && this.query === '' && this.options.length === 0) return false;
if (this.filterable && this.options.length > 0 && this.filteredOptionsCount === 0) {
if (this.filterable && this.query && this.options.length > 0 && this.filteredOptionsCount === 0) {
return this.noMatchText || this.t('el.select.noMatch');
}
if (this.options.length === 0) {
@@ -182,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 }`;
}
},
@@ -230,7 +245,8 @@
valueKey: {
type: String,
default: 'value'
}
},
collapseTags: Boolean
},
data() {
@@ -533,13 +549,14 @@
},
resetInputHeight() {
if (this.collapseTags) return;
this.$nextTick(() => {
if (!this.$refs.reference) return;
let inputChildNodes = this.$refs.reference.$el.childNodes;
let input = [].filter.call(inputChildNodes, item => item.tagName === 'INPUT')[0];
const tags = this.$refs.tags;
input.style.height = this.selected.length === 0 && this.selectSize === 'mini'
? sizeMap[this.selectSize] + 'px'
input.style.height = this.selected.length === 0
? sizeMap[this.selectSize] || 40 + 'px'
: Math.max(tags ? (tags.clientHeight + 10) : 0, sizeMap[this.selectSize] || 40) + 'px';
if (this.visible && this.emptyText !== false) {
this.broadcast('ElSelectDropdown', 'updatePopper');

View File

@@ -1,7 +1,7 @@
<template>
<div
class="el-step"
:style="[style, isLast ? { maxWidth: 100 / stepsCount + '%' } : { marginRight: - $parent.stepOffset + 'px' }]"
:style="style"
:class="[
!isSimple && `is-${$parent.direction}`,
isSimple && 'is-simple',
@@ -113,6 +113,7 @@ export default {
return isSimple ? '' : space ;
},
style: function() {
const style = {};
const parent = this.$parent;
const len = parent.steps.length;
@@ -121,8 +122,15 @@ export default {
: this.space
? this.space
: 100 / (len - 1) + '%');
style.flexBasis = space;
if (this.isVertical) return style;
if (this.isLast) {
style.maxWidth = 100 / this.stepsCount + '%';
} else {
style.marginRight = -this.$parent.stepOffset + 'px';
}
return { flexBasis: space };
return style;
}
},

View File

@@ -340,10 +340,10 @@ export default {
// 判断是否text-overflow, 如果是就显示tooltip
const cellChild = event.target.querySelector('.cell');
if (hasClass(cellChild, 'el-tooltip') && cellChild.scrollWidth > cellChild.offsetWidth) {
if (hasClass(cellChild, 'el-tooltip') && cellChild.scrollWidth > cellChild.offsetWidth && this.$refs.tooltip) {
const tooltip = this.$refs.tooltip;
this.tooltipContent = cell.innerText;
this.tooltipContent = cell.textContent || cell.innerText;
tooltip.referenceElm = cell;
tooltip.$refs.popper && (tooltip.$refs.popper.style.display = 'none');
tooltip.doDestroy();

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

@@ -345,7 +345,6 @@
this.updateScrollY();
this.layout.update();
this.$nextTick(() => {
if (this.destroyed) return;
if (this.height) {
this.layout.setHeight(this.height);
} else if (this.maxHeight) {
@@ -353,12 +352,6 @@
} else if (this.shouldUpdateHeight) {
this.layout.updateHeight();
}
if (this.$el) {
this.isHidden = this.$el.clientWidth === 0;
if (this.isHidden && this.layout.bodyWidth) {
setTimeout(() => this.debouncedLayout());
}
}
});
}
},
@@ -497,7 +490,6 @@
},
destroyed() {
this.destroyed = true;
if (this.windowResizeListener) removeResizeListener(this.$el, this.windowResizeListener);
},
@@ -538,8 +530,7 @@
resizeProxyVisible: false,
// 是否拥有多级表头
isGroup: false,
scrollPosition: 'left',
destroyed: false
scrollPosition: 'left'
};
}
};

View File

@@ -1,6 +1,6 @@
{
"name": "element-theme-chalk",
"version": "2.0.2",
"version": "2.0.5",
"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

@@ -16,10 +16,7 @@
font-size: $--collapse-header-size;
font-weight: 500;
transition: border-bottom-color .3s;
&:focus:not(.focusing), &:active {
outline-width: 0;
}
outline: none;
@include e(arrow) {
margin-right: 8px;
transition: transform .3s;
@@ -27,6 +24,9 @@
line-height: 48px;
font-weight: 300;
}
&.focusing:focus:not(:hover){
color: $--color-primary;
}
}
@include e(wrap) {

File diff suppressed because it is too large Load Diff

View File

@@ -5,6 +5,7 @@
flex-direction: row;
flex: 1;
box-sizing: border-box;
min-width: 0;
@include when(vertical) {
flex-direction: column;

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

@@ -2,8 +2,8 @@
@font-face {
font-family: 'element-icons';
src: url('#{$--font-path}/element-icons.woff?t=1508751886602') format('woff'), /* chrome, firefox */
url('#{$--font-path}/element-icons.ttf?t=1508751886602') format('truetype'); /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
src: url('#{$--font-path}/element-icons.woff?t=1510834658947') format('woff'), /* chrome, firefox */
url('#{$--font-path}/element-icons.ttf?t=1510834658947') format('truetype'); /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
font-weight: normal;
font-style: normal
}

View File

@@ -23,6 +23,7 @@
.el-input__inner {
text-align: center;
-moz-appearance: textfield;
}
// pagesize 的下拉 icon
@@ -35,9 +36,6 @@
width: 100px;
margin: 0 5px;
.el-input__icon {
}
.el-input__inner {
padding-right: 25px;
border-radius: $--pagination-border-radius;
@@ -149,7 +147,6 @@
margin: 0 2px;
box-sizing: border-box;
border-radius: $--pagination-border-radius;
-moz-appearance: textfield;
&.el-input {
width: 50px;

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";
@@ -62,6 +63,10 @@
}
}
}
&.is-focus .el-input__inner {
border-color: $--select-input-focus-background;
}
}
> .el-input {
@@ -75,7 +80,7 @@
margin-left: 15px;
color: $--select-multiple-input-color;
font-size: $--select-font-size;
vertical-align: baseline;
vertical-align: middle;
appearance: none;
height: 28px;
background-color: transparent;
@@ -84,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;
@@ -121,6 +134,7 @@
&__close.el-icon-close {
background-color: $--color-text-placeholder;
right: -7px;
top: 0;
color: $--color-white;
&:hover {
@@ -133,18 +147,4 @@
}
}
}
@include e(tag) {
display: inline-block;
height: $--select-tag-height;
line-height: $--select-tag-height;
font-size: $--select-font-size;
border-radius: $--border-radius-base;
color: $--select-tag-color;
background-color: $--select-tag-background;
& .el-icon-close {
font-size: $--select-input-font-size;
}
}
}

View File

@@ -140,12 +140,12 @@
@include when(vertical) {
position: relative;
.el-slider__runway {
width: 4px;
width: $--slider-height;
height: 100%;
margin: 0 16px;
}
.el-slider__bar {
width: 4px;
width: $--slider-height;
height: auto;
border-radius: 0 0 3px 3px;
}

View File

@@ -232,10 +232,6 @@
}
}
th:first-child .cell, td:first-child .cell {
padding-left: 0;
}
// 拥有多级表头
@include m((group, border)) {
border: $--table-border;
@@ -430,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

@@ -225,9 +225,16 @@
}
}
@include m((top, bottom)) {
&:not(.el-tabs--border-card):not(.el-tabs--card) .el-tabs__item:nth-child(2) {
.el-tabs__item:nth-child(2) {
padding-left: 0;
}
&.el-tabs--border-card, &.el-tabs--card,
.el-tabs--left, .el-tabs--right {
.el-tabs__item:nth-child(2) {
padding-left: 20px;
}
}
}
@include m(bottom) {
.el-tabs__header {

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

@@ -6,7 +6,7 @@
display: inline-block;
text-align: center;
cursor: pointer;
outline: none;
@include e(input) {
display: none;
}
@@ -48,6 +48,14 @@
color: $--color-primary;
}
}
&:focus {
border-color: $--color-primary;
color: $--color-primary;
.el-upload-dragger {
border-color: $--color-primary;
}
}
}
@include b(upload-dragger) {
@@ -160,11 +168,11 @@
display: none;
position: absolute;
top: 5px;
right: 0;
right: 5px;
font-size: 12px;
cursor: pointer;
opacity: 1;
color: $--color-primary;
transform: translate(15%,0);
}
&:hover {
@@ -189,20 +197,20 @@
cursor: pointer;
}
&:focus {
&:focus:not(:hover) { /* 键盘focus */
.el-icon-close-tip {
display: inline-block;
}
}
&:focus:not(.focusing), &:active {
&:not(.focusing):focus, &:active { /* click时 */
outline-width: 0;
.el-icon-close-tip {
display: none;
}
}
&:hover, &:focus { /*键盘焦点时 显示提示文字 focus*/
&:hover, &:focus {
.el-upload-list__item-status-label {
display: none;
}

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,7 +198,7 @@ export default class TreeStore {
const node = this.nodesMap[key];
if (!node) return;
const childNodes = node.childNodes;
for (let i = 0, j = childNodes.length; i < j; i++) {
for (let i = childNodes.length - 1; i >= 0; i--) {
const child = childNodes[i];
this.remove(child.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] && this.treeItems[0].setAttribute('tabindex', 0);
},
handelKeydown(ev) {
const currentItem = ev.target;
if (currentItem.className.indexOf('el-tree-node') === -1) return;
ev.preventDefault();
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) { // up、down
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) { // left、right 展开
currentItem.click(); // 选中
}
if ([13, 32].indexOf(keyCode) > -1) { // space enter选中checkbox
if (hasInput) {
hasInput.click();
}
}
}
},
@@ -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

@@ -13,7 +13,7 @@
:class="['el-upload-list__item', 'is-' + file.status, focusing ? 'focusing' : '']"
:key="index"
tabindex="0"
@keydown.delete="$emit('remove', file)"
@keydown.delete="!disabled && $emit('remove', file)"
@focus="focusing = true"
@blur="focusing = false"
@click="focusing = false"

View File

@@ -91,7 +91,8 @@ export default {
const before = this.beforeUpload(rawFile);
if (before && before.then) {
before.then(processedFile => {
if (Object.prototype.toString.call(processedFile) === '[object File]') {
const fileType = Object.prototype.toString.call(processedFile);
if (fileType === '[object File]' || fileType === '[object Blob]') {
this.post(processedFile);
} else {
this.post(rawFile);

View File

@@ -173,7 +173,7 @@ if (typeof window !== 'undefined' && window.Vue) {
};
module.exports = {
version: '2.0.2',
version: '2.0.5',
locale: locale.use,
i18n: locale.i18n,
install,
@@ -248,3 +248,5 @@ module.exports = {
Main,
Footer
};
module.exports.default = module.exports;

View File

@@ -16,6 +16,10 @@ export default {
startTime: 'Begintyd',
endDate: 'Einddatum',
endTime: 'Eindtyd',
prevYear: 'Previous Year', // to be translated
nextYear: 'Next Year', // to be translated
prevMonth: 'Previous Month', // to be translated
nextMonth: 'Next Month', // to be translated
year: 'Jaar',
month1: 'Jan',
month2: 'Feb',

View File

@@ -16,6 +16,10 @@ export default {
startTime: 'وقت البدء',
endDate: 'تاريخ الانتهاء',
endTime: 'وقت الانتهاء',
prevYear: 'Previous Year', // to be translated
nextYear: 'Next Year', // to be translated
prevMonth: 'Previous Month', // to be translated
nextMonth: 'Next Month', // to be translated
year: '',
month1: 'يناير',
month2: 'فبراير',

View File

@@ -16,6 +16,10 @@ export default {
startTime: 'Начален час',
endDate: 'Крайна дата',
endTime: 'Краен час',
prevYear: 'Previous Year', // to be translated
nextYear: 'Next Year', // to be translated
prevMonth: 'Previous Month', // to be translated
nextMonth: 'Next Month', // to be translated
year: '',
month1: 'Януари',
month2: 'Февруари',

View File

@@ -16,6 +16,10 @@ export default {
startTime: 'Hora Inici',
endDate: 'Data Final',
endTime: 'Hora Final',
prevYear: 'Previous Year', // to be translated
nextYear: 'Next Year', // to be translated
prevMonth: 'Previous Month', // to be translated
nextMonth: 'Next Month', // to be translated
year: 'Any',
month1: 'Gener',
month2: 'Febrer',

View File

@@ -16,6 +16,10 @@ export default {
startTime: 'Čas Začátku',
endDate: 'Datum Konce',
endTime: 'Čas Konce',
prevYear: 'Previous Year', // to be translated
nextYear: 'Next Year', // to be translated
prevMonth: 'Previous Month', // to be translated
nextMonth: 'Next Month', // to be translated
day: 'Den',
week: 'Týden',
month: 'Měsíc',

View File

@@ -16,6 +16,10 @@ export default {
startTime: 'Starttidspunkt',
endDate: 'Slutdato',
endTime: 'Sluttidspunkt',
prevYear: 'Previous Year', // to be translated
nextYear: 'Next Year', // to be translated
prevMonth: 'Previous Month', // to be translated
nextMonth: 'Next Month', // to be translated
year: 'År',
month1: 'Januar',
month2: 'Februar',

View File

@@ -16,6 +16,10 @@ export default {
startTime: 'Startzeit',
endDate: 'Enddatum',
endTime: 'Endzeit',
prevYear: 'Previous Year', // to be translated
nextYear: 'Next Year', // to be translated
prevMonth: 'Previous Month', // to be translated
nextMonth: 'Next Month', // to be translated
day: 'Tag',
week: 'Woche',
month: 'Monat',

View File

@@ -16,6 +16,10 @@ export default {
startTime: 'Algusaeg',
endDate: 'Lõpukuupäev',
endTime: 'Lõpuaeg',
prevYear: 'Previous Year', // to be translated
nextYear: 'Next Year', // to be translated
prevMonth: 'Previous Month', // to be translated
nextMonth: 'Next Month', // to be translated
year: '',
month1: 'Jaanuar',
month2: 'Veebruar',

Some files were not shown because too many files have changed in this diff Show More