├── .browserslistrc
├── .eslintrc.js
├── .gitignore
├── .npmignore
├── LICENSE
├── README.md
├── babel.config.js
├── package-lock.json
├── package.json
├── postcss.config.js
├── preview.gif
├── public
├── favicon.ico
└── index.html
├── src
├── App.vue
├── main.js
└── plugins
│ └── vue-columns-resizable
│ └── index.js
└── vue.config.js
/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not ie <= 8
4 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true
5 | },
6 | 'extends': [
7 | 'plugin:vue/essential',
8 | 'eslint:recommended'
9 | ],
10 | rules: {
11 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
12 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
13 | },
14 | parserOptions: {
15 | parser: 'babel-eslint'
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 | /lib
5 |
6 | # local env files
7 | .env.local
8 | .env.*.local
9 |
10 | # Log files
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 |
15 | # Editor directories and files
16 | .idea
17 | .vscode
18 | *.suo
19 | *.ntvs*
20 | *.njsproj
21 | *.sln
22 | *.sw*
23 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .*
2 | *.md
3 | *.yml
4 | *.config.js
5 | src/
6 | public/
7 | node_modules/
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Fuxy526
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vue-columns-resizable
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Vue directive for making table columns resizable.
10 |
11 | [demo](https://fuxy526.github.io/vue-columns-resizable/)
12 |
13 | 
14 |
15 | ## Install
16 |
17 | ```sh
18 | npm install vue-columns-resizable --save
19 | ```
20 |
21 | ## Usage
22 |
23 | #### main.js
24 |
25 | ```javascript
26 | import VueColumnsResizable from './plugins/vue-columns-resizable';
27 |
28 | Vue.use(VueColumnsResizable);
29 | ```
30 |
31 | #### *.vue
32 |
33 | ```html
34 |
35 |
36 |
37 | name |
38 | age |
39 | gender |
40 |
41 |
42 |
43 |
44 | John |
45 | 20 |
46 | male |
47 |
48 |
49 | Emma |
50 | 18 |
51 | female |
52 |
53 |
54 | Peter |
55 | 21 |
56 | male |
57 |
58 |
59 |
60 | ```
61 |
62 | Resize on thead
63 |
64 | ```html
65 |
66 |
67 |
68 | name |
69 | age |
70 | gender |
71 |
72 |
73 |
74 |
75 | John |
76 | 20 |
77 | male |
78 |
79 |
80 | Emma |
81 | 18 |
82 | female |
83 |
84 |
85 | Peter |
86 | 21 |
87 | male |
88 |
89 |
90 |
91 | ```
92 |
93 | ## Changelog
94 |
95 | * 0.0.1 - Resize on columns & Resize on thead
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/app'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-columns-resizable",
3 | "version": "0.0.1",
4 | "description": "Vue directive for making table columns resizable.",
5 | "private": false,
6 | "main": "lib/vue-columns-resizable.umd.min.js",
7 | "scripts": {
8 | "dev": "vue-cli-service serve",
9 | "build": "vue-cli-service build",
10 | "build:lib": "vue-cli-service build --target lib --name vue-columns-resizable --dest lib src/plugins/vue-columns-resizable/index.js",
11 | "lint": "vue-cli-service lint"
12 | },
13 | "repository": {
14 | "type": "git",
15 | "url": "git+https://github.com/Fuxy526/vue-columns-resizable.git"
16 | },
17 | "bugs": {
18 | "url": "https://github.com/Fuxy526/vue-columns-resizable/issues"
19 | },
20 | "homepage": "https://github.com/Fuxy526/vue-columns-resizable#readme",
21 | "dependencies": {
22 | "vue": "^2.5.22"
23 | },
24 | "devDependencies": {
25 | "@vue/cli-plugin-babel": "^3.4.0",
26 | "@vue/cli-plugin-eslint": "^3.4.0",
27 | "@vue/cli-service": "^3.4.0",
28 | "babel-eslint": "^10.0.1",
29 | "eslint": "^5.8.0",
30 | "eslint-plugin-vue": "^5.0.0",
31 | "fibers": "^3.1.1",
32 | "sass": "^1.16.0",
33 | "sass-loader": "^7.1.0",
34 | "vue-template-compiler": "^2.5.21"
35 | },
36 | "author": "Fuxy526",
37 | "license": "MIT"
38 | }
39 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | autoprefixer: {}
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/preview.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fuxy526/vue-columns-resizable/9dc284140cb1cde778affeed26675450c9929b0c/preview.gif
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fuxy526/vue-columns-resizable/9dc284140cb1cde778affeed26675450c9929b0c/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | vue-columns-resizable
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Default
5 |
6 |
7 |
8 | name |
9 | age |
10 | gender |
11 |
12 |
13 |
14 |
15 | John |
16 | 20 |
17 | male |
18 |
19 |
20 | Emma |
21 | 18 |
22 | female |
23 |
24 |
25 | Peter |
26 | 21 |
27 | male |
28 |
29 |
30 |
31 |
32 |
33 |
Resize on thead
34 |
35 |
36 |
37 | name |
38 | age |
39 | gender |
40 |
41 |
42 |
43 |
44 | John |
45 | 20 |
46 | male |
47 |
48 |
49 | Emma |
50 | 18 |
51 | female |
52 |
53 |
54 | Peter |
55 | 21 |
56 | male |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
69 |
70 |
81 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import App from './App.vue';
3 | import VueColumnsResizable from './plugins/vue-columns-resizable';
4 |
5 | Vue.use(VueColumnsResizable);
6 |
7 | Vue.config.productionTip = false;
8 |
9 | new Vue({
10 | render: h => h(App),
11 | }).$mount('#app');
12 |
--------------------------------------------------------------------------------
/src/plugins/vue-columns-resizable/index.js:
--------------------------------------------------------------------------------
1 | export default {
2 | install(Vue) {
3 | Vue.directive('columns-resizable', {
4 | inserted(el) {
5 | const nodeName = el.nodeName;
6 | if (['TABLE', 'THEAD'].indexOf(nodeName) < 0) return;
7 |
8 | const table = nodeName === 'TABLE' ? el : el.parentElement;
9 | const thead = table.querySelector('thead');
10 | const ths = thead.querySelectorAll('th');
11 | const barHeight = nodeName === 'TABLE' ? table.offsetHeight : thead.offsetHeight;
12 |
13 | const resizeContainer = document.createElement('div');
14 | table.style.position = 'relative';
15 | resizeContainer.style.position = 'relative';
16 | resizeContainer.style.width = table.offsetWidth + 'px';
17 | resizeContainer.className = "vue-columns-resizable";
18 | table.parentElement.insertBefore(resizeContainer, table);
19 |
20 | let moving = false;
21 | let movingIndex = 0;
22 |
23 | ths.forEach((th, index) => {
24 | th.style.width = th.offsetWidth + 'px';
25 |
26 | if (index + 1 >= ths.length) return;
27 |
28 | const nextTh = ths[index + 1];
29 | const bar = document.createElement('div');
30 |
31 | bar.style.position = 'absolute';
32 | bar.style.left = nextTh.offsetLeft - 4 + 'px';
33 | bar.style.top = 0;
34 | bar.style.height = barHeight + 'px';
35 | bar.style.width = '8px';
36 | bar.style.cursor = 'col-resize';
37 | bar.style.zIndex = 1;
38 | bar.className = 'columns-resize-bar';
39 |
40 | bar.addEventListener('mousedown', () => {
41 | moving = true;
42 | movingIndex = index;
43 | document.body.style.cursor = 'col-resize';
44 | document.body.style.userSelect = 'none';
45 | });
46 |
47 | resizeContainer.appendChild(bar);
48 | });
49 |
50 | const bars = resizeContainer.querySelectorAll('.columns-resize-bar');
51 |
52 | document.addEventListener('mouseup', () => {
53 | if (!moving) return;
54 |
55 | moving = false;
56 | document.body.style.cursor = '';
57 | document.body.style.userSelect = '';
58 |
59 | bars.forEach((bar, index) => {
60 | const th = ths[index];
61 | const nextTh = ths[index + 1];
62 | th.style.width = th.offsetWidth + 'px';
63 | bar.style.left = nextTh.offsetLeft - 4 + 'px';
64 | });
65 | });
66 |
67 | const cutPx = str => +str.replace('px', '');
68 |
69 | const handleResize = e => {
70 | if (moving) {
71 | const th = ths[movingIndex];
72 | const nextTh = ths[movingIndex + 1];
73 | const bar = bars[movingIndex];
74 | th.style.width = cutPx(th.style.width) + e.movementX + 'px';
75 | nextTh.style.width = cutPx(nextTh.style.width) - e.movementX + 'px';
76 | bar.style.left = nextTh.offsetLeft - 4 + e.movementX + 'px';
77 | }
78 | };
79 |
80 | resizeContainer.addEventListener('mousemove', handleResize);
81 | table.addEventListener('mousemove', handleResize);
82 | },
83 | });
84 |
85 | },
86 | };
87 |
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | publicPath: './',
3 | productionSourceMap: false,
4 | };
--------------------------------------------------------------------------------