mirror of
https://github.com/ElemeFE/element.git
synced 2025-12-16 11:44:01 +08:00
Compare commits
73 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
beec4739a3 | ||
|
|
46bd165fb1 | ||
|
|
0820daf0dd | ||
|
|
5406a97359 | ||
|
|
23e86bcf1a | ||
|
|
1af6989544 | ||
|
|
d65249e744 | ||
|
|
ecbaea7839 | ||
|
|
6f1fc76e30 | ||
|
|
217b48338f | ||
|
|
1707bae9f7 | ||
|
|
bd55a5a593 | ||
|
|
292ad8efec | ||
|
|
c7d3de95b0 | ||
|
|
2884984097 | ||
|
|
37f4ce0b30 | ||
|
|
4f00d7dea8 | ||
|
|
6db51156b1 | ||
|
|
c3cbfb1d4c | ||
|
|
d419e260d0 | ||
|
|
ed511e9219 | ||
|
|
f24aeeca00 | ||
|
|
9611079d4d | ||
|
|
8fa549894b | ||
|
|
64f154839c | ||
|
|
1833db26d8 | ||
|
|
ac39df84c0 | ||
|
|
c3ee5fc0df | ||
|
|
33bf6f9cd9 | ||
|
|
c0c0e728ca | ||
|
|
2260a3bab3 | ||
|
|
010b09891a | ||
|
|
9f2ea7eab0 | ||
|
|
aa02b42022 | ||
|
|
cbfd9cfab3 | ||
|
|
73184399ed | ||
|
|
7f8991a664 | ||
|
|
363a80b184 | ||
|
|
6c77cd9716 | ||
|
|
81011d1c48 | ||
|
|
4ea53ab896 | ||
|
|
651b517fd0 | ||
|
|
839dda529e | ||
|
|
4d71e2f3af | ||
|
|
c8477c815a | ||
|
|
38e320b8cc | ||
|
|
cee4542c36 | ||
|
|
fb066a6e45 | ||
|
|
513294d159 | ||
|
|
5e37f18166 | ||
|
|
44849f7998 | ||
|
|
a32e793845 | ||
|
|
fa522dd2bc | ||
|
|
03ccdb4fbc | ||
|
|
c30d4b11d2 | ||
|
|
eefa2c907a | ||
|
|
52bbf4f3e1 | ||
|
|
c1da7a5c86 | ||
|
|
08b80ca467 | ||
|
|
88868eebf7 | ||
|
|
9553e1edba | ||
|
|
664b3fb401 | ||
|
|
194874b3b2 | ||
|
|
aa09c460ff | ||
|
|
06112e51da | ||
|
|
6a5a3aaa2f | ||
|
|
bd545e4554 | ||
|
|
1d37197f0b | ||
|
|
343e9fa438 | ||
|
|
98bf5d7f28 | ||
|
|
2c34b3c804 | ||
|
|
4403fdc251 | ||
|
|
1582da7c53 |
@@ -6,7 +6,7 @@
|
||||
"expect": true,
|
||||
"sinon": true
|
||||
},
|
||||
"plugins": ['vue'],
|
||||
"plugins": ['vue','json'],
|
||||
"extends": 'elemefe',
|
||||
"parserOptions": {
|
||||
"ecmaFeatures": {
|
||||
|
||||
2
.github/CONTRIBUTING.en-US.md
vendored
2
.github/CONTRIBUTING.en-US.md
vendored
@@ -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
1
.gitignore
vendored
@@ -14,3 +14,4 @@ fe.element/element-ui
|
||||
coverage
|
||||
waiter.config.js
|
||||
build/bin/algolia-key.js
|
||||
.envrc
|
||||
|
||||
@@ -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*
|
||||
|
||||
@@ -1,5 +1,36 @@
|
||||
## 更新日志
|
||||
|
||||
### 2.0.5
|
||||
|
||||
*2017-11-17*
|
||||
|
||||
- 修复上个版本引入的 Popover、Tree、Breadcrumb、Cascader 的 bug,#8188 #8217 #8283
|
||||
- 修复 clickoutside 指令的内存泄露问题,#8168 #8225(by @badpunman @STLighter)
|
||||
- 修复默认尺寸的多选 Select 在清空选项后输入框高度不随之更新的问题,#8317(by @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 在解析自定义颜色时的错误,#8153(by @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
46
FAQ.md
@@ -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>
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -59,6 +59,8 @@ module.exports = {
|
||||
Loading,
|
||||
{{list}}
|
||||
};
|
||||
|
||||
module.exports.default = module.exports;
|
||||
`;
|
||||
|
||||
delete Components.font;
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
},
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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/)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 | — | — |
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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.
|
||||
:::
|
||||
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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`。
|
||||
:::
|
||||
|
||||
### 行内表单
|
||||
|
||||
当垂直方向空间受限且表单较简单时,可以在一行内放置表单。
|
||||
|
||||
@@ -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
|
||||
| 事件名称 | 说明 | 回调参数 |
|
||||
|
||||
@@ -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/)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 | — | — |
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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 | — | 请选择 |
|
||||
|
||||
@@ -2053,6 +2053,7 @@
|
||||
| setCurrentRow | 用于单选表格,设定某一行为选中行,如果调用时不加参数,则会取消目前高亮行的选中状态。 | row |
|
||||
| clearSort | 用于清空排序条件,数据会恢复成未排序的状态 | — |
|
||||
| clearFilter | 用于清空过滤条件,数据会恢复成未过滤的状态 | — |
|
||||
| doLayout | 对 Table 进行重新布局。当 Table 或其祖先元素由隐藏切换为显示时,可能需要调用此方法 | — |
|
||||
|
||||
### Table Slot
|
||||
| name | 说明 |
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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": [
|
||||
|
||||
@@ -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"}
|
||||
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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';
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
'el-dropdown-menu__item--divided': divided
|
||||
}"
|
||||
@click="handleClick"
|
||||
:aria-disabled="disabled"
|
||||
:tabindex="disabled ? null : -1"
|
||||
>
|
||||
<slot></slot>
|
||||
</li>
|
||||
|
||||
@@ -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') {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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 }/>
|
||||
|
||||
@@ -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(() => {
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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>
|
||||
: ''
|
||||
}
|
||||
|
||||
@@ -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'
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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": {}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -5,6 +5,7 @@
|
||||
flex-direction: row;
|
||||
flex: 1;
|
||||
box-sizing: border-box;
|
||||
min-width: 0;
|
||||
|
||||
@include when(vertical) {
|
||||
flex-direction: column;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -27,4 +27,10 @@
|
||||
line-height: 1;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
@include e(reference) {
|
||||
&:focus:not(.focusing), &:focus:hover {
|
||||
outline-width: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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}`;
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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: 'فبراير',
|
||||
|
||||
@@ -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: 'Февруари',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user