Commit af4387600728996f0d7d8f89a563e08295f8d271

Authored by Lawrence Lee
Committed by GitHub
2 parents 1c82a9ab 9c83f0e5

Merge pull request #2 from iview/2.0

Merge
@@ -4,7 +4,14 @@ @@ -4,7 +4,14 @@
4 </a> 4 </a>
5 </p> 5 </p>
6 6
7 -# iView [![](https://img.shields.io/travis/iview/iview.svg?style=flat-square)](https://travis-ci.org/iview/iview) [![iView](https://img.shields.io/npm/v/iview.svg?style=flat-square)](https://www.npmjs.org/package/iview) [![NPM downloads](http://img.shields.io/npm/dm/iview.svg?style=flat-square)](https://npmjs.org/package/iview) [![Join the chat at https://gitter.im/iview/iview](https://img.shields.io/badge/chat-on_gitter-30b392.svg?style=flat-square)](https://gitter.im/iview/iview?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 7 +# iView
  8 +[![](https://img.shields.io/travis/iview/iview.svg?style=flat-square)](https://travis-ci.org/iview/iview)
  9 +[![iView](https://img.shields.io/npm/v/iview.svg?style=flat-square)](https://www.npmjs.org/package/iview)
  10 +[![NPM downloads](http://img.shields.io/npm/dm/iview.svg?style=flat-square)](https://npmjs.org/package/iview)
  11 +[![NPM downloads](https://img.shields.io/npm/dt/iview.svg?style=flat-square)](https://npmjs.org/package/iview)
  12 +![JS gzip size](http://img.badgesize.io/https://unpkg.com/iview/dist/iview.min.js?compression=gzip&label=gzip%20size:%20JS&style=flat-square)
  13 +![CSS gzip size](http://img.badgesize.io/https://unpkg.com/iview/dist/styles/iview.css?compression=gzip&label=gzip%20size:%20CSS&style=flat-square)
  14 +[![Join the chat at https://gitter.im/iview/iview](https://img.shields.io/badge/chat-on_gitter-30b392.svg?style=flat-square)](https://gitter.im/iview/iview?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
8 15
9 ### A high quality UI Toolkit built on Vue.js. 16 ### A high quality UI Toolkit built on Vue.js.
10 17
@@ -82,6 +89,7 @@ Normal browsers and Internet Explorer 9+. @@ -82,6 +89,7 @@ Normal browsers and Internet Explorer 9+.
82 | [Aresn](https://github.com/icarusion) | ![](https://avatars3.githubusercontent.com/u/5370542?v=3&s=60) | 89 | [Aresn](https://github.com/icarusion) | ![](https://avatars3.githubusercontent.com/u/5370542?v=3&s=60) |
83 | [jingsam](https://github.com/jingsam) | ![](https://avatars3.githubusercontent.com/u/1522494?v=3&s=60) | 90 | [jingsam](https://github.com/jingsam) | ![](https://avatars3.githubusercontent.com/u/1522494?v=3&s=60) |
84 | [rijn](https://github.com/rijn) | ![](https://avatars2.githubusercontent.com/u/6976367?v=3&s=60) | 91 | [rijn](https://github.com/rijn) | ![](https://avatars2.githubusercontent.com/u/6976367?v=3&s=60) |
  92 +| [lcx960324](https://github.com/lcx960324) | ![](https://avatars3.githubusercontent.com/u/9768245?v=3&s=60) |
85 | [GITleonine1989](https://github.com/GITleonine1989) | ![](https://avatars1.githubusercontent.com/u/7582490?v=3&s=60) | 93 | [GITleonine1989](https://github.com/GITleonine1989) | ![](https://avatars1.githubusercontent.com/u/7582490?v=3&s=60) |
86 | [huixisheng](https://github.com/huixisheng) | ![](https://avatars1.githubusercontent.com/u/1518967?v=3&s=60) | 94 | [huixisheng](https://github.com/huixisheng) | ![](https://avatars1.githubusercontent.com/u/1518967?v=3&s=60) |
87 95
examples/routers/badge.vue
@@ -14,37 +14,24 @@ @@ -14,37 +14,24 @@
14 </style> 14 </style>
15 <template> 15 <template>
16 <div> 16 <div>
17 - <Badge count="3"> 17 + <Badge dot :count="count">
18 <a href="#" class="demo-badge"></a> 18 <a href="#" class="demo-badge"></a>
19 </Badge> 19 </Badge>
20 - <Badge dot>  
21 - <a href="#" class="demo-badge"></a>  
22 - </Badge>  
23 - <Badge dot>  
24 - <Icon type="ios-bell-outline" size="26"></Icon>  
25 - </Badge>  
26 - <Badge dot>  
27 - <a href="#">可以是一个链接</a>  
28 - </Badge>  
29 - <Badge count="100">  
30 - <a href="#" class="demo-badge"></a>  
31 - </Badge>  
32 - <Badge count="1000" overflow-count="999">  
33 - <a href="#" class="demo-badge"></a>  
34 - </Badge>  
35 - <br>  
36 - <Badge count="10"></Badge>  
37 - <br><br>  
38 - <Badge count="20" class-name="demo-badge-alone"></Badge> 20 + <Button @click="setCount">set count</Button>
39 </div> 21 </div>
40 </template> 22 </template>
41 <script> 23 <script>
42 export default { 24 export default {
43 props: {}, 25 props: {},
44 data () { 26 data () {
45 - return {}; 27 + return {
  28 + count: 50
  29 + };
46 }, 30 },
47 - computed: {},  
48 - methods: {} 31 + methods: {
  32 + setCount () {
  33 + this.count = 10;
  34 + }
  35 + }
49 }; 36 };
50 </script> 37 </script>
51 \ No newline at end of file 38 \ No newline at end of file
examples/routers/form.vue
@@ -2,12 +2,7 @@ @@ -2,12 +2,7 @@
2 <div style="width: 300px;"> 2 <div style="width: 300px;">
3 <i-form ref="formValidate" :model="formValidate" :rules="ruleValidate" :label-width="80"> 3 <i-form ref="formValidate" :model="formValidate" :rules="ruleValidate" :label-width="80">
4 <Form-item label="爱好" prop="interest"> 4 <Form-item label="爱好" prop="interest">
5 - <Checkbox-group v-model="formValidate.interest">  
6 - <Checkbox label="吃饭"></Checkbox>  
7 - <Checkbox label="睡觉"></Checkbox>  
8 - <Checkbox label="跑步"></Checkbox>  
9 - <Checkbox label="看电影"></Checkbox>  
10 - </Checkbox-group> 5 + <Input v-model="formValidate.interest" number></Input>
11 </Form-item> 6 </Form-item>
12 <Form-item> 7 <Form-item>
13 <i-button type="primary" @click="handleSubmit('formValidate')">提交</i-button> 8 <i-button type="primary" @click="handleSubmit('formValidate')">提交</i-button>
@@ -21,12 +16,15 @@ @@ -21,12 +16,15 @@
21 data () { 16 data () {
22 return { 17 return {
23 formValidate: { 18 formValidate: {
24 - interest: ['吃饭', '跑步'] 19 + interest: ''
25 }, 20 },
26 ruleValidate: { 21 ruleValidate: {
27 interest: [ 22 interest: [
28 - { required: true, type: 'array', min: 1, message: '至少选择一个爱好', trigger: 'change' },  
29 - { type: 'array', max: 2, message: '最多选择两个爱好', trigger: 'change' } 23 + {
  24 + required: true,
  25 + type: 'number',
  26 + trigger: 'change'
  27 + }
30 ] 28 ]
31 } 29 }
32 } 30 }
examples/routers/menu.vue
1 <template> 1 <template>
2 <div> 2 <div>
3 - <Menu mode="horizontal" :theme="theme1" @on-select="s">  
4 - <Row type="flex" justify="center" align="middle">  
5 - <i-col span="12">  
6 - <Menu-item name="1"> 3 + <Row>
  4 + <i-col span="8">
  5 + <Menu :theme="theme2">
  6 + <Submenu name="1">
  7 + <template slot="title">
7 <Icon type="ios-paper"></Icon> 8 <Icon type="ios-paper"></Icon>
8 内容管理 9 内容管理
9 - </Menu-item>  
10 - <Menu-item name="2"> 10 + </template>
  11 + <Menu-item name="1-1">文章管理</Menu-item>
  12 + <Menu-item name="1-2">评论管理</Menu-item>
  13 + <Menu-item name="1-3">举报管理</Menu-item>
  14 + </Submenu>
  15 + <Submenu name="2">
  16 + <template slot="title">
11 <Icon type="ios-people"></Icon> 17 <Icon type="ios-people"></Icon>
12 用户管理 18 用户管理
13 - </Menu-item>  
14 - <Submenu name="3">  
15 - <template slot="title">  
16 - <Icon type="stats-bars"></Icon>  
17 - 统计分析  
18 - </template>  
19 - <Menu-group title="使用">  
20 - <Menu-item name="3-1">新增和启动</Menu-item>  
21 - <Menu-item name="3-2">活跃分析</Menu-item>  
22 - <Menu-item name="3-3">时段分析</Menu-item>  
23 - </Menu-group>  
24 - <Menu-group title="留存">  
25 - <Menu-item name="3-4">用户留存</Menu-item>  
26 - <Menu-item name="3-5">流失用户</Menu-item>  
27 - </Menu-group>  
28 - </Submenu>  
29 - <Menu-item name="4">  
30 - <Icon type="settings"></Icon>  
31 - 综合设置  
32 - </Menu-item>  
33 - </i-col>  
34 - </Row>  
35 - </Menu> 19 + </template>
  20 + <Menu-item name="2-1">新增用户</Menu-item>
  21 + <Menu-item name="2-2">活跃用户</Menu-item>
  22 + </Submenu>
  23 + <Submenu name="3">
  24 + <template slot="title">
  25 + <Icon type="stats-bars"></Icon>
  26 + 统计分析
  27 + </template>
  28 + <Menu-group title="使用">
  29 + <Menu-item name="3-1">新增和启动</Menu-item>
  30 + <Menu-item name="3-2">活跃分析</Menu-item>
  31 + <Menu-item name="3-3">时段分析</Menu-item>
  32 + </Menu-group>
  33 + <Menu-group title="留存">
  34 + <Menu-item name="3-4">用户留存</Menu-item>
  35 + <Menu-item name="3-5">流失用户</Menu-item>
  36 + </Menu-group>
  37 + </Submenu>
  38 + </Menu>
  39 + </i-col>
  40 + </Row>
36 <br> 41 <br>
37 <p>切换主题</p> 42 <p>切换主题</p>
38 - <Radio-group v-model="theme1"> 43 + <Radio-group v-model="theme2">
39 <Radio label="light"></Radio> 44 <Radio label="light"></Radio>
40 <Radio label="dark"></Radio> 45 <Radio label="dark"></Radio>
41 - <Radio label="primary"></Radio>  
42 </Radio-group> 46 </Radio-group>
43 </div> 47 </div>
44 </template> 48 </template>
@@ -46,149 +50,8 @@ @@ -46,149 +50,8 @@
46 export default { 50 export default {
47 data () { 51 data () {
48 return { 52 return {
49 - theme1: 'light'  
50 - }  
51 - },  
52 - methods: {  
53 - s (s) {  
54 - console.log(s) 53 + theme2: 'light'
55 } 54 }
56 } 55 }
57 } 56 }
58 </script> 57 </script>
59 -  
60 -  
61 -<!--<template>-->  
62 - <!--<div>-->  
63 - <!--<Row>-->  
64 - <!--<i-col span="8">-->  
65 - <!--<Menu :theme="theme2" @on-select="s">-->  
66 - <!--<Submenu name="1">-->  
67 - <!--<template slot="title">-->  
68 - <!--<Icon type="ios-paper"></Icon>-->  
69 - <!--内容管理-->  
70 - <!--</template>-->  
71 - <!--<Menu-item name="1-1">文章管理</Menu-item>-->  
72 - <!--<Menu-item name="1-2">评论管理</Menu-item>-->  
73 - <!--<Menu-item name="1-3">举报管理</Menu-item>-->  
74 - <!--</Submenu>-->  
75 - <!--<Submenu name="2">-->  
76 - <!--<template slot="title">-->  
77 - <!--<Icon type="ios-people"></Icon>-->  
78 - <!--用户管理-->  
79 - <!--</template>-->  
80 - <!--<Menu-item name="2-1">新增用户</Menu-item>-->  
81 - <!--<Menu-item name="2-2">活跃用户</Menu-item>-->  
82 - <!--</Submenu>-->  
83 - <!--<Submenu name="3">-->  
84 - <!--<template slot="title">-->  
85 - <!--<Icon type="stats-bars"></Icon>-->  
86 - <!--统计分析-->  
87 - <!--</template>-->  
88 - <!--<Menu-group title="使用">-->  
89 - <!--<Menu-item name="3-1">新增和启动</Menu-item>-->  
90 - <!--<Menu-item name="3-2">活跃分析</Menu-item>-->  
91 - <!--<Menu-item name="3-3">时段分析</Menu-item>-->  
92 - <!--</Menu-group>-->  
93 - <!--<Menu-group title="留存">-->  
94 - <!--<Menu-item name="3-4">用户留存</Menu-item>-->  
95 - <!--<Menu-item name="3-5">流失用户</Menu-item>-->  
96 - <!--</Menu-group>-->  
97 - <!--</Submenu>-->  
98 - <!--</Menu>-->  
99 - <!--</i-col>-->  
100 - <!--<i-col span="8">-->  
101 - <!--<Menu :theme="theme2" active-name="1-2" :open-names="['1']" @on-select="s">-->  
102 - <!--<Submenu name="1">-->  
103 - <!--<template slot="title">-->  
104 - <!--<Icon type="ios-paper"></Icon>-->  
105 - <!--内容管理-->  
106 - <!--</template>-->  
107 - <!--<Menu-item name="1-1">文章管理</Menu-item>-->  
108 - <!--<Menu-item name="1-2">评论管理</Menu-item>-->  
109 - <!--<Menu-item name="1-3">举报管理</Menu-item>-->  
110 - <!--</Submenu>-->  
111 - <!--<Submenu name="2">-->  
112 - <!--<template slot="title">-->  
113 - <!--<Icon type="ios-people"></Icon>-->  
114 - <!--用户管理-->  
115 - <!--</template>-->  
116 - <!--<Menu-item name="2-1">新增用户</Menu-item>-->  
117 - <!--<Menu-item name="2-2">活跃用户</Menu-item>-->  
118 - <!--</Submenu>-->  
119 - <!--<Submenu name="3">-->  
120 - <!--<template slot="title">-->  
121 - <!--<Icon type="stats-bars"></Icon>-->  
122 - <!--统计分析-->  
123 - <!--</template>-->  
124 - <!--<Menu-group title="使用">-->  
125 - <!--<Menu-item name="3-1">新增和启动</Menu-item>-->  
126 - <!--<Menu-item name="3-2">活跃分析</Menu-item>-->  
127 - <!--<Menu-item name="3-3">时段分析</Menu-item>-->  
128 - <!--</Menu-group>-->  
129 - <!--<Menu-group title="留存">-->  
130 - <!--<Menu-item name="3-4">用户留存</Menu-item>-->  
131 - <!--<Menu-item name="3-5">流失用户</Menu-item>-->  
132 - <!--</Menu-group>-->  
133 - <!--</Submenu>-->  
134 - <!--</Menu>-->  
135 - <!--</i-col>-->  
136 - <!--<i-col span="8">-->  
137 - <!--<Menu :theme="theme2" :open-names="['1']" accordion @on-select="s">-->  
138 - <!--<Submenu name="1">-->  
139 - <!--<template slot="title">-->  
140 - <!--<Icon type="ios-paper"></Icon>-->  
141 - <!--内容管理-->  
142 - <!--</template>-->  
143 - <!--<Menu-item name="1-1">文章管理</Menu-item>-->  
144 - <!--<Menu-item name="1-2">评论管理</Menu-item>-->  
145 - <!--<Menu-item name="1-3">举报管理</Menu-item>-->  
146 - <!--</Submenu>-->  
147 - <!--<Submenu name="2">-->  
148 - <!--<template slot="title">-->  
149 - <!--<Icon type="ios-people"></Icon>-->  
150 - <!--用户管理-->  
151 - <!--</template>-->  
152 - <!--<Menu-item name="2-1">新增用户</Menu-item>-->  
153 - <!--<Menu-item name="2-2">活跃用户</Menu-item>-->  
154 - <!--</Submenu>-->  
155 - <!--<Submenu name="3">-->  
156 - <!--<template slot="title">-->  
157 - <!--<Icon type="stats-bars"></Icon>-->  
158 - <!--统计分析-->  
159 - <!--</template>-->  
160 - <!--<Menu-group title="使用">-->  
161 - <!--<Menu-item name="3-1">新增和启动</Menu-item>-->  
162 - <!--<Menu-item name="3-2">活跃分析</Menu-item>-->  
163 - <!--<Menu-item name="3-3">时段分析</Menu-item>-->  
164 - <!--</Menu-group>-->  
165 - <!--<Menu-group title="留存">-->  
166 - <!--<Menu-item name="3-4">用户留存</Menu-item>-->  
167 - <!--<Menu-item name="3-5">流失用户</Menu-item>-->  
168 - <!--</Menu-group>-->  
169 - <!--</Submenu>-->  
170 - <!--</Menu>-->  
171 - <!--</i-col>-->  
172 - <!--</Row>-->  
173 - <!--<br>-->  
174 - <!--<p>切换主题</p>-->  
175 - <!--<Radio-group v-model="theme2">-->  
176 - <!--<Radio label="light"></Radio>-->  
177 - <!--<Radio label="dark"></Radio>-->  
178 - <!--</Radio-group>-->  
179 - <!--</div>-->  
180 -<!--</template>-->  
181 -<!--<script>-->  
182 - <!--export default {-->  
183 - <!--data () {-->  
184 - <!--return {-->  
185 - <!--theme2: 'light'-->  
186 - <!--}-->  
187 - <!--},-->  
188 - <!--methods: {-->  
189 - <!--s (s) {-->  
190 - <!--console.log(s);-->  
191 - <!--}-->  
192 - <!--}-->  
193 - <!--}-->  
194 -<!--</script>-->  
examples/routers/modal.vue
1 <template> 1 <template>
2 <div> 2 <div>
  3 + {{ val }}
3 <Button @click="confirm">标准</Button> 4 <Button @click="confirm">标准</Button>
4 <Button @click="custom">自定义按钮文字</Button> 5 <Button @click="custom">自定义按钮文字</Button>
5 <Button @click="async">异步关闭</Button> 6 <Button @click="async">异步关闭</Button>
  7 + <Button type="primary" @click="modal1 = true">显示对话框</Button>
  8 + <Modal
  9 + v-model="modal1"
  10 + title="普通的Modal对话框标题"
  11 + @on-ok="ok"
  12 + @on-cancel="cancel">
  13 + <p>对话框内容</p>
  14 + <p>对话框内容</p>
  15 + <p>对话框内容</p>
  16 + </Modal>
6 </div> 17 </div>
7 </template> 18 </template>
8 <script> 19 <script>
9 export default { 20 export default {
  21 + data () {
  22 + return {
  23 + modal1: false,
  24 + val: ''
  25 + }
  26 + },
10 methods: { 27 methods: {
  28 + ok () {
  29 + this.$Message.info('点击了确定');
  30 + },
  31 + cancel () {
  32 + this.$Message.info('点击了取消');
  33 + },
11 confirm () { 34 confirm () {
12 this.$Modal.confirm({ 35 this.$Modal.confirm({
13 title: '确认对话框标题', 36 title: '确认对话框标题',
14 content: '<p>一些对话框内容</p><p>一些对话框内容</p>', 37 content: '<p>一些对话框内容</p><p>一些对话框内容</p>',
  38 + render: (h) => {
  39 + return h('Input', {
  40 + props: {
  41 + value: this.val,
  42 + autofocus: true
  43 + },
  44 + on: {
  45 + input: (val) => {
  46 + this.val = val;
  47 + }
  48 + }
  49 + }, '一个按钮')
  50 + },
15 onOk: () => { 51 onOk: () => {
16 this.$Message.info('点击了确定'); 52 this.$Message.info('点击了确定');
17 }, 53 },
examples/routers/table.vue
@@ -84,7 +84,8 @@ @@ -84,7 +84,8 @@
84 { 84 {
85 name: '张小刚', 85 name: '张小刚',
86 age: 25, 86 age: 25,
87 - address: '北京市海淀区西二旗' 87 + address: '北京市海淀区西二旗',
  88 + _disableExpand: true
88 }, 89 },
89 { 90 {
90 name: '李小红', 91 name: '李小红',
examples/routers/tabs.vue
1 <template> 1 <template>
2 - <Tabs value="name1" :animated="false">  
3 - <Tab-pane label="标签一" name="name1"> 2 + <Tabs value="name1" :animated="true">
  3 + <Tab-pane :label="label1" name="name1">
4 <Table :columns="columns1" :data="data1"></Table> 4 <Table :columns="columns1" :data="data1"></Table>
5 </Tab-pane> 5 </Tab-pane>
6 <Tab-pane label="标签二" name="name2"> 6 <Tab-pane label="标签二" name="name2">
@@ -15,6 +15,12 @@ @@ -15,6 +15,12 @@
15 export default { 15 export default {
16 data () { 16 data () {
17 return { 17 return {
  18 + label1: (h) => {
  19 + return h('div', [
  20 + h('span', '标签一'),
  21 + h('Button', 'button')
  22 + ]);
  23 + },
18 columns1: [ 24 columns1: [
19 { 25 {
20 title: '姓名', 26 title: '姓名',
1 { 1 {
2 "name": "iview", 2 "name": "iview",
3 - "version": "2.0.0-rc.15", 3 + "version": "2.0.0-rc.16",
4 "title": "iView", 4 "title": "iView",
5 "description": "A high quality UI components Library with Vue.js", 5 "description": "A high quality UI components Library with Vue.js",
6 "homepage": "http://www.iviewui.com", 6 "homepage": "http://www.iviewui.com",
src/components/badge/badge.vue
@@ -61,17 +61,9 @@ @@ -61,17 +61,9 @@
61 } 61 }
62 62
63 return status; 63 return status;
64 - }  
65 - },  
66 - data () {  
67 - return {  
68 - alone: false  
69 - };  
70 - },  
71 - mounted () {  
72 - const child_length = this.$refs.badge.children.length;  
73 - if (child_length === 1) {  
74 - this.alone = true; 64 + },
  65 + alone () {
  66 + return this.$slots.default === undefined;
75 } 67 }
76 } 68 }
77 }; 69 };
src/components/base/collapse-transition.js 0 → 100644
  1 +// Thanks to https://github.com/ElemeFE/element/blob/dev/src/transitions/collapse-transition.js
  2 +
  3 +import { addClass, removeClass } from '../../utils/assist';
  4 +
  5 +const Transition = {
  6 + beforeEnter(el) {
  7 + addClass(el, 'collapse-transition');
  8 + if (!el.dataset) el.dataset = {};
  9 +
  10 + el.dataset.oldPaddingTop = el.style.paddingTop;
  11 + el.dataset.oldPaddingBottom = el.style.paddingBottom;
  12 +
  13 + el.style.height = '0';
  14 + el.style.paddingTop = 0;
  15 + el.style.paddingBottom = 0;
  16 + },
  17 +
  18 + enter(el) {
  19 + el.dataset.oldOverflow = el.style.overflow;
  20 + if (el.scrollHeight !== 0) {
  21 + el.style.height = el.scrollHeight + 'px';
  22 + el.style.paddingTop = el.dataset.oldPaddingTop;
  23 + el.style.paddingBottom = el.dataset.oldPaddingBottom;
  24 + } else {
  25 + el.style.height = '';
  26 + el.style.paddingTop = el.dataset.oldPaddingTop;
  27 + el.style.paddingBottom = el.dataset.oldPaddingBottom;
  28 + }
  29 +
  30 + el.style.overflow = 'hidden';
  31 + },
  32 +
  33 + afterEnter(el) {
  34 + // for safari: remove class then reset height is necessary
  35 + removeClass(el, 'collapse-transition');
  36 + el.style.height = '';
  37 + el.style.overflow = el.dataset.oldOverflow;
  38 + },
  39 +
  40 + beforeLeave(el) {
  41 + if (!el.dataset) el.dataset = {};
  42 + el.dataset.oldPaddingTop = el.style.paddingTop;
  43 + el.dataset.oldPaddingBottom = el.style.paddingBottom;
  44 + el.dataset.oldOverflow = el.style.overflow;
  45 +
  46 + el.style.height = el.scrollHeight + 'px';
  47 + el.style.overflow = 'hidden';
  48 + },
  49 +
  50 + leave(el) {
  51 + if (el.scrollHeight !== 0) {
  52 + // for safari: add class after set height, or it will jump to zero height suddenly, weired
  53 + addClass(el, 'collapse-transition');
  54 + el.style.height = 0;
  55 + el.style.paddingTop = 0;
  56 + el.style.paddingBottom = 0;
  57 + }
  58 + },
  59 +
  60 + afterLeave(el) {
  61 + removeClass(el, 'collapse-transition');
  62 + el.style.height = '';
  63 + el.style.overflow = el.dataset.oldOverflow;
  64 + el.style.paddingTop = el.dataset.oldPaddingTop;
  65 + el.style.paddingBottom = el.dataset.oldPaddingBottom;
  66 + }
  67 +};
  68 +
  69 +export default {
  70 + name: 'CollapseTransition',
  71 + functional: true,
  72 + render(h, { children }) {
  73 + const data = {
  74 + on: Transition
  75 + };
  76 +
  77 + return h('transition', data, children);
  78 + }
  79 +};
src/components/base/render.vue 0 → 100644
  1 +<template>
  2 + <div ref="cell"></div>
  3 +</template>
  4 +<script>
  5 + import Vue from 'vue';
  6 + export default {
  7 + name: 'RenderCell',
  8 + props: {
  9 + render: Function
  10 + },
  11 + methods: {
  12 + compile () {
  13 + if (this.render) {
  14 + this.$el.innerHTML = '';
  15 + const component = new Vue({
  16 + functional: true,
  17 + render: (h) => {
  18 + return this.render(h);
  19 + }
  20 + });
  21 + const Cell = component.$mount();
  22 + this.$refs.cell.appendChild(Cell.$el);
  23 + }
  24 + }
  25 + },
  26 + mounted () {
  27 + this.compile();
  28 + }
  29 + };
  30 +</script>
0 \ No newline at end of file 31 \ No newline at end of file
src/components/checkbox/checkbox.vue
@@ -105,7 +105,7 @@ @@ -105,7 +105,7 @@
105 this.$emit('input', checked); 105 this.$emit('input', checked);
106 106
107 if (this.group) { 107 if (this.group) {
108 - this.$parent.change(this.model); 108 + this.parent.change(this.model);
109 } else { 109 } else {
110 this.$emit('on-change', checked); 110 this.$emit('on-change', checked);
111 this.dispatch('FormItem', 'on-form-change', checked); 111 this.dispatch('FormItem', 'on-form-change', checked);
src/components/collapse/panel.vue
@@ -4,18 +4,21 @@ @@ -4,18 +4,21 @@
4 <Icon type="arrow-right-b"></Icon> 4 <Icon type="arrow-right-b"></Icon>
5 <slot></slot> 5 <slot></slot>
6 </div> 6 </div>
7 - <div :class="contentClasses" v-show="isActive">  
8 - <div :class="boxClasses"><slot name="content"></slot></div>  
9 - </div> 7 + <collapse-transition>
  8 + <div :class="contentClasses" v-show="isActive">
  9 + <div :class="boxClasses"><slot name="content"></slot></div>
  10 + </div>
  11 + </collapse-transition>
10 </div> 12 </div>
11 </template> 13 </template>
12 <script> 14 <script>
13 import Icon from '../icon/icon.vue'; 15 import Icon from '../icon/icon.vue';
  16 + import CollapseTransition from '../base/collapse-transition';
14 const prefixCls = 'ivu-collapse'; 17 const prefixCls = 'ivu-collapse';
15 18
16 export default { 19 export default {
17 name: 'Panel', 20 name: 'Panel',
18 - components: { Icon }, 21 + components: { Icon, CollapseTransition },
19 props: { 22 props: {
20 name: { 23 name: {
21 type: String 24 type: String
src/components/loading-bar/loading-bar.js
@@ -31,9 +31,7 @@ LoadingBar.newInstance = properties =&gt; { @@ -31,9 +31,7 @@ LoadingBar.newInstance = properties =&gt; {
31 }, 31 },
32 component: loading_bar, 32 component: loading_bar,
33 destroy () { 33 destroy () {
34 - setTimeout(function() {  
35 - document.body.removeChild(document.getElementsByClassName('ivu-loading-bar')[0].parentElement);  
36 - }, 500); 34 + document.body.removeChild(document.getElementsByClassName('ivu-loading-bar')[0]);
37 } 35 }
38 }; 36 };
39 }; 37 };
src/components/menu/submenu.vue
@@ -4,7 +4,9 @@ @@ -4,7 +4,9 @@
4 <slot name="title"></slot> 4 <slot name="title"></slot>
5 <Icon type="ios-arrow-down" :class="[prefixCls + '-submenu-title-icon']"></Icon> 5 <Icon type="ios-arrow-down" :class="[prefixCls + '-submenu-title-icon']"></Icon>
6 </div> 6 </div>
7 - <ul :class="[prefixCls]" v-if="mode === 'vertical'" v-show="opened"><slot></slot></ul> 7 + <collapse-transition v-if="mode === 'vertical'">
  8 + <ul :class="[prefixCls]" v-show="opened"><slot></slot></ul>
  9 + </collapse-transition>
8 <transition name="slide-up" v-else> 10 <transition name="slide-up" v-else>
9 <Drop 11 <Drop
10 v-show="opened" 12 v-show="opened"
@@ -17,6 +19,7 @@ @@ -17,6 +19,7 @@
17 <script> 19 <script>
18 import Drop from '../select/dropdown.vue'; 20 import Drop from '../select/dropdown.vue';
19 import Icon from '../icon/icon.vue'; 21 import Icon from '../icon/icon.vue';
  22 + import CollapseTransition from '../base/collapse-transition';
20 import { getStyle, findComponentUpward } from '../../utils/assist'; 23 import { getStyle, findComponentUpward } from '../../utils/assist';
21 import Emitter from '../../mixins/emitter'; 24 import Emitter from '../../mixins/emitter';
22 25
@@ -25,7 +28,7 @@ @@ -25,7 +28,7 @@
25 export default { 28 export default {
26 name: 'Submenu', 29 name: 'Submenu',
27 mixins: [ Emitter ], 30 mixins: [ Emitter ],
28 - components: { Icon, Drop }, 31 + components: { Icon, Drop, CollapseTransition },
29 props: { 32 props: {
30 name: { 33 name: {
31 type: [String, Number], 34 type: [String, Number],
src/components/modal/confirm.js
@@ -8,31 +8,6 @@ const prefixCls = &#39;ivu-modal-confirm&#39;; @@ -8,31 +8,6 @@ const prefixCls = &#39;ivu-modal-confirm&#39;;
8 Modal.newInstance = properties => { 8 Modal.newInstance = properties => {
9 const _props = properties || {}; 9 const _props = properties || {};
10 10
11 - // let props = '';  
12 - // Object.keys(_props).forEach(prop => {  
13 - // props += ' :' + camelcaseToHyphen(prop) + '=' + prop;  
14 - // });  
15 - //  
16 - // const div = document.createElement('div');  
17 - // div.innerHTML = `  
18 - // <Modal${props} v-model="visible" :width="width" :scrollable="scrollable">  
19 - // <div class="${prefixCls}">  
20 - // <div class="${prefixCls}-head">  
21 - // <div class="${prefixCls}-head-title" v-html="title"></div>  
22 - // </div>  
23 - // <div class="${prefixCls}-body">  
24 - // <div :class="iconTypeCls"><i :class="iconNameCls"></i></div>  
25 - // <div v-html="body"></div>  
26 - // </div>  
27 - // <div class="${prefixCls}-footer">  
28 - // <i-button type="text" size="large" v-if="showCancel" @click.native="cancel">{{ localeCancelText }}</i-button>  
29 - // <i-button type="primary" size="large" :loading="buttonLoading" @click.native="ok">{{ localeOkText }}</i-button>  
30 - // </div>  
31 - // </div>  
32 - // </Modal>  
33 - // `;  
34 - // document.body.appendChild(div);  
35 -  
36 const Instance = new Vue({ 11 const Instance = new Vue({
37 mixins: [ Locale ], 12 mixins: [ Locale ],
38 data: Object.assign({}, _props, { 13 data: Object.assign({}, _props, {
@@ -73,6 +48,35 @@ Modal.newInstance = properties =&gt; { @@ -73,6 +48,35 @@ Modal.newInstance = properties =&gt; {
73 } 48 }
74 }, this.localeOkText)); 49 }, this.localeOkText));
75 50
  51 + // render content
  52 + let body_render;
  53 + if (this.render) {
  54 + body_render = h('div', {
  55 + attrs: {
  56 + class: `${prefixCls}-body ${prefixCls}-body-render`
  57 + }
  58 + }, [this.render(h)]);
  59 + } else {
  60 + body_render = h('div', {
  61 + attrs: {
  62 + class: `${prefixCls}-body`
  63 + }
  64 + }, [
  65 + h('div', {
  66 + class: this.iconTypeCls
  67 + }, [
  68 + h('i', {
  69 + class: this.iconNameCls
  70 + })
  71 + ]),
  72 + h('div', {
  73 + domProps: {
  74 + innerHTML: this.body
  75 + }
  76 + })
  77 + ]);
  78 + }
  79 +
76 return h(Modal, { 80 return h(Modal, {
77 props: Object.assign({}, _props, { 81 props: Object.assign({}, _props, {
78 width: this.width, 82 width: this.width,
@@ -106,24 +110,7 @@ Modal.newInstance = properties =&gt; { @@ -106,24 +110,7 @@ Modal.newInstance = properties =&gt; {
106 } 110 }
107 }) 111 })
108 ]), 112 ]),
109 - h('div', {  
110 - attrs: {  
111 - class: `${prefixCls}-body`  
112 - }  
113 - }, [  
114 - h('div', {  
115 - class: this.iconTypeCls  
116 - }, [  
117 - h('i', {  
118 - class: this.iconNameCls  
119 - })  
120 - ]),  
121 - h('div', {  
122 - domProps: {  
123 - innerHTML: this.body  
124 - }  
125 - })  
126 - ]), 113 + body_render,
127 h('div', { 114 h('div', {
128 attrs: { 115 attrs: {
129 class: `${prefixCls}-footer` 116 class: `${prefixCls}-footer`
src/components/modal/index.js
@@ -2,18 +2,20 @@ import Modal from &#39;./confirm&#39;; @@ -2,18 +2,20 @@ import Modal from &#39;./confirm&#39;;
2 2
3 let modalInstance; 3 let modalInstance;
4 4
5 -function getModalInstance () { 5 +function getModalInstance (render = undefined) {
6 modalInstance = modalInstance || Modal.newInstance({ 6 modalInstance = modalInstance || Modal.newInstance({
7 closable: false, 7 closable: false,
8 maskClosable: false, 8 maskClosable: false,
9 - footerHide: true 9 + footerHide: true,
  10 + render: render
10 }); 11 });
11 12
12 return modalInstance; 13 return modalInstance;
13 } 14 }
14 15
15 function confirm (options) { 16 function confirm (options) {
16 - let instance = getModalInstance(); 17 + const render = ('render' in options) ? options.render : undefined;
  18 + let instance = getModalInstance(render);
17 19
18 options.onRemove = function () { 20 options.onRemove = function () {
19 modalInstance = null; 21 modalInstance = null;
src/components/modal/modal.vue
1 <template> 1 <template>
2 - <div> 2 + <div v-transfer-dom>
3 <transition :name="transitionNames[1]"> 3 <transition :name="transitionNames[1]">
4 <div :class="maskClasses" v-show="visible" @click="mask"></div> 4 <div :class="maskClasses" v-show="visible" @click="mask"></div>
5 </transition> 5 </transition>
src/components/table/cell.vue
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 <Checkbox :value="checked" @on-change="toggleSelect" :disabled="disabled"></Checkbox> 5 <Checkbox :value="checked" @on-change="toggleSelect" :disabled="disabled"></Checkbox>
6 </template> 6 </template>
7 <template v-if="renderType === 'normal'"><span v-html="row[column.key]"></span></template> 7 <template v-if="renderType === 'normal'"><span v-html="row[column.key]"></span></template>
8 - <template v-if="renderType === 'expand'"> 8 + <template v-if="renderType === 'expand' && !row._disableExpand">
9 <div :class="expandCls" @click="toggleExpand"> 9 <div :class="expandCls" @click="toggleExpand">
10 <Icon type="ios-arrow-right"></Icon> 10 <Icon type="ios-arrow-right"></Icon>
11 </div> 11 </div>
src/components/tabs/pane.vue
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 type: String 11 type: String
12 }, 12 },
13 label: { 13 label: {
14 - type: String, 14 + type: [String, Function],
15 default: '' 15 default: ''
16 }, 16 },
17 icon: { 17 icon: {
src/components/tabs/tabs.vue
@@ -8,7 +8,8 @@ @@ -8,7 +8,8 @@
8 <div :class="barClasses" :style="barStyle"></div> 8 <div :class="barClasses" :style="barStyle"></div>
9 <div :class="tabCls(item)" v-for="(item, index) in navList" @click="handleChange(index)"> 9 <div :class="tabCls(item)" v-for="(item, index) in navList" @click="handleChange(index)">
10 <Icon v-if="item.icon !== ''" :type="item.icon"></Icon> 10 <Icon v-if="item.icon !== ''" :type="item.icon"></Icon>
11 - {{ item.label }} 11 + <Render v-if="item.labelType === 'function'" :render="item.label"></Render>
  12 + <template v-else>{{ item.label }}</template>
12 <Icon v-if="showClose(item)" type="ios-close-empty" @click.native.stop="handleRemove(index)"></Icon> 13 <Icon v-if="showClose(item)" type="ios-close-empty" @click.native.stop="handleRemove(index)"></Icon>
13 </div> 14 </div>
14 </div> 15 </div>
@@ -22,6 +23,7 @@ @@ -22,6 +23,7 @@
22 </template> 23 </template>
23 <script> 24 <script>
24 import Icon from '../icon/icon.vue'; 25 import Icon from '../icon/icon.vue';
  26 + import Render from '../base/render.vue';
25 import { oneOf, getStyle } from '../../utils/assist'; 27 import { oneOf, getStyle } from '../../utils/assist';
26 import Emitter from '../../mixins/emitter'; 28 import Emitter from '../../mixins/emitter';
27 29
@@ -30,7 +32,7 @@ @@ -30,7 +32,7 @@
30 export default { 32 export default {
31 name: 'Tabs', 33 name: 'Tabs',
32 mixins: [ Emitter ], 34 mixins: [ Emitter ],
33 - components: { Icon }, 35 + components: { Icon, Render },
34 props: { 36 props: {
35 value: { 37 value: {
36 type: [String, Number] 38 type: [String, Number]
@@ -128,6 +130,7 @@ @@ -128,6 +130,7 @@
128 this.navList = []; 130 this.navList = [];
129 this.getTabs().forEach((pane, index) => { 131 this.getTabs().forEach((pane, index) => {
130 this.navList.push({ 132 this.navList.push({
  133 + labelType: typeof pane.label,
131 label: pane.label, 134 label: pane.label,
132 icon: pane.icon || '', 135 icon: pane.icon || '',
133 name: pane.currentName || index, 136 name: pane.currentName || index,
src/components/tree/node.vue
1 <template> 1 <template>
2 - <transition name="slide-up"> 2 + <collapse-transition>
3 <ul :class="classes" v-show="visible"> 3 <ul :class="classes" v-show="visible">
4 <li> 4 <li>
5 <span :class="arrowClasses" @click="handleExpand"> 5 <span :class="arrowClasses" @click="handleExpand">
6 <Icon type="arrow-right-b"></Icon> 6 <Icon type="arrow-right-b"></Icon>
7 </span> 7 </span>
8 <Checkbox 8 <Checkbox
9 - v-if="showCheckbox"  
10 - :value="data.checked"  
11 - :indeterminate="indeterminate"  
12 - :disabled="data.disabled || data.disableCheckbox"  
13 - @click.native.prevent="handleCheck"></Checkbox> 9 + v-if="showCheckbox"
  10 + :value="data.checked"
  11 + :indeterminate="indeterminate"
  12 + :disabled="data.disabled || data.disableCheckbox"
  13 + @click.native.prevent="handleCheck"></Checkbox>
14 <span :class="titleClasses" v-html="data.title" @click="handleSelect"></span> 14 <span :class="titleClasses" v-html="data.title" @click="handleSelect"></span>
15 <Tree-node 15 <Tree-node
16 - v-for="item in data.children"  
17 - :key="item"  
18 - :data="item"  
19 - :visible="data.expand"  
20 - :multiple="multiple"  
21 - :show-checkbox="showCheckbox"> 16 + v-for="item in data.children"
  17 + :key="item"
  18 + :data="item"
  19 + :visible="data.expand"
  20 + :multiple="multiple"
  21 + :show-checkbox="showCheckbox">
22 </Tree-node> 22 </Tree-node>
23 </li> 23 </li>
24 </ul> 24 </ul>
25 - </transition> 25 + </collapse-transition>
26 </template> 26 </template>
27 <script> 27 <script>
28 import Checkbox from '../checkbox/checkbox.vue'; 28 import Checkbox from '../checkbox/checkbox.vue';
29 import Icon from '../icon/icon.vue'; 29 import Icon from '../icon/icon.vue';
  30 + import CollapseTransition from '../base/collapse-transition';
30 import Emitter from '../../mixins/emitter'; 31 import Emitter from '../../mixins/emitter';
31 import { findComponentsDownward } from '../../utils/assist'; 32 import { findComponentsDownward } from '../../utils/assist';
32 33
@@ -35,7 +36,7 @@ @@ -35,7 +36,7 @@
35 export default { 36 export default {
36 name: 'TreeNode', 37 name: 'TreeNode',
37 mixins: [ Emitter ], 38 mixins: [ Emitter ],
38 - components: { Checkbox, Icon }, 39 + components: { Checkbox, Icon, CollapseTransition },
39 props: { 40 props: {
40 data: { 41 data: {
41 type: Object, 42 type: Object,
src/directives/transfer-dom.js
@@ -18,6 +18,7 @@ const directive = { @@ -18,6 +18,7 @@ const directive = {
18 inserted (el, { value }, vnode) { 18 inserted (el, { value }, vnode) {
19 el.className = el.className ? el.className + ' v-transfer-dom' : 'v-transfer-dom'; 19 el.className = el.className ? el.className + ' v-transfer-dom' : 'v-transfer-dom';
20 const parentNode = el.parentNode; 20 const parentNode = el.parentNode;
  21 + if (!parentNode) return;
21 const home = document.createComment(''); 22 const home = document.createComment('');
22 let hasMovedOut = false; 23 let hasMovedOut = false;
23 24
@@ -38,6 +39,7 @@ const directive = { @@ -38,6 +39,7 @@ const directive = {
38 componentUpdated (el, { value }) { 39 componentUpdated (el, { value }) {
39 // need to make sure children are done updating (vs. `update`) 40 // need to make sure children are done updating (vs. `update`)
40 const ref$1 = el.__transferDomData; 41 const ref$1 = el.__transferDomData;
  42 + if (!ref$1) return;
41 // homes.get(el) 43 // homes.get(el)
42 const parentNode = ref$1.parentNode; 44 const parentNode = ref$1.parentNode;
43 const home = ref$1.home; 45 const home = ref$1.home;
@@ -59,7 +61,9 @@ const directive = { @@ -59,7 +61,9 @@ const directive = {
59 } 61 }
60 }, 62 },
61 unbind: function unbind (el, binding) { 63 unbind: function unbind (el, binding) {
62 - el.className = el.className.replace('v-transfer-dom', '') 64 + el.className = el.className.replace('v-transfer-dom', '');
  65 + const ref$1 = el.__transferDomData;
  66 + if (!ref$1) return;
63 if (el.__transferDomData.hasMovedOut === true) { 67 if (el.__transferDomData.hasMovedOut === true) {
64 el.__transferDomData.parentNode && el.__transferDomData.parentNode.appendChild(el) 68 el.__transferDomData.parentNode && el.__transferDomData.parentNode.appendChild(el)
65 } 69 }
src/locale/lang/fr-FR.js 0 → 100644
  1 +export default {
  2 + i: {
  3 + select: {
  4 + placeholder: 'Sélectionnez',
  5 + noMatch: 'Aucun résultat',
  6 + loading: 'Chargement'
  7 + },
  8 + table: {
  9 + noDataText: 'Aucune donnée',
  10 + noFilteredDataText: 'No filter data',
  11 + confirmFilter: 'Confirmez',
  12 + resetFilter: 'Reset',
  13 + clearFilter: 'Tout'
  14 + },
  15 + datepicker: {
  16 + selectDate: 'Sélectionnez une date',
  17 + selectTime: 'Sélectionnez une heure',
  18 + startTime: 'Heure de début',
  19 + endTime: 'Heure de fin',
  20 + clear: 'Annuler',
  21 + ok: 'OK',
  22 + month: '',
  23 + month1: 'Janvier',
  24 + month2: 'Février',
  25 + month3: 'Mars',
  26 + month4: 'Avril',
  27 + month5: 'Mai',
  28 + month6: 'Juin',
  29 + month7: 'Juillet',
  30 + month8: 'Août',
  31 + month9: 'Septembre',
  32 + month10: 'Octobre',
  33 + month11: 'Novembre',
  34 + month12: 'Decembre',
  35 + year: '',
  36 + weeks: {
  37 + sun: 'Dim',
  38 + mon: 'Lun',
  39 + tue: 'Mar',
  40 + wed: 'Mer',
  41 + thu: 'Jeu',
  42 + fri: 'Ven',
  43 + sat: 'Sam'
  44 + },
  45 + months: {
  46 + m1: 'Jan',
  47 + m2: 'Fev',
  48 + m3: 'Mar',
  49 + m4: 'Avr',
  50 + m5: 'Mai',
  51 + m6: 'Jun',
  52 + m7: 'Jul',
  53 + m8: 'Aoû',
  54 + m9: 'Sep',
  55 + m10: 'Oct',
  56 + m11: 'Nov',
  57 + m12: 'Déc'
  58 + }
  59 + },
  60 + transfer: {
  61 + titles: {
  62 + source: 'Source',
  63 + target: 'Cible'
  64 + },
  65 + filterPlaceholder: 'Recherche',
  66 + notFoundText: 'Pas de résultat'
  67 + },
  68 + modal: {
  69 + okText: 'OK',
  70 + cancelText: 'Annuler'
  71 + },
  72 + poptip: {
  73 + okText: 'OK',
  74 + cancelText: 'Annuler'
  75 + },
  76 + page: {
  77 + prev: 'Page Précédente',
  78 + next: 'Page Suivante',
  79 + total: 'Total',
  80 + item: 'élément',
  81 + items: 'éléments',
  82 + prev5: '5 Pages en Avant',
  83 + next5: '5 Pages en Arrière',
  84 + page: '/page',
  85 + goto: 'Aller à',
  86 + p: ''
  87 + },
  88 + rate: {
  89 + star: 'Étoile',
  90 + stars: 'Étoiles'
  91 + },
  92 + tree: {
  93 + emptyText: 'Aucune donnée'
  94 + }
  95 + }
  96 +};
src/styles/animation/index.less
@@ -25,4 +25,8 @@ @@ -25,4 +25,8 @@
25 @import "fade"; 25 @import "fade";
26 @import "move"; 26 @import "move";
27 @import "ease"; 27 @import "ease";
28 -@import "slide";  
29 \ No newline at end of file 28 \ No newline at end of file
  29 +@import "slide";
  30 +
  31 +.collapse-transition {
  32 + transition: @transition-time height ease-in-out, @transition-time padding-top ease-in-out, @transition-time padding-bottom ease-in-out;
  33 +}
30 \ No newline at end of file 34 \ No newline at end of file
src/styles/components/modal.less
@@ -98,6 +98,11 @@ @@ -98,6 +98,11 @@
98 color: @text-color; 98 color: @text-color;
99 position: relative; 99 position: relative;
100 100
  101 + &-render{
  102 + margin: 0;
  103 + padding: 0;
  104 + }
  105 +
101 &-icon { 106 &-icon {
102 font-size: 36px; 107 font-size: 36px;
103 position: absolute; 108 position: absolute;
src/utils/assist.js
@@ -232,4 +232,66 @@ function findComponentsDownward (context, componentName, components = []) { @@ -232,4 +232,66 @@ function findComponentsDownward (context, componentName, components = []) {
232 } 232 }
233 return components; 233 return components;
234 } 234 }
235 -export {findComponentsDownward};  
236 \ No newline at end of file 235 \ No newline at end of file
  236 +export {findComponentsDownward};
  237 +
  238 +/* istanbul ignore next */
  239 +const trim = function(string) {
  240 + return (string || '').replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, '');
  241 +};
  242 +
  243 +/* istanbul ignore next */
  244 +export function hasClass(el, cls) {
  245 + if (!el || !cls) return false;
  246 + if (cls.indexOf(' ') !== -1) throw new Error('className should not contain space.');
  247 + if (el.classList) {
  248 + return el.classList.contains(cls);
  249 + } else {
  250 + return (' ' + el.className + ' ').indexOf(' ' + cls + ' ') > -1;
  251 + }
  252 +}
  253 +
  254 +/* istanbul ignore next */
  255 +export function addClass(el, cls) {
  256 + if (!el) return;
  257 + let curClass = el.className;
  258 + const classes = (cls || '').split(' ');
  259 +
  260 + for (let i = 0, j = classes.length; i < j; i++) {
  261 + const clsName = classes[i];
  262 + if (!clsName) continue;
  263 +
  264 + if (el.classList) {
  265 + el.classList.add(clsName);
  266 + } else {
  267 + if (!hasClass(el, clsName)) {
  268 + curClass += ' ' + clsName;
  269 + }
  270 + }
  271 + }
  272 + if (!el.classList) {
  273 + el.className = curClass;
  274 + }
  275 +}
  276 +
  277 +/* istanbul ignore next */
  278 +export function removeClass(el, cls) {
  279 + if (!el || !cls) return;
  280 + const classes = cls.split(' ');
  281 + let curClass = ' ' + el.className + ' ';
  282 +
  283 + for (let i = 0, j = classes.length; i < j; i++) {
  284 + const clsName = classes[i];
  285 + if (!clsName) continue;
  286 +
  287 + if (el.classList) {
  288 + el.classList.remove(clsName);
  289 + } else {
  290 + if (hasClass(el, clsName)) {
  291 + curClass = curClass.replace(' ' + clsName + ' ', ' ');
  292 + }
  293 + }
  294 + }
  295 + if (!el.classList) {
  296 + el.className = trim(curClass);
  297 + }
  298 +}
237 \ No newline at end of file 299 \ No newline at end of file