├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── assets ├── tree.svg └── vue-orgchart.jpg ├── build ├── rollup.config.js └── webpack.config.js ├── dist ├── style.css ├── style.min.css ├── vue-orgchart.common.js ├── vue-orgchart.common.min.js ├── vue-orgchart.esm.js ├── vue-orgchart.js └── vue-orgchart.min.js ├── docs ├── .nojekyll ├── README.md ├── _assets │ └── tree.svg ├── _coverpage.md ├── _navbar.md ├── _sidebar.md ├── basic.md ├── drag.md ├── edit.md ├── exportpic.md ├── favicon.ico ├── index.html ├── index.min.js ├── panzoom.md ├── props.md ├── quickstart.md ├── style.css ├── style.min.css └── zh-cn │ ├── README.md │ ├── _navbar.md │ ├── _sidebar.md │ ├── basic.md │ ├── drag.md │ ├── edit.md │ ├── exportpic.md │ ├── panzoom.md │ ├── props.md │ └── quickstart.md ├── examples ├── Ajax.vue ├── App.vue ├── data │ ├── basic.js │ ├── edit.js │ └── index.js ├── index.html ├── main.js └── store │ ├── index.js │ └── service.js ├── package-lock.json ├── package.json ├── src ├── components │ ├── VoBasic.vue │ └── VoEdit.vue ├── index.js └── lib │ ├── lodash.js │ ├── orgchart.js │ └── utils.js └── test ├── index.js ├── karma.conf.js └── load └── webpack ├── basic ├── App.vue ├── index.js └── webpack.config.js ├── edit ├── App.vue ├── index.js └── webpack.config.js └── index.html /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["latest", { 4 | "es2015": { "modules": false } 5 | }], 6 | "stage-2" 7 | ], 8 | "plugins": [["transform-object-assign"],[ 9 | "transform-runtime", 10 | { 11 | "helpers": false, 12 | "polyfill": false, 13 | "regenerator": true, 14 | "moduleName": "babel-runtime" 15 | } 16 | ]] 17 | } 18 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | webpack.config.js 2 | /src/lib/orgchart.js 3 | /src/main.js 4 | /src/index.js 5 | /dist 6 | /examples 7 | /build 8 | /docs 9 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | // http://eslint.org/docs/user-guide/configuring 2 | 3 | module.exports = { 4 | root: true, 5 | parser: 'babel-eslint', 6 | parserOptions: { 7 | sourceType: 'module' 8 | }, 9 | env: { 10 | browser: true, 11 | }, 12 | extends: 'standard', 13 | plugins: [ 14 | 'html' 15 | ], 16 | rules: { 17 | 'no-mixed-operators': 'off' 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | npm-debug.log 4 | yarn-error.log 5 | 6 | # Editor directories and files 7 | .idea 8 | *.suo 9 | *.ntvs* 10 | *.njsproj 11 | *.sln 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: stable 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017-present, spiritree 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | vue-orgchart logo 4 | 5 |

6 | 7 |

8 | A Vue wrapper for OrgChart.js. 9 |

10 | 11 |

12 | Travis Status 13 | npm 14 | 15 |

16 | 17 | ## Intro 18 | 19 | - First of all, thanks a lot for dabeng's great work -- [OrgChart.js](https://github.com/dabeng/OrgChart.js) 20 | - If you prefer the Vue.js Wrapper for Orgchart.js,you could try [my project](https://github.com/spiritree/vue-orgchart) 21 | 22 | ## Links 23 | 24 | - [Documentation](https://spiritree.github.io/vue-orgchart) 25 | 26 | ### Feature 27 | 28 | - Support import and export JSON 29 | - Supports exporting chart as a picture 30 | - draggable Orgchart 31 | - Editable Orgchart 32 | 33 | ... 34 | ## Install 35 | ```shell 36 | npm install vue-orgchart -S 37 | ``` 38 | ## Quick Start 39 | 40 | > In `main.js` 41 | 42 | `import 'vue-orgchart/dist/style.min.css'` 43 | 44 | > In `*.vue` 45 | 46 | ```javascript 47 | 52 | 53 | 74 | ``` 75 | ## Development 76 | 77 | ``` bash 78 | # install dependencies 79 | npm install 80 | 81 | # serve with hot reload at localhost:8999 82 | npm run dev 83 | 84 | # unit test 85 | npm run test 86 | 87 | # build by rollup 88 | npm run rollup 89 | ``` 90 | 91 | ## License 92 | 93 | MIT 94 | -------------------------------------------------------------------------------- /assets/tree.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/vue-orgchart.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spiritree/vue-orgchart/c8de4152e2839e28af5561bcce9b4af0d3f046a4/assets/vue-orgchart.jpg -------------------------------------------------------------------------------- /build/rollup.config.js: -------------------------------------------------------------------------------- 1 | const rollup = require('rollup') 2 | const vue = require('rollup-plugin-vue') 3 | const resolve = require('rollup-plugin-node-resolve') 4 | const babel = require('rollup-plugin-babel') 5 | const uglify = require('rollup-plugin-uglify') 6 | const autoprefixer = require('autoprefixer') 7 | const cssnano = require('cssnano') 8 | 9 | const outputOptions = [ 10 | { 11 | min: true, 12 | format: 'umd', 13 | name: 'vue-orgchart', 14 | file: 'dist/vue-orgchart.min.js' 15 | }, 16 | { 17 | min: false, 18 | format: 'umd', 19 | name: 'vue-orgchart', 20 | file: 'dist/vue-orgchart.js' 21 | }, 22 | { 23 | min: true, 24 | format: 'cjs', 25 | name: 'vue-orgchart', 26 | file: 'dist/vue-orgchart.common.min.js' 27 | }, 28 | { 29 | min: false, 30 | format: 'cjs', 31 | name: 'vue-orgchart', 32 | file: 'dist/vue-orgchart.common.js' 33 | }, 34 | { 35 | min: false, 36 | format: 'es', 37 | name: 'vue-orgchart', 38 | file: 'dist/vue-orgchart.esm.js' 39 | } 40 | ] 41 | 42 | async function build(item) { 43 | const vueSettings = item.min 44 | ? { css: 'dist/style.min.css', postcss: [autoprefixer, cssnano] } 45 | : { css: 'dist/style.css', postcss: [autoprefixer] } 46 | 47 | const inputOptions = { 48 | input: 'src/index.js', 49 | plugins: [ 50 | vue(vueSettings), 51 | resolve({ 52 | extensions: ['.js', '.vue'] 53 | }), 54 | babel({ 55 | exclude: 'node_modules/**', 56 | plugins: ['external-helpers'] 57 | }) 58 | ] 59 | } 60 | if (item.min) inputOptions.plugins.push(uglify()) 61 | 62 | const bundle = await rollup.rollup(inputOptions) 63 | await bundle.write(item) 64 | } 65 | 66 | outputOptions.forEach(item => { 67 | build(item) 68 | .then(() => item.min 69 | ? console.log(`rollup: ${item.name}.${item.format}.min built successfully`) 70 | : console.log(`rollup: ${item.name}.${item.format} built successfully`)) 71 | .catch(err => console.error(err)) 72 | }) 73 | -------------------------------------------------------------------------------- /build/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const webpack = require('webpack') 3 | const HtmlWebpackPlugin = require('html-webpack-plugin') 4 | const opn = require('opn') 5 | 6 | opn('http://localhost:8999') 7 | 8 | function resolve (dir) { 9 | return path.join(__dirname, '..', dir) 10 | } 11 | 12 | module.exports = { 13 | entry: './examples/main.js', 14 | output: { 15 | path: path.resolve(__dirname, '../dist'), 16 | publicPath: '/', 17 | filename: 'build.js' 18 | }, 19 | module: { 20 | rules: [ 21 | { 22 | test: /\.css$/, 23 | use: [ 24 | 'vue-style-loader', 25 | 'css-loader' 26 | ], 27 | }, 28 | { 29 | test: /\.vue$/, 30 | loader: 'vue-loader', 31 | options: { 32 | loaders: { 33 | } 34 | // other vue-loader options go here 35 | } 36 | }, 37 | { 38 | test: /\.js$/, 39 | loader: 'babel-loader', 40 | exclude: /node_modules/ 41 | }, 42 | { 43 | test: /\.(png|jpg|gif|svg)$/, 44 | loader: 'file-loader', 45 | options: { 46 | name: '[name].[ext]?[hash]' 47 | } 48 | } 49 | ] 50 | }, 51 | resolve: { 52 | alias: { 53 | 'vue$': 'vue/dist/vue.esm.js' 54 | }, 55 | extensions: ['*', '.js', '.vue', '.json'] 56 | }, 57 | devServer: { 58 | port: '8999', 59 | hot: true, 60 | contentBase: path.join(__dirname, 'dist'), 61 | stats: 'errors-only' 62 | }, 63 | performance: { 64 | hints: false 65 | }, 66 | devtool: '#eval-source-map', 67 | plugins: [ 68 | new webpack.DefinePlugin({ 69 | 'process.env': { 70 | NODE_ENV: '"development"' 71 | } 72 | }), 73 | new webpack.HotModuleReplacementPlugin(), 74 | new HtmlWebpackPlugin({ 75 | filename: 'index.html', 76 | template: './examples/index.html', 77 | inject: true 78 | }) 79 | ] 80 | } 81 | -------------------------------------------------------------------------------- /dist/style.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | #wrapper { 69 | width: 50%; 70 | margin: 0 auto; 71 | } 72 | 73 | #wrapper li { 74 | margin-top: 20px; 75 | } 76 | 77 | #wrapper a { 78 | font-size: 24px; 79 | } 80 | 81 | #wrapper span { 82 | font-size: 24px; 83 | } 84 | 85 | #chart-container { 86 | position: relative; 87 | display: inline-block; 88 | top: 10px; 89 | left: 10px; 90 | height: 50%; 91 | width: calc(100% - 24px); 92 | border-radius: 5px; 93 | overflow: auto; 94 | overflow-x: hidden; 95 | text-align: center; 96 | font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif; 97 | font-size: 14px; 98 | } 99 | .orgchart { 100 | display: inline-block; 101 | min-height: 100%; 102 | min-width: 100%; 103 | -webkit-touch-callout: none; 104 | -webkit-user-select: none; 105 | -moz-user-select: none; 106 | -ms-user-select: none; 107 | user-select: none; 108 | background-size: 10px 10px; 109 | border: 1px dashed transparent; 110 | } 111 | 112 | .orgchart .hidden, .orgchart~.hidden { 113 | display: none; 114 | } 115 | 116 | .orgchart div, 117 | .orgchart div::before, 118 | .orgchart div::after { 119 | -webkit-box-sizing: border-box; 120 | box-sizing: border-box; 121 | } 122 | 123 | .orgchart.b2t { 124 | -webkit-transform: rotate(180deg); 125 | transform: rotate(180deg); 126 | } 127 | 128 | .orgchart.l2r { 129 | -webkit-transform: rotate(-90deg) rotateY(180deg); 130 | transform: rotate(-90deg) rotateY(180deg); 131 | } 132 | 133 | .orgchart .verticalNodes ul { 134 | list-style: none; 135 | margin: 0; 136 | padding-left: 18px; 137 | text-align: left; 138 | } 139 | 140 | .orgchart .verticalNodes ul:first-child { 141 | margin-top: 3px; 142 | } 143 | 144 | .orgchart .verticalNodes>td::before { 145 | content: ''; 146 | border: 1px solid rgba(217, 83, 79, 0.8); 147 | } 148 | 149 | .orgchart .verticalNodes>td>ul>li:first-child::before { 150 | top: -4px; 151 | height: 30px; 152 | width: calc(50% - 2px); 153 | border-width: 2px 0 0 2px; 154 | } 155 | 156 | .orgchart .verticalNodes ul>li { 157 | position: relative; 158 | } 159 | 160 | .orgchart .verticalNodes ul>li::before, 161 | .orgchart .verticalNodes ul>li::after { 162 | content: ''; 163 | position: absolute; 164 | left: -6px; 165 | border-color: rgba(217, 83, 79, 0.8); 166 | border-style: solid; 167 | border-width: 0 0 2px 2px; 168 | -webkit-box-sizing: border-box; 169 | box-sizing: border-box; 170 | } 171 | 172 | .orgchart .verticalNodes ul>li::before { 173 | top: -4px; 174 | height: 30px; 175 | width: 11px; 176 | } 177 | 178 | .orgchart .verticalNodes ul>li::after { 179 | top: 1px; 180 | height: 100%; 181 | } 182 | 183 | .orgchart .verticalNodes ul>li:first-child::after { 184 | top: 24px; 185 | width: 11px; 186 | border-width: 2px 0 0 2px; 187 | } 188 | 189 | .orgchart .verticalNodes ul>li:last-child::after { 190 | border-width: 2px 0 0; 191 | } 192 | 193 | .orgchart.r2l { 194 | -webkit-transform: rotate(90deg); 195 | transform: rotate(90deg); 196 | } 197 | 198 | .orgchart>.spinner { 199 | font-size: 100px; 200 | margin-top: 30px; 201 | color: rgba(68, 157, 68, 0.8); 202 | } 203 | 204 | .orgchart table { 205 | border-spacing: 0; 206 | border-collapse: separate; 207 | } 208 | 209 | .orgchart>table:first-child{ 210 | margin: 20px auto; 211 | } 212 | 213 | .orgchart td { 214 | text-align: center; 215 | vertical-align: top; 216 | padding: 0; 217 | } 218 | 219 | .orgchart tr.lines .topLine { 220 | border-top: 2px solid #616161; 221 | } 222 | 223 | .orgchart tr.lines .rightLine { 224 | border-right: 1px solid #616161; 225 | float: none; 226 | border-radius: 0; 227 | } 228 | 229 | .orgchart tr.lines .leftLine { 230 | border-left: 1px solid #616161; 231 | float: none; 232 | border-radius: 0; 233 | } 234 | 235 | .orgchart tr.lines .downLine { 236 | background-color: #616161; 237 | margin: 0 auto; 238 | height: 20px; 239 | width: 2px; 240 | float: none; 241 | } 242 | 243 | /* node styling */ 244 | .orgchart .node { 245 | display: inline-block; 246 | position: relative; 247 | margin: 0; 248 | padding: 3px; 249 | border: 2px dashed transparent; 250 | text-align: center; 251 | width: 130px; 252 | } 253 | 254 | .orgchart.l2r .node, .orgchart.r2l .node { 255 | width: 40px; 256 | height: 130px; 257 | } 258 | 259 | .orgchart .node>.hazy { 260 | opacity: 0.2; 261 | } 262 | 263 | .orgchart .node>.spinner { 264 | position: absolute; 265 | top: calc(50% - 15px); 266 | left: calc(50% - 15px); 267 | vertical-align: middle; 268 | font-size: 30px; 269 | color: rgba(68, 157, 68, 0.8); 270 | } 271 | 272 | .orgchart .node:hover { 273 | background-color: rgba(238, 217, 54, 0.5); 274 | -webkit-transition: .5s; 275 | transition: .5s; 276 | cursor: default; 277 | z-index: 20; 278 | } 279 | 280 | .orgchart .node.focused { 281 | background-color: rgba(238, 217, 54, 0.5); 282 | } 283 | 284 | .orgchart .ghost-node { 285 | position: fixed; 286 | left: -10000px; 287 | top: -10000px; 288 | } 289 | 290 | .orgchart .ghost-node rect { 291 | fill: #ffffff; 292 | stroke: #bf0000; 293 | } 294 | 295 | .orgchart .node.allowedDrop { 296 | border-color: rgba(68, 157, 68, 0.9); 297 | } 298 | 299 | .orgchart .node .title { 300 | text-align: center; 301 | font-size: 12px; 302 | font-weight: 300; 303 | height: 20px; 304 | line-height: 20px; 305 | overflow: hidden; 306 | text-overflow: ellipsis; 307 | white-space: nowrap; 308 | background-color: #42b983; 309 | color: #fff; 310 | border-radius: 4px 4px 0 0; 311 | } 312 | 313 | .orgchart.b2t .node .title { 314 | -webkit-transform: rotate(-180deg); 315 | transform: rotate(-180deg); 316 | -webkit-transform-origin: center bottom; 317 | transform-origin: center bottom; 318 | } 319 | 320 | .orgchart.l2r .node .title { 321 | -webkit-transform: rotate(-90deg) translate(-40px, -40px) rotateY(180deg); 322 | transform: rotate(-90deg) translate(-40px, -40px) rotateY(180deg); 323 | -webkit-transform-origin: bottom center; 324 | transform-origin: bottom center; 325 | width: 120px; 326 | } 327 | 328 | .orgchart.r2l .node .title { 329 | -webkit-transform: rotate(-90deg) translate(-40px, -40px); 330 | transform: rotate(-90deg) translate(-40px, -40px); 331 | -webkit-transform-origin: bottom center; 332 | transform-origin: bottom center; 333 | width: 120px; 334 | } 335 | 336 | .orgchart .node .title .symbol { 337 | float: left; 338 | margin-top: 4px; 339 | margin-left: 2px; 340 | } 341 | 342 | .orgchart .node .content { 343 | width: 100%; 344 | height: 20px; 345 | font-size: 11px; 346 | line-height: 18px; 347 | border: 1px solid #42b983; 348 | border-radius: 0 0 4px 4px; 349 | text-align: center; 350 | background-color: #fff; 351 | color: #333; 352 | overflow: hidden; 353 | text-overflow: ellipsis; 354 | white-space: nowrap; 355 | } 356 | 357 | .orgchart.b2t .node .content { 358 | -webkit-transform: rotate(180deg); 359 | transform: rotate(180deg); 360 | -webkit-transform-origin: center top; 361 | transform-origin: center top; 362 | } 363 | 364 | .orgchart.l2r .node .content { 365 | -webkit-transform: rotate(-90deg) translate(-40px, -40px) rotateY(180deg); 366 | transform: rotate(-90deg) translate(-40px, -40px) rotateY(180deg); 367 | -webkit-transform-origin: top center; 368 | transform-origin: top center; 369 | width: 120px; 370 | } 371 | 372 | .orgchart.r2l .node .content { 373 | -webkit-transform: rotate(-90deg) translate(-40px, -40px); 374 | transform: rotate(-90deg) translate(-40px, -40px); 375 | -webkit-transform-origin: top center; 376 | transform-origin: top center; 377 | width: 120px; 378 | } 379 | 380 | .orgchart .node .edge { 381 | font-size: 15px; 382 | position: absolute; 383 | color: rgba(68, 157, 68, 0.5); 384 | cursor: default; 385 | transition: .2s; 386 | -webkit-transition: .2s; 387 | } 388 | 389 | .orgchart.noncollapsable .node .edge { 390 | display: none; 391 | } 392 | 393 | .orgchart .edge:hover { 394 | color: #449d44; 395 | cursor: pointer; 396 | } 397 | 398 | .orgchart .node .verticalEdge { 399 | width: calc(100% - 10px); 400 | width: -moz-calc(100% - 10px); 401 | left: 5px; 402 | } 403 | 404 | .orgchart .node .topEdge { 405 | top: -4px; 406 | } 407 | 408 | .orgchart .node .bottomEdge { 409 | bottom: -4px; 410 | } 411 | 412 | .orgchart .node .horizontalEdge { 413 | width: 15px; 414 | height: calc(100% - 10px); 415 | height: -moz-calc(100% - 10px); 416 | top: 5px; 417 | } 418 | 419 | .orgchart .node .rightEdge { 420 | right: -4px; 421 | } 422 | 423 | .orgchart .node .leftEdge { 424 | left: -4px; 425 | } 426 | 427 | .orgchart .node .horizontalEdge::before { 428 | position: absolute; 429 | top: calc(50% - 7px); 430 | top: -moz-calc(50% - 7px); 431 | } 432 | 433 | .orgchart .node .rightEdge::before { 434 | right: 3px; 435 | } 436 | 437 | .orgchart .node .leftEdge::before { 438 | left: 3px; 439 | } 440 | 441 | .orgchart .node .toggleBtn { 442 | position: absolute; 443 | left: 5px; 444 | bottom: -2px; 445 | color: rgba(68, 157, 68, 0.6); 446 | } 447 | 448 | .orgchart .node .toggleBtn:hover { 449 | color: rgba(68, 157, 68, 0.8); 450 | } 451 | 452 | .oc-export-btn { 453 | display: inline-block; 454 | position: absolute; 455 | right: 5px; 456 | bottom: 5px; 457 | padding: 6px 12px; 458 | margin-bottom: 0; 459 | font-size: 14px; 460 | font-weight: 400; 461 | line-height: 1.42857143; 462 | text-align: center; 463 | white-space: nowrap; 464 | vertical-align: middle; 465 | -ms-touch-action: manipulation; 466 | touch-action: manipulation; 467 | cursor: pointer; 468 | -webkit-user-select: none; 469 | -moz-user-select: none; 470 | -ms-user-select: none; 471 | user-select: none; 472 | color: #fff; 473 | background-color: #409eff; 474 | border: 1px solid transparent; 475 | border-color: #409eff; 476 | border-radius: 4px; 477 | } 478 | 479 | .oc-export-btn:hover,.oc-export-btn:focus,.oc-export-btn:active { 480 | background-color: #409eff; 481 | border-color: #409eff; 482 | } 483 | 484 | .orgchart~.mask { 485 | position: absolute; 486 | top: 0; 487 | right: 0; 488 | bottom: 0; 489 | left: 0; 490 | z-index: 999; 491 | text-align: center; 492 | background-color: rgba(0,0,0,0.3); 493 | } 494 | 495 | .orgchart~.mask .spinner { 496 | position: absolute; 497 | top: calc(50% - 54px); 498 | left: calc(50% - 54px); 499 | color: rgba(255,255,255,0.8); 500 | font-size: 108px; 501 | } 502 | 503 | .orgchart .node { 504 | -webkit-transition: all 0.3s; 505 | transition: all 0.3s; 506 | top: 0; 507 | left: 0; 508 | } 509 | 510 | .orgchart .slide-down { 511 | opacity: 0; 512 | top: 40px; 513 | } 514 | 515 | .orgchart.l2r .node.slide-down, .orgchart.r2l .node.slide-down { 516 | top: 130px; 517 | } 518 | 519 | .orgchart .slide-up { 520 | opacity: 0; 521 | top: -40px; 522 | } 523 | 524 | .orgchart.l2r .node.slide-up, .orgchart.r2l .node.slide-up { 525 | top: -130px; 526 | } 527 | 528 | .orgchart .slide-right { 529 | opacity: 0; 530 | left: 130px; 531 | } 532 | 533 | .orgchart.l2r .node.slide-right, .orgchart.r2l .node.slide-right { 534 | left: 40px; 535 | } 536 | 537 | .orgchart .slide-left { 538 | opacity: 0; 539 | left: -130px; 540 | } 541 | 542 | .orgchart.l2r .node.slide-left, .orgchart.r2l .node.slide-left { 543 | left: -40px; 544 | } 545 | #edit-panel { 546 | position: relative; 547 | left: 10px; 548 | width: calc(100% - 40px); 549 | border-radius: 4px; 550 | float: left; 551 | margin-top: 20px; 552 | padding: 10px 5px 10px 10px; 553 | font-size: 14px; 554 | line-height: 1.5; 555 | border-radius: 2px; 556 | color: rgba(0, 0, 0, 0.65); 557 | background-color: #fff; 558 | } 559 | 560 | #edit-panel .btn-inputs { 561 | font-size: 24px; 562 | } 563 | 564 | #edit-panel label { 565 | font-weight: bold; 566 | } 567 | 568 | #edit-panel .new-node { 569 | height: 24px; 570 | -webkit-appearance: none; 571 | background-color:#fff; 572 | background-image: none; 573 | border-radius: 4px; 574 | line-height: 1; 575 | border: 1px solid #d8dce5; 576 | -webkit-box-sizing: border-box; 577 | box-sizing: border-box; 578 | color: #5a5e66; 579 | display: inline-block; 580 | -webkit-transition: border-color .2s cubic-bezier(.645,.045,.355,1); 581 | transition: border-color .2s cubic-bezier(.645,.045,.355,1); 582 | } 583 | 584 | #edit-panel .new-node:focus { 585 | border-color: #409eff; 586 | outline: none; 587 | } 588 | 589 | #edit-panel .new-node:hover { 590 | border-color: #b4bccc; 591 | } 592 | 593 | #edit-panel.edit-parent-node .selected-node-group{ 594 | display: none; 595 | } 596 | 597 | #chart-state-panel, #selected-node, #btn-remove-input { 598 | margin-right: 20px; 599 | } 600 | 601 | #edit-panel button { 602 | /* color: #333; 603 | background-color: #fff; */ 604 | display: inline-block; 605 | padding: 6px 12px; 606 | margin-bottom: 0; 607 | line-height: 1.42857143; 608 | text-align: center; 609 | white-space: nowrap; 610 | border-radius: 4px; 611 | vertical-align: middle; 612 | -ms-touch-action: manipulation; 613 | touch-action: manipulation; 614 | cursor: pointer; 615 | -webkit-user-select: none; 616 | -moz-user-select: none; 617 | -ms-user-select: none; 618 | user-select: none; 619 | background-image: none; 620 | } 621 | 622 | #edit-panel.edit-parent-node button:not(#btn-add-nodes) { 623 | display: none; 624 | } 625 | 626 | #edit-panel button:hover,.edit-panel button:focus,.edit-panel button:active { 627 | border-color: #409eff; 628 | -webkit-box-shadow: 0 0 10px #409eff; 629 | box-shadow: 0 0 10px #409eff; 630 | } 631 | 632 | #new-nodelist { 633 | display: inline-block; 634 | list-style:none; 635 | margin-top: -2px; 636 | padding: 0; 637 | vertical-align: text-top; 638 | } 639 | 640 | #new-nodelist>* { 641 | padding-bottom: 4px; 642 | } 643 | 644 | .btn-inputs { 645 | vertical-align: sub; 646 | } 647 | 648 | 649 | .btn-inputs:hover { 650 | text-shadow: 0 0 4px #fff; 651 | } 652 | 653 | .radio-panel input[type='radio'] { 654 | border: 1px solid #d8dce5; 655 | border-radius: 100%; 656 | cursor: pointer; 657 | -webkit-box-sizing: border-box; 658 | box-sizing: border-box; 659 | display: inline-block; 660 | height: 14px; 661 | width: 14px; 662 | vertical-align: top; 663 | } 664 | 665 | #edit-panel.view-state .radio-panel input[type='radio']+label { 666 | font-size: 14px; 667 | font-weight: 500; 668 | /* color: #5a5e66; */ 669 | line-height: 1; 670 | } 671 | 672 | #btn-add-nodes { 673 | margin-left: 20px; 674 | } 675 | 676 | -------------------------------------------------------------------------------- /dist/style.min.css: -------------------------------------------------------------------------------- 1 | #wrapper{width:50%;margin:0 auto}#wrapper li{margin-top:20px}#wrapper a,#wrapper span{font-size:24px}#chart-container{position:relative;display:inline-block;top:10px;left:10px;height:50%;width:calc(100% - 24px);border-radius:5px;overflow:auto;overflow-x:hidden;text-align:center;font-family:Source Sans Pro,Helvetica Neue,Arial,sans-serif;font-size:14px}.orgchart{display:inline-block;min-height:100%;min-width:100%;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-size:10px 10px;border:1px dashed transparent}.orgchart .hidden,.orgchart~.hidden{display:none}.orgchart div,.orgchart div:after,.orgchart div:before{-webkit-box-sizing:border-box;box-sizing:border-box}.orgchart.b2t{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.orgchart.l2r{-webkit-transform:rotate(-90deg) rotateY(180deg);transform:rotate(-90deg) rotateY(180deg)}.orgchart .verticalNodes ul{list-style:none;margin:0;padding-left:18px;text-align:left}.orgchart .verticalNodes ul:first-child{margin-top:3px}.orgchart .verticalNodes>td:before{content:"";border:1px solid rgba(217,83,79,.8)}.orgchart .verticalNodes>td>ul>li:first-child:before{top:-4px;height:30px;width:calc(50% - 2px);border-width:2px 0 0 2px}.orgchart .verticalNodes ul>li{position:relative}.orgchart .verticalNodes ul>li:after,.orgchart .verticalNodes ul>li:before{content:"";position:absolute;left:-6px;border-color:rgba(217,83,79,.8);border-style:solid;border-width:0 0 2px 2px;-webkit-box-sizing:border-box;box-sizing:border-box}.orgchart .verticalNodes ul>li:before{top:-4px;height:30px;width:11px}.orgchart .verticalNodes ul>li:after{top:1px;height:100%}.orgchart .verticalNodes ul>li:first-child:after{top:24px;width:11px;border-width:2px 0 0 2px}.orgchart .verticalNodes ul>li:last-child:after{border-width:2px 0 0}.orgchart.r2l{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.orgchart>.spinner{font-size:100px;margin-top:30px;color:rgba(68,157,68,.8)}.orgchart table{border-spacing:0;border-collapse:separate}.orgchart>table:first-child{margin:20px auto}.orgchart td{text-align:center;vertical-align:top;padding:0}.orgchart tr.lines .topLine{border-top:2px solid #616161}.orgchart tr.lines .rightLine{border-right:1px solid #616161;float:none;border-radius:0}.orgchart tr.lines .leftLine{border-left:1px solid #616161;float:none;border-radius:0}.orgchart tr.lines .downLine{background-color:#616161;margin:0 auto;height:20px;width:2px;float:none}.orgchart .node{display:inline-block;position:relative;margin:0;padding:3px;border:2px dashed transparent;text-align:center;width:130px}.orgchart.l2r .node,.orgchart.r2l .node{width:40px;height:130px}.orgchart .node>.hazy{opacity:.2}.orgchart .node>.spinner{position:absolute;top:calc(50% - 15px);left:calc(50% - 15px);vertical-align:middle;font-size:30px;color:rgba(68,157,68,.8)}.orgchart .node:hover{-webkit-transition:.5s;transition:.5s;cursor:default;z-index:1}.orgchart .node.focused,.orgchart .node:hover{background-color:rgba(238,217,54,.5)}.orgchart .ghost-node{position:fixed;left:-10000px;top:-10000px}.orgchart .ghost-node rect{fill:#fff;stroke:#bf0000}.orgchart .node.allowedDrop{border-color:rgba(68,157,68,.9)}.orgchart .node .title{text-align:center;font-size:12px;font-weight:300;height:20px;line-height:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;background-color:#42b983;color:#fff;border-radius:4px 4px 0 0}.orgchart.b2t .node .title{-webkit-transform:rotate(-180deg);transform:rotate(-180deg);-webkit-transform-origin:center bottom;transform-origin:center bottom}.orgchart.l2r .node .title{-webkit-transform:rotate(-90deg) translate(-40px,-40px) rotateY(180deg);transform:rotate(-90deg) translate(-40px,-40px) rotateY(180deg);-webkit-transform-origin:bottom center;transform-origin:bottom center;width:120px}.orgchart.r2l .node .title{-webkit-transform:rotate(-90deg) translate(-40px,-40px);transform:rotate(-90deg) translate(-40px,-40px);-webkit-transform-origin:bottom center;transform-origin:bottom center;width:120px}.orgchart .node .title .symbol{float:left;margin-top:4px;margin-left:2px}.orgchart .node .content{width:100%;height:20px;font-size:11px;line-height:18px;border:1px solid #42b983;border-radius:0 0 4px 4px;text-align:center;background-color:#fff;color:#333;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.orgchart.b2t .node .content{-webkit-transform:rotate(180deg);transform:rotate(180deg);-webkit-transform-origin:center top;transform-origin:center top}.orgchart.l2r .node .content{-webkit-transform:rotate(-90deg) translate(-40px,-40px) rotateY(180deg);transform:rotate(-90deg) translate(-40px,-40px) rotateY(180deg);-webkit-transform-origin:top center;transform-origin:top center;width:120px}.orgchart.r2l .node .content{-webkit-transform:rotate(-90deg) translate(-40px,-40px);transform:rotate(-90deg) translate(-40px,-40px);-webkit-transform-origin:top center;transform-origin:top center;width:120px}.orgchart .node .edge{font-size:15px;position:absolute;color:rgba(68,157,68,.5);cursor:default;transition:.2s;-webkit-transition:.2s}.orgchart.noncollapsable .node .edge{display:none}.orgchart .edge:hover{color:#449d44;cursor:pointer}.orgchart .node .verticalEdge{width:calc(100% - 10px);width:-moz-calc(100% - 10px);left:5px}.orgchart .node .topEdge{top:-4px}.orgchart .node .bottomEdge{bottom:-4px}.orgchart .node .horizontalEdge{width:15px;height:calc(100% - 10px);height:-moz-calc(100% - 10px);top:5px}.orgchart .node .rightEdge{right:-4px}.orgchart .node .leftEdge{left:-4px}.orgchart .node .horizontalEdge:before{position:absolute;top:calc(50% - 7px);top:-moz-calc(50% - 7px)}.orgchart .node .rightEdge:before{right:3px}.orgchart .node .leftEdge:before{left:3px}.orgchart .node .toggleBtn{position:absolute;left:5px;bottom:-2px;color:rgba(68,157,68,.6)}.orgchart .node .toggleBtn:hover{color:rgba(68,157,68,.8)}.oc-export-btn{display:inline-block;position:absolute;right:5px;bottom:5px;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;color:#fff;background-color:#409eff;border:1px solid transparent;border-color:#409eff;border-radius:4px}.oc-export-btn:active,.oc-export-btn:focus,.oc-export-btn:hover{background-color:#409eff;border-color:#409eff}.orgchart~.mask{position:absolute;top:0;right:0;bottom:0;left:0;z-index:2;text-align:center;background-color:rgba(0,0,0,.3)}.orgchart~.mask .spinner{position:absolute;top:calc(50% - 54px);left:calc(50% - 54px);color:hsla(0,0%,100%,.8);font-size:108px}.orgchart .node{-webkit-transition:all .3s;transition:all .3s;top:0;left:0}.orgchart .slide-down{opacity:0;top:40px}.orgchart.l2r .node.slide-down,.orgchart.r2l .node.slide-down{top:130px}.orgchart .slide-up{opacity:0;top:-40px}.orgchart.l2r .node.slide-up,.orgchart.r2l .node.slide-up{top:-130px}.orgchart .slide-right{opacity:0;left:130px}.orgchart.l2r .node.slide-right,.orgchart.r2l .node.slide-right{left:40px}.orgchart .slide-left{opacity:0;left:-130px}.orgchart.l2r .node.slide-left,.orgchart.r2l .node.slide-left{left:-40px}#edit-panel{position:relative;left:10px;width:calc(100% - 40px);border-radius:4px;float:left;margin-top:20px;padding:10px 5px 10px 10px;font-size:14px;line-height:1.5;border-radius:2px;color:rgba(0,0,0,.65);background-color:#fff}#edit-panel .btn-inputs{font-size:24px}#edit-panel label{font-weight:700}#edit-panel .new-node{height:24px;-webkit-appearance:none;background-color:#fff;background-image:none;border-radius:4px;line-height:1;border:1px solid #d8dce5;-webkit-box-sizing:border-box;box-sizing:border-box;color:#5a5e66;display:inline-block;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1)}#edit-panel .new-node:focus{border-color:#409eff;outline:none}#edit-panel .new-node:hover{border-color:#b4bccc}#edit-panel.edit-parent-node .selected-node-group{display:none}#btn-remove-input,#chart-state-panel,#selected-node{margin-right:20px}#edit-panel button{display:inline-block;padding:6px 12px;margin-bottom:0;line-height:1.42857143;text-align:center;white-space:nowrap;border-radius:4px;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none}#edit-panel.edit-parent-node button:not(#btn-add-nodes){display:none}#edit-panel button:hover,.edit-panel button:active,.edit-panel button:focus{border-color:#409eff;-webkit-box-shadow:0 0 10px #409eff;box-shadow:0 0 10px #409eff}#new-nodelist{display:inline-block;list-style:none;margin-top:-2px;padding:0;vertical-align:text-top}#new-nodelist>*{padding-bottom:4px}.btn-inputs{vertical-align:sub}.btn-inputs:hover{text-shadow:0 0 4px #fff}.radio-panel input[type=radio]{border:1px solid #d8dce5;border-radius:100%;cursor:pointer;-webkit-box-sizing:border-box;box-sizing:border-box;display:inline-block;height:14px;width:14px;vertical-align:top}#edit-panel.view-state .radio-panel input[type=radio]+label{font-size:14px;font-weight:500;line-height:1}#btn-add-nodes{margin-left:20px} 2 | -------------------------------------------------------------------------------- /docs/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spiritree/vue-orgchart/c8de4152e2839e28af5561bcce9b4af0d3f046a4/docs/.nojekyll -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | ## vue-orgchart 2 | 3 | > A vue wrapper for OrgChart.js. 4 | 5 | ### Intro 6 | - First of all, thanks a lot for dabeng's great work -- [OrgChart.js](https://github.com/dabeng/OrgChart.js) 7 | - If you prefer the Vue.js Wrapper for Orgchart.js,you could try [my project](https://github.com/spiritree/vue-orgchart) 8 | 9 | ### Feature 10 | - Support import and export JSON 11 | - Supports exporting chart as a picture 12 | - draggable Orgchart 13 | - Editable Orgchart 14 | 15 | ... 16 | -------------------------------------------------------------------------------- /docs/_assets/tree.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/_coverpage.md: -------------------------------------------------------------------------------- 1 | ![logo](_assets/tree.svg) 2 | 3 | # vue-orgchart 1.0.0 4 | 5 | > A Vue.js wrapper for OrgChart.js. 6 | 7 | - Support import and export JSON 8 | - Supports exporting chart as a picture 9 | - Editable Orgchart 10 | 11 | 12 | [GitHub](https://github.com/spiritree/vue-orgchart) 13 | [Get Started](#vue-orgchart) 14 | 15 | 16 | ![color](#b3daff) 17 | -------------------------------------------------------------------------------- /docs/_navbar.md: -------------------------------------------------------------------------------- 1 | - Translations 2 | - [:cn: 中文](/zh-cn/) 3 | - [:uk: English](/) 4 | -------------------------------------------------------------------------------- /docs/_sidebar.md: -------------------------------------------------------------------------------- 1 | - Getting started 2 | - [Quick Start](quickstart) 3 | - [Chart Props](props) 4 | - Charts 5 | - [Basic Orgchart](basic) 6 | - [Pan/Zoom Orgchart](panzoom) 7 | - [Draggable Orgchart](drag) 8 | - [Export Picture Orgchart](exportpic) 9 | - [Editable Orgchart](edit) 10 | -------------------------------------------------------------------------------- /docs/basic.md: -------------------------------------------------------------------------------- 1 | ## Basic OrgChart 2 | 3 | ```html 4 | /*vue*/ 5 | 8 | 9 | 29 | ``` 30 | -------------------------------------------------------------------------------- /docs/drag.md: -------------------------------------------------------------------------------- 1 | ## Draggable OrgChart 2 | 3 | ```html 4 | /*vue*/ 5 | 8 | 9 | 29 | ``` 30 | 31 | -------------------------------------------------------------------------------- /docs/edit.md: -------------------------------------------------------------------------------- 1 | ## Editable OrgChart 2 | 3 | ```html 4 | /*vue*/ 5 | 34 | 35 | 170 | ``` 171 | ```json 172 | ``` 173 | -------------------------------------------------------------------------------- /docs/exportpic.md: -------------------------------------------------------------------------------- 1 | ## Export Picture OrgChart 2 | 3 | ```html 4 | /*vue*/ 5 | 8 | 9 | 30 | ``` 31 | -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spiritree/vue-orgchart/c8de4152e2839e28af5561bcce9b4af0d3f046a4/docs/favicon.ico -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | vue-orgchart - A vue wrapper for OrgChart.js 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /docs/index.min.js: -------------------------------------------------------------------------------- 1 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t(e["vue-orgchart"]={})}(this,function(e){"use strict";function t(e,t){return e===t||e!=e&&t!=t}function n(e,n){for(var r=e.length;r--;)if(t(e[r][0],n))return r;return-1}function r(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t-1&&e%1==0&&e<=Oe}function _(e){return null!=e&&b(e.length)&&!s(e)}function E(e,n,r){var i=e[n];Ze.call(e,n)&&t(i,r)&&(void 0!==r||n in e)||f(e,n,r)}function S(e,t){return!!(t=null==t?Ke:t)&&("number"==typeof e||Qe.test(e))&&e>-1&&e%1==0&&e0?t.split(" ").forEach(function(t){return e.classList.add(t)}):e.classList.add(t)})}},{key:"_removeClass",value:function(e,t){e.forEach(function(e){t.indexOf(" ")>0?t.split(" ").forEach(function(t){return e.classList.remove(t)}):e.classList.remove(t)})}},{key:"_css",value:function(e,t,n){e.forEach(function(e){e.style[t]=n})}},{key:"_removeAttr",value:function(e,t){e.forEach(function(e){e.removeAttribute(t)})}},{key:"_one",value:function(e,t,n,r){e.addEventListener(t,function i(o){try{n.call(r,o)}finally{e.removeEventListener(t,i)}})}},{key:"_getDescElements",value:function(e,t){var n=[];return e.forEach(function(e){return n.push.apply(n,D(e.querySelectorAll(t)))}),n}},{key:"_getJSON",value:function(e){return new Promise(function(t,n){var r=new XMLHttpRequest;r.open("GET",e),r.onreadystatechange=function(){4===this.readyState&&(200===this.status?t(JSON.parse(this.response)):n(new Error(this.statusText)))},r.responseType="json",r.setRequestHeader("Content-Type","application/json"),r.send()})}},{key:"_buildJsonDS",value:function(e){var t=this,n={name:e.firstChild.textContent.trim(),relationship:("LI"===e.parentNode.parentNode.nodeName?"1":"0")+(e.parentNode.children.length>1?1:0)+(e.children.length?1:0)};return e.id&&(n.id=e.id),e.querySelector("ul")&&Array.from(e.querySelector("ul").children).forEach(function(e){n.children||(n.children=[]),n.children.push(t._buildJsonDS(e))}),n}},{key:"_attachRel",value:function(e,t){if(e.relationship=t+(e.children&&e.children.length>0?1:0),e.children){var n=!0,r=!1,i=void 0;try{for(var o,s=e.children[Symbol.iterator]();!(n=(o=s.next()).done);n=!0){var a=o.value;this._attachRel(a,"1"+(e.children.length>1?1:0))}}catch(e){r=!0,i=e}finally{try{!n&&s.return&&s.return()}finally{if(r)throw i}}}return e}},{key:"_repaint",value:function(e){e&&(e.style.offsetWidth=e.offsetWidth)}},{key:"_isInAction",value:function(e){return e.querySelector(":scope > .edge").className.indexOf("fa-")>-1}},{key:"_getNodeState",value:function(e,t){var n=this,r=void 0,i={exist:!1,visible:!1};return"parent"===t?((r=this._closest(e,function(e){return e.classList&&e.classList.contains("nodes")}))&&(i.exist=!0),i.exist&&this._isVisible(r.parentNode.children[0])&&(i.visible=!0)):"children"===t?((r=this._closest(e,function(e){return"TR"===e.nodeName}).nextElementSibling)&&(i.exist=!0),i.exist&&this._isVisible(r)&&(i.visible=!0)):"siblings"===t&&((r=this._siblings(this._closest(e,function(e){return"TABLE"===e.nodeName}).parentNode)).length&&(i.exist=!0),i.exist&&r.some(function(e){return n._isVisible(e)})&&(i.visible=!0)),i}},{key:"getRelatedNodes",value:function(e,t){return"parent"===t?this._closest(e,function(e){return e.classList.contains("nodes")}).parentNode.children[0].querySelector(".node"):"children"===t?Array.from(this._closest(e,function(e){return"TABLE"===e.nodeName}).lastChild.children).map(function(e){return e.querySelector(".node")}):"siblings"===t?this._siblings(this._closest(e,function(e){return"TABLE"===e.nodeName}).parentNode).map(function(e){return e.querySelector(".node")}):[]}},{key:"_switchHorizontalArrow",value:function(e){var t=this.options,n=e.querySelector(".leftEdge"),r=e.querySelector(".rightEdge"),i=this._closest(e,function(e){return"TABLE"===e.nodeName}).parentNode;if(t.toggleSiblingsResp&&(void 0===t.ajaxURL||this._closest(e,function(e){return e.classList.contains(".nodes")}).dataset.siblingsLoaded)){var o=i.previousElementSibling,s=i.nextElementSibling;o&&(o.classList.contains("hidden")?(n.classList.add("fa-chevron-left"),n.classList.remove("fa-chevron-right")):(n.classList.add("fa-chevron-right"),n.classList.remove("fa-chevron-left"))),s&&(s.classList.contains("hidden")?(r.classList.add("fa-chevron-right"),r.classList.remove("fa-chevron-left")):(r.classList.add("fa-chevron-left"),r.classList.remove("fa-chevron-right")))}else{var a=this._siblings(i),l=!!a.length&&!a.some(function(e){return e.classList.contains("hidden")});n.classList.toggle("fa-chevron-right",l),n.classList.toggle("fa-chevron-left",!l),r.classList.toggle("fa-chevron-left",l),r.classList.toggle("fa-chevron-right",!l)}}},{key:"_hoverNode",value:function(e){var t=e.target,n=!1,r=t.querySelector(":scope > .topEdge"),i=t.querySelector(":scope > .bottomEdge"),o=t.querySelector(":scope > .leftEdge");"mouseenter"===e.type?(r&&(n=this._getNodeState(t,"parent").visible,r.classList.toggle("fa-chevron-up",!n),r.classList.toggle("fa-chevron-down",n)),i&&(n=this._getNodeState(t,"children").visible,i.classList.toggle("fa-chevron-down",!n),i.classList.toggle("fa-chevron-up",n)),o&&this._switchHorizontalArrow(t)):Array.from(t.querySelectorAll(":scope > .edge")).forEach(function(e){e.classList.remove("fa-chevron-up","fa-chevron-down","fa-chevron-right","fa-chevron-left")})}},{key:"_clickNode",value:function(e){var t=e.currentTarget,n=this.chart.querySelector(".focused");n&&n.classList.remove("focused"),t.classList.add("focused")}},{key:"_buildParentNode",value:function(e,t,n){var r=this,i=document.createElement("table");t.relationship=t.relationship||"001",this._createNode(t,0).then(function(e){var t=r.chart;e.classList.remove("slide-up"),e.classList.add("slide-down");var o=document.createElement("tr"),s=document.createElement("tr"),a=document.createElement("tr"),l=document.createElement("tr");o.setAttribute("class","hidden"),o.innerHTML='',i.appendChild(o),s.setAttribute("class","lines hidden"),s.innerHTML='
',i.appendChild(s),a.setAttribute("class","lines hidden"),a.innerHTML='  ',i.appendChild(a),l.setAttribute("class","nodes"),l.innerHTML='',i.appendChild(l),i.querySelector("td").appendChild(e),t.insertBefore(i,t.children[0]),i.children[3].children[0].appendChild(t.lastChild),n()}).catch(function(e){console.error("Failed to create parent node",e)})}},{key:"_switchVerticalArrow",value:function(e){e.classList.toggle("fa-chevron-up"),e.classList.toggle("fa-chevron-down")}},{key:"showParent",value:function(e){var t=this._prevAll(this._closest(e,function(e){return e.classList.contains("nodes")}));this._removeClass(t,"hidden"),this._addClass(Array(t[0].children).slice(1,-1),"hidden");var n=t[2].querySelector(".node");this._one(n,"transitionend",function(){n.classList.remove("slide"),this._isInAction(e)&&this._switchVerticalArrow(e.querySelector(":scope > .topEdge"))},this),this._repaint(n),n.classList.add("slide"),n.classList.remove("slide-down")}},{key:"showSiblings",value:function(e,t){var n=this,r=[],i=this._closest(e,function(e){return"TABLE"===e.nodeName}).parentNode;r=t?"left"===t?this._prevAll(i):this._nextAll(i):this._siblings(i),this._removeClass(r,"hidden");var o=this._prevAll(this._closest(e,function(e){return e.classList.contains("nodes")}));if(i=Array.from(o[0].querySelectorAll(":scope > .hidden")),t?this._removeClass(i.slice(0,2*r.length),"hidden"):this._removeClass(i,"hidden"),!this._getNodeState(e,"parent").visible){this._removeClass(o,"hidden");var s=o[2].querySelector(".node");this._one(s,"transitionend",function(e){e.target.classList.remove("slide")},this),this._repaint(s),s.classList.add("slide"),s.classList.remove("slide-down")}r.forEach(function(e){Array.from(e.querySelectorAll(".node")).forEach(function(e){n._isVisible(e)&&(e.classList.add("slide"),e.classList.remove("slide-left","slide-right"))})}),this._one(r[0].querySelector(".slide"),"transitionend",function(){var t=this;r.forEach(function(e){t._removeClass(Array.from(e.querySelectorAll(".slide")),"slide")}),this._isInAction(e)&&(this._switchHorizontalArrow(e),e.querySelector(".topEdge").classList.remove("fa-chevron-up"),e.querySelector(".topEdge").classList.add("fa-chevron-down"))},this)}},{key:"hideSiblings",value:function(e,t){var n=this,r=this._closest(e,function(e){return"TABLE"===e.nodeName}).parentNode;if(this._siblings(r).forEach(function(e){e.querySelector(".spinner")&&(n.chart.dataset.inAjax=!1)}),!t||t&&"left"===t){this._prevAll(r).forEach(function(e){Array.from(e.querySelectorAll(".node")).forEach(function(e){n._isVisible(e)&&e.classList.add("slide","slide-right")})})}if(!t||t&&"left"!==t){this._nextAll(r).forEach(function(e){Array.from(e.querySelectorAll(".node")).forEach(function(e){n._isVisible(e)&&e.classList.add("slide","slide-left")})})}var i=[];this._siblings(r).forEach(function(e){Array.prototype.push.apply(i,Array.from(e.querySelectorAll(".slide")))});var o=[],s=!0,a=!1,l=void 0;try{for(var c,d=i[Symbol.iterator]();!(s=(c=d.next()).done);s=!0){var u=c.value,h=this._closest(u,function(e){return e.classList.contains("nodes")}).previousElementSibling;o.push(h),o.push(h.previousElementSibling)}}catch(e){a=!0,l=e}finally{try{!s&&d.return&&d.return()}finally{if(a)throw l}}(o=[].concat(D(new Set(o)))).forEach(function(e){e.style.visibility="hidden"}),this._one(i[0],"transitionend",function(n){var s=this;o.forEach(function(e){e.removeAttribute("style")});var a=[];a=t?"left"===t?this._prevAll(r,":not(.hidden)"):this._nextAll(r,":not(.hidden)"):this._siblings(r);var l=Array.from(this._closest(r,function(e){return e.classList.contains("nodes")}).previousElementSibling.querySelectorAll(":scope > :not(.hidden)")).slice(1,t?2*a.length+1:-1);this._addClass(l,"hidden"),this._removeClass(i,"slide"),a.forEach(function(e){Array.from(e.querySelectorAll(".node")).slice(1).forEach(function(e){s._isVisible(e)&&(e.classList.remove("slide-left","slide-right"),e.classList.add("slide-up"))})}),a.forEach(function(e){s._addClass(Array.from(e.querySelectorAll(".lines")),"hidden"),s._addClass(Array.from(e.querySelectorAll(".nodes")),"hidden"),s._addClass(Array.from(e.querySelectorAll(".verticalNodes")),"hidden")}),this._addClass(a,"hidden"),this._isInAction(e)&&this._switchHorizontalArrow(e)},this)}},{key:"hideParent",value:function(e){var t=Array.from(this._closest(e,function(e){return e.classList.contains("nodes")}).parentNode.children).slice(0,3);t[0].querySelector(".spinner")&&(this.chart.dataset.inAjax=!1),this._getNodeState(e,"siblings").visible&&this.hideSiblings(e);var n=t.slice(1);this._css(n,"visibility","hidden");var r=t[0].querySelector(".node"),i=this._getNodeState(r,"parent").visible;r&&this._isVisible(r)&&(r.classList.add("slide","slide-down"),this._one(r,"transitionend",function(){r.classList.remove("slide"),this._removeAttr(n,"style"),this._addClass(t,"hidden")},this)),r&&i&&this.hideParent(r)}},{key:"addParent",value:function(e,t){var n=this;this._buildParentNode(e,t,function(){if(!e.querySelector(":scope > .topEdge")){var t=document.createElement("i");t.setAttribute("class","edge verticalEdge topEdge fa"),e.appendChild(t)}n.showParent(e)})}},{key:"_startLoading",value:function(e,t){var n=this.options,r=this.chart;if(void 0!==r.dataset.inAjax&&"true"===r.dataset.inAjax)return!1;e.classList.add("hidden");var i=document.createElement("i");i.setAttribute("class","fa fa-circle-o-notch fa-spin spinner"),t.appendChild(i),this._addClass(Array.from(t.querySelectorAll(":scope > *:not(.spinner)")),"hazy"),r.dataset.inAjax=!0;var o=this.chartContainer.querySelector(".oc-export-btn"+(""!==n.chartClass?"."+n.chartClass:""));return o&&(o.disabled=!0),!0}},{key:"_endLoading",value:function(e,t){var n=this.options;e.classList.remove("hidden"),t.querySelector(":scope > .spinner").remove(),this._removeClass(Array.from(t.querySelectorAll(":scope > .hazy")),"hazy"),this.chart.dataset.inAjax=!1;var r=this.chartContainer.querySelector(".oc-export-btn"+(""!==n.chartClass?"."+n.chartClass:""));r&&(r.disabled=!1)}},{key:"_clickTopEdge",value:function(e){e.stopPropagation();var t=this,n=e.target,r=n.parentNode,i=this._getNodeState(r,"parent"),o=this.options;if(i.exist){var s=this._closest(r,function(e){return e.classList.contains("nodes")}).parentNode.firstChild.querySelector(".node");if(s.classList.contains("slide"))return;i.visible?(this.hideParent(r),this._one(s,"transitionend",function(){this._isInAction(r)&&(this._switchVerticalArrow(n),this._switchHorizontalArrow(r))},this)):this.showParent(r)}else{var a=n.parentNode.id;this._startLoading(n,r)&&this._getJSON("function"==typeof o.ajaxURL.parent?o.ajaxURL.parent(r.dataset.source):o.ajaxURL.parent+a).then(function(e){"true"===t.chart.dataset.inAjax&&Object.keys(e).length&&t.addParent(r,e)}).catch(function(e){console.error("Failed to get parent node data.",e)}).finally(function(){t._endLoading(n,r)})}}},{key:"hideChildren",value:function(e){var t=this,n=this._nextAll(e.parentNode.parentNode),r=n[n.length-1],i=[];r.querySelector(".spinner")&&(this.chart.dataset.inAjax=!1);var o=Array.from(r.querySelectorAll(".node")).filter(function(e){return t._isVisible(e)}),s=r.classList.contains("verticalNodes");s||(o.forEach(function(e){Array.prototype.push.apply(i,t._prevAll(t._closest(e,function(e){return e.classList.contains("nodes")}),".lines"))}),i=[].concat(D(new Set(i))),this._css(i,"visibility","hidden")),this._one(o[0],"transitionend",function(a){this._removeClass(o,"slide"),s?t._addClass(n,"hidden"):(i.forEach(function(e){e.removeAttribute("style"),e.classList.add("hidden"),e.parentNode.lastChild.classList.add("hidden")}),this._addClass(Array.from(r.querySelectorAll(".verticalNodes")),"hidden")),this._isInAction(e)&&this._switchVerticalArrow(e.querySelector(".bottomEdge"))},this),this._addClass(o,"slide slide-up")}},{key:"showChildren",value:function(e){var t=this,n=this,r=this._nextAll(e.parentNode.parentNode),i=[];this._removeClass(r,"hidden"),r.some(function(e){return e.classList.contains("verticalNodes")})?r.forEach(function(e){Array.prototype.push.apply(i,Array.from(e.querySelectorAll(".node")).filter(function(e){return n._isVisible(e)}))}):Array.from(r[2].children).forEach(function(e){Array.prototype.push.apply(i,Array.from(e.querySelector("tr").querySelectorAll(".node")).filter(function(e){return n._isVisible(e)}))}),this._repaint(i[0]),this._one(i[0],"transitionend",function(n){t._removeClass(i,"slide"),t._isInAction(e)&&t._switchVerticalArrow(e.querySelector(".bottomEdge"))},this),this._addClass(i,"slide"),this._removeClass(i,"slide-up")}},{key:"_buildChildNode",value:function(e,t,n){var r=t.children||t.siblings;e.querySelector("td").setAttribute("colSpan",2*r.length),this.buildHierarchy(e,{children:r},0,n)}},{key:"addChildren",value:function(e,t){var n=this,r=this.options,i=0;this.chart.dataset.inEdit="addChildren",this._buildChildNode.call(this,this._closest(e,function(e){return"TABLE"===e.nodeName}),t,function(){if(++i===t.children.length){if(!e.querySelector(".bottomEdge")){var o=document.createElement("i");o.setAttribute("class","edge verticalEdge bottomEdge fa"),e.appendChild(o)}if(!e.querySelector(".symbol")){var s=document.createElement("i");s.setAttribute("class","fa "+r.parentNodeSymbol+" symbol"),e.querySelector(":scope > .title").appendChild(s)}n.showChildren(e),n.chart.dataset.inEdit=""}})}},{key:"_clickBottomEdge",value:function(e){var t=this;e.stopPropagation();var n=this,r=this.options,i=e.target,o=i.parentNode,s=this._getNodeState(o,"children");if(s.exist){var a=this._closest(o,function(e){return"TR"===e.nodeName}).parentNode.lastChild;if(Array.from(a.querySelectorAll(".node")).some(function(e){return t._isVisible(e)&&e.classList.contains("slide")}))return;s.visible?this.hideChildren(o):this.showChildren(o)}else{var l=i.parentNode.id;this._startLoading(i,o)&&this._getJSON("function"==typeof r.ajaxURL.children?r.ajaxURL.children(o.dataset.source):r.ajaxURL.children+l).then(function(e){"true"===n.chart.dataset.inAjax&&e.children.length&&n.addChildren(o,e)}).catch(function(e){console.error("Failed to get children nodes data",e)}).finally(function(){n._endLoading(i,o)})}}},{key:"_complementLine",value:function(e,t,n){var r=e.parentNode.parentNode.children;r[0].children[0].setAttribute("colspan",2*t),r[1].children[0].setAttribute("colspan",2*t);for(var i=0;i1?Math.floor(a/2-1):0;if("TD"===e.parentNode.nodeName){var c=this._prevAll(e.parentNode.parentNode);c[0].remove(),c[1].remove();var d=0;i._buildChildNode.call(i,i._closest(e.parentNode,function(e){return"TABLE"===e.nodeName}),t,function(){if(++d===o){var t=Array.from(i._closest(e.parentNode,function(e){return"TABLE"===e.nodeName}).lastChild.children);if(s>1){var r=e.parentNode.parentNode;Array.from(r.children).forEach(function(e){t[0].parentNode.insertBefore(e,t[0])}),r.remove(),i._complementLine(t[0],a,s),i._addClass(t,"hidden"),t.forEach(function(e){i._addClass(e.querySelectorAll(".node"),"slide-left")})}else{var c=e.parentNode.parentNode;t[l].parentNode.insertBefore(e.parentNode,t[l+1]),c.remove(),i._complementLine(t[l],a,1),i._addClass(t,"hidden"),i._addClass(i._getDescElements(t.slice(0,l+1),".node"),"slide-right"),i._addClass(i._getDescElements(t.slice(l+1),".node"),"slide-left")}n()}})}else{var u=0;i.buildHierarchy.call(i,i.chart,t,0,function(){if(++u===a){var t=e.nextElementSibling.children[3].children[l],o=document.createElement("td");o.setAttribute("colspan",2),o.appendChild(e),t.parentNode.insertBefore(o,t.nextElementSibling),i._complementLine(t,a,1);var s=i._closest(e,function(e){return e.classList&&e.classList.contains("nodes")}).parentNode.children[0];s.classList.add("hidden"),i._addClass(Array.from(s.querySelectorAll(".node")),"slide-down");var c=r._siblings(e.parentNode);i._addClass(c,"hidden"),i._addClass(i._getDescElements(c.slice(0,l),".node"),"slide-right"),i._addClass(i._getDescElements(c.slice(l),".node"),"slide-left"),n()}})}}},{key:"addSiblings",value:function(e,t){var n=this;this.chart.dataset.inEdit="addSiblings",this._buildSiblingNode.call(this,this._closest(e,function(e){return"TABLE"===e.nodeName}),t,function(){if(n._closest(e,function(e){return e.classList&&e.classList.contains("nodes")}).dataset.siblingsLoaded=!0,!e.querySelector(".leftEdge")){var t=document.createElement("i"),r=document.createElement("i");t.setAttribute("class","edge horizontalEdge rightEdge fa"),e.appendChild(t),r.setAttribute("class","edge horizontalEdge leftEdge fa"),e.appendChild(r)}n.showSiblings(e),n.chart.dataset.inEdit=""})}},{key:"removeNodes",value:function(e){var t=this._closest(e,function(e){return"TABLE"===e.nodeName}).parentNode,n=this._siblings(t.parentNode);"TD"===t.nodeName?this._getNodeState(e,"siblings").exist?(n[2].querySelector(".topLine").nextElementSibling.remove(),n[2].querySelector(".topLine").remove(),n[0].children[0].setAttribute("colspan",n[2].children.length),n[1].children[0].setAttribute("colspan",n[2].children.length),t.remove()):(n[0].children[0].removeAttribute("colspan"),n[0].querySelector(".bottomEdge").remove(),this._siblings(n[0]).forEach(function(e){return e.remove()})):Array.from(t.parentNode.children).forEach(function(e){return e.remove()})}},{key:"_clickHorizontalEdge",value:function(e){var t=this;e.stopPropagation();var n=this,r=this.options,i=e.target,o=i.parentNode,s=this._getNodeState(o,"siblings");if(s.exist){var a=this._closest(o,function(e){return"TABLE"===e.nodeName}).parentNode;if(this._siblings(a).some(function(e){var n=e.querySelector(".node");return t._isVisible(n)&&n.classList.contains("slide")}))return;if(r.toggleSiblingsResp){var l=this._closest(o,function(e){return"TABLE"===e.nodeName}).parentNode.previousElementSibling,c=this._closest(o,function(e){return"TABLE"===e.nodeName}).parentNode.nextElementSibling;i.classList.contains("leftEdge")?l.classList.contains("hidden")?this.showSiblings(o,"left"):this.hideSiblings(o,"left"):c.classList.contains("hidden")?this.showSiblings(o,"right"):this.hideSiblings(o,"right")}else s.visible?this.hideSiblings(o):this.showSiblings(o)}else{var d=i.parentNode.id,u=this._getNodeState(o,"parent").exist?"function"==typeof r.ajaxURL.siblings?r.ajaxURL.siblings(JSON.parse(o.dataset.source)):r.ajaxURL.siblings+d:"function"==typeof r.ajaxURL.families?r.ajaxURL.families(JSON.parse(o.dataset.source)):r.ajaxURL.families+d;this._startLoading(i,o)&&this._getJSON(u).then(function(e){"true"===n.chart.dataset.inAjax&&(e.siblings||e.children)&&n.addSiblings(o,e)}).catch(function(e){console.error("Failed to get sibling nodes data",e)}).finally(function(){n._endLoading(i,o)})}}},{key:"_clickToggleButton",value:function(e){var t=this,n=e.target,r=n.parentNode.nextElementSibling,i=Array.from(r.querySelectorAll(".node")),o=Array.from(r.children).map(function(e){return e.querySelector(".node")});o.some(function(e){return e.classList.contains("slide")})||(n.classList.toggle("fa-plus-square"),n.classList.toggle("fa-minus-square"),i[0].classList.contains("slide-up")?(r.classList.remove("hidden"),this._repaint(o[0]),this._addClass(o,"slide"),this._removeClass(o,"slide-up"),this._one(o[0],"transitionend",function(){t._removeClass(o,"slide")})):(this._addClass(i,"slide slide-up"),this._one(i[0],"transitionend",function(){t._removeClass(i,"slide"),i.forEach(function(e){t._closest(e,function(e){return"UL"===e.nodeName}).classList.add("hidden")})}),i.forEach(function(e){var n=Array.from(e.querySelectorAll(".toggleBtn"));t._removeClass(n,"fa-minus-square"),t._addClass(n,"fa-plus-square")})))}},{key:"_dispatchClickEvent",value:function(e){var t=e.target.classList;t.contains("topEdge")?this._clickTopEdge(e):t.contains("rightEdge")||t.contains("leftEdge")?this._clickHorizontalEdge(e):t.contains("bottomEdge")?this._clickBottomEdge(e):t.contains("toggleBtn")?this._clickToggleButton(e):this._clickNode(e)}},{key:"_onDragStart",value:function(e){var t=e.target,n=this.options,r=/firefox/.test(window.navigator.userAgent.toLowerCase());if(r&&e.dataTransfer.setData("text/html","hack for firefox"),this.chart.style.transform){var i=void 0,o=void 0;document.querySelector(".ghost-node")?o=(i=this.chart.querySelector(":scope > .ghost-node")).children[0]:((i=document.createElementNS("http://www.w3.org/2000/svg","svg")).classList.add("ghost-node"),o=document.createElementNS("http://www.w3.org/2000/svg","rect"),i.appendChild(o),this.chart.appendChild(i));var s=this.chart.style.transform.split(","),a=Math.abs(window.parseFloat("t2b"===n.direction||"b2t"===n.direction?s[0].slice(s[0].indexOf("(")+1):s[1]));i.setAttribute("width",t.offsetWidth),i.setAttribute("height",t.offsetHeight),o.setAttribute("x",5*a),o.setAttribute("y",5*a),o.setAttribute("width",120*a),o.setAttribute("height",40*a),o.setAttribute("rx",4*a),o.setAttribute("ry",4*a),o.setAttribute("stroke-width",1*a);var l=e.offsetX*a,c=e.offsetY*a;if("l2r"===n.direction?(l=e.offsetY*a,c=e.offsetX*a):"r2l"===n.direction?(l=t.offsetWidth-e.offsetY*a,c=e.offsetX*a):"b2t"===n.direction&&(l=t.offsetWidth-e.offsetX*a,c=t.offsetHeight-e.offsetY*a),r){var d=document.createElement("img");d.src="data:image/svg+xml;utf8,"+(new XMLSerializer).serializeToString(i),e.dataTransfer.setDragImage(d,l,c),o.setAttribute("fill","rgb(255, 255, 255)"),o.setAttribute("stroke","rgb(191, 0, 0)")}else e.dataTransfer.setDragImage(i,l,c)}var u=e.target,h=this._closest(u,function(e){return e.classList&&e.classList.contains("nodes")}).parentNode.children[0].querySelector(".node"),f=Array.from(this._closest(u,function(e){return"TABLE"===e.nodeName}).querySelectorAll(".node"));this.dragged=u,Array.from(this.chart.querySelectorAll(".node")).forEach(function(e){f.includes(e)||(n.dropCriteria?n.dropCriteria(u,h,e)&&e.classList.add("allowedDrop"):e.classList.add("allowedDrop"))})}},{key:"_onDragOver",value:function(e){e.preventDefault();e.currentTarget.classList.contains("allowedDrop")||(e.dataTransfer.dropEffect="none")}},{key:"_onDragEnd",value:function(e){Array.from(this.chart.querySelectorAll(".allowedDrop")).forEach(function(e){e.classList.remove("allowedDrop")})}},{key:"_onDrop",value:function(e){var t=e.currentTarget,n=this.chart,r=this.dragged,i=this._closest(r,function(e){return e.classList&&e.classList.contains("nodes")}).parentNode.children[0].children[0];if(this._removeClass(Array.from(n.querySelectorAll(".allowedDrop")),"allowedDrop"),t.parentNode.parentNode.nextElementSibling){var o=window.parseInt(t.parentNode.colSpan)+2;if(t.parentNode.setAttribute("colspan",o),t.parentNode.parentNode.nextElementSibling.children[0].setAttribute("colspan",o),!r.querySelector(".horizontalEdge")){var s=document.createElement("i"),a=document.createElement("i");s.setAttribute("class","edge horizontalEdge rightEdge fa"),r.appendChild(s),a.setAttribute("class","edge horizontalEdge leftEdge fa"),r.appendChild(a)}var l=t.parentNode.parentNode.nextElementSibling.nextElementSibling,c=document.createElement("td"),d=document.createElement("td");c.setAttribute("class","leftLine topLine"),c.innerHTML=" ",l.insertBefore(c,l.children[1]),d.setAttribute("class","rightLine topLine"),d.innerHTML=" ",l.insertBefore(d,l.children[2]),l.nextElementSibling.appendChild(this._closest(r,function(e){return"TABLE"===e.nodeName}).parentNode);var u=this._siblings(this._closest(r,function(e){return"TABLE"===e.nodeName}).parentNode).map(function(e){return e.querySelector(".node")});if(1===u.length){var h=document.createElement("i"),f=document.createElement("i");h.setAttribute("class","edge horizontalEdge rightEdge fa"),u[0].appendChild(h),f.setAttribute("class","edge horizontalEdge leftEdge fa"),u[0].appendChild(f)}}else{var p=document.createElement("i");p.setAttribute("class","edge verticalEdge bottomEdge fa"),t.appendChild(p),t.parentNode.setAttribute("colspan",2);var v=this._closest(t,function(e){return"TABLE"===e.nodeName}),g=document.createElement("tr"),y=document.createElement("tr"),m=document.createElement("tr");g.setAttribute("class","lines"),g.innerHTML='
',v.appendChild(g),y.setAttribute("class","lines"),y.innerHTML='  ',v.appendChild(y),m.setAttribute("class","nodes"),v.appendChild(m),Array.from(r.querySelectorAll(".horizontalEdge")).forEach(function(e){r.removeChild(e)});var b=this._closest(r,function(e){return"TABLE"===e.nodeName}).parentNode;m.appendChild(b)}var _=window.parseInt(i.colSpan);if(_>2){i.setAttribute("colspan",_-2),i.parentNode.nextElementSibling.children[0].setAttribute("colspan",_-2);var E=i.parentNode.nextElementSibling.nextElementSibling;E.children[1].remove(),E.children[1].remove();var S=Array.from(i.parentNode.parentNode.children[3].children).map(function(e){return e.querySelector(".node")});1===S.length&&(S[0].querySelector(".leftEdge").remove(),S[0].querySelector(".rightEdge").remove())}else i.removeAttribute("colspan"),i.querySelector(".node").removeChild(i.querySelector(".bottomEdge")),Array.from(i.parentNode.parentNode.children).slice(1).forEach(function(e){return e.remove()});var A=new CustomEvent("nodedropped.orgchart",{detail:{draggedNode:r,dragZone:i.children[0],dropZone:t}});n.dispatchEvent(A)}},{key:"_createNode",value:function(e,t){var n=this,r=this.options;return new Promise(function(i,o){if(e.children){var s=!0,a=!1,l=void 0;try{for(var c,d=e.children[Symbol.iterator]();!(s=(c=d.next()).done);s=!0){c.value.parentId=e.id}}catch(e){a=!0,l=e}finally{try{!s&&d.return&&d.return()}finally{if(a)throw l}}}var u=document.createElement("div");delete e.children,u.dataset.source=JSON.stringify(e),e[r.nodeId]&&(u.id=e[r.nodeId]);var h=n.chart.dataset.inEdit,f=void 0;f=h?"addChildren"===h?" slide-up":"":t>=r.depth?" slide-up":"",u.setAttribute("class","node "+(e.className||"")+f),r.draggable&&u.setAttribute("draggable",!0),e.parentId&&u.setAttribute("data-parent",e.parentId),u.innerHTML='\n
'+e[r.nodeTitle]+"
\n "+(r.nodeContent?'
'+e[r.nodeContent]+"
":"")+"\n ";var p=e.relationship||"";if(r.verticalDepth&&t+2>r.verticalDepth){if(t+1>=r.verticalDepth&&Number(p.substr(2,1))){var v=document.createElement("i"),g=t+1>=r.depth?"plus":"minus";v.setAttribute("class","toggleBtn fa fa-"+g+"-square"),u.appendChild(v)}}else{if(Number(p.substr(0,1))){var y=document.createElement("i");y.setAttribute("class","edge verticalEdge topEdge fa"),u.appendChild(y)}if(Number(p.substr(1,1))){var m=document.createElement("i"),b=document.createElement("i");m.setAttribute("class","edge horizontalEdge rightEdge fa"),u.appendChild(m),b.setAttribute("class","edge horizontalEdge leftEdge fa"),u.appendChild(b)}if(Number(p.substr(2,1))){var _=document.createElement("i"),E=document.createElement("i"),S=u.querySelector(":scope > .title");_.setAttribute("class","edge verticalEdge bottomEdge fa"),u.appendChild(_),E.setAttribute("class","fa "+r.parentNodeSymbol+" symbol"),S.insertBefore(E,S.children[0])}}u.addEventListener("mouseenter",n._hoverNode.bind(n)),u.addEventListener("mouseleave",n._hoverNode.bind(n)),u.addEventListener("click",n._dispatchClickEvent.bind(n)),r.draggable&&(u.addEventListener("dragstart",n._onDragStart.bind(n)),u.addEventListener("dragover",n._onDragOver.bind(n)),u.addEventListener("dragend",n._onDragEnd.bind(n)),u.addEventListener("drop",n._onDrop.bind(n))),r.createNode&&r.createNode(u,e),i(u)})}},{key:"buildHierarchy",value:function(e,t,n,r){var i=this,o=this.options,s=void 0,a=t.children,l=o.verticalDepth&&n+1>=o.verticalDepth;if(Object.keys(t).length>1&&(s=l?e:document.createElement("table"),l||e.appendChild(s),this._createNode(t,n).then(function(e){if(l)s.insertBefore(e,s.firstChild);else{var t=document.createElement("tr");t.innerHTML="\n \n \n ",t.children[0].appendChild(e),s.insertBefore(t,s.children[0]?s.children[0]:null)}r&&r()}).catch(function(e){console.error("Failed to creat node",e)})),a){1===Object.keys(t).length&&(s=e);var c=void 0,d=o.verticalDepth&&n+2>=o.verticalDepth,u=i.chart.dataset.inEdit;if(c=u?"addSiblings"===u?"":" hidden":n+1>=o.depth?" hidden":"",!d){var h=document.createElement("tr");h.setAttribute("class","lines"+c),h.innerHTML='\n \n
\n \n ',s.appendChild(h)}var f=document.createElement("tr");f.setAttribute("class","lines"+c),f.innerHTML='\n  \n '+a.slice(1).map(function(){return'\n  \n  \n '}).join("")+'\n  \n ';var p=void 0;if(d)if(p=document.createElement("ul"),c&&p.classList.add(c.trim()),n+2===o.verticalDepth){var v=document.createElement("tr");v.setAttribute("class","verticalNodes"+c),v.innerHTML="",v.firstChild.appendChild(p),s.appendChild(v)}else s.appendChild(p);else(p=document.createElement("tr")).setAttribute("class","nodes"+c),s.appendChild(f),s.appendChild(p);a.forEach(function(e){var t=void 0;d?t=document.createElement("li"):(t=document.createElement("td")).setAttribute("colspan",2),p.appendChild(t),i.buildHierarchy(t,e,n+1,r)})}}},{key:"_clickChart",value:function(e){!this._closest(e.target,function(e){return e.classList&&e.classList.contains("node")})&&this.chart.querySelector(".node.focused")&&this.chart.querySelector(".node.focused").classList.remove("focused")}},{key:"_clickExportButton",value:function(){var e=this.options,t=this.chartContainer,n=t.querySelector(":scope > .mask"),r=t.querySelector(".orgchart:not(.hidden)"),i="l2r"===e.direction||"r2l"===e.direction;n?n.classList.remove("hidden"):((n=document.createElement("div")).setAttribute("class","mask"),n.innerHTML='',t.appendChild(n)),t.classList.add("canvasContainer"),window.html2canvas(r,{width:i?r.clientHeight:r.clientWidth,height:i?r.clientWidth:r.clientHeight,onclone:function(e){var t=e.querySelector(".canvasContainer");t.style.overflow="visible",t.querySelector(".orgchart:not(.hidden)").transform=""}}).then(function(e){var n=t.querySelector(".oc-download-btn");t.querySelector(".mask").classList.add("hidden"),n.setAttribute("href",e.toDataURL()),n.click()}).catch(function(e){console.error("Failed to export the curent orgchart!",e)}).finally(function(){t.classList.remove("canvasContainer")})}},{key:"_loopChart",value:function(e){var t=this,n={id:e.querySelector(".node").id};return e.children[3]&&Array.from(e.children[3].children).forEach(function(e){n.children||(n.children=[]),n.children.push(t._loopChart(e.firstChild))}),n}},{key:"_loopChartDataset",value:function(e){var t=this,n=JSON.parse(e.querySelector(".node").dataset.source);return e.children[3]&&Array.from(e.children[3].children).forEach(function(e){n.children||(n.children=[]),n.children.push(t._loopChartDataset(e.firstChild))}),n}},{key:"getChartJSON",value:function(){return this.chart.querySelector(".node").id?this._loopChartDataset(this.chart.querySelector("table")):"Error: Nodes of orghcart to be exported must have id attribute!"}},{key:"getHierarchy",value:function(){return this.chart.querySelector(".node").id?this._loopChart(this.chart.querySelector("table")):"Error: Nodes of orghcart to be exported must have id attribute!"}},{key:"_onPanStart",value:function(e){var t=e.currentTarget;if(this._closest(e.target,function(e){return e.classList&&e.classList.contains("node")})||e.touches&&e.touches.length>1)t.dataset.panning=!1;else{t.style.cursor="move",t.dataset.panning=!0;var n=0,r=0,i=window.getComputedStyle(t).transform;if("none"!==i){var o=i.split(",");i.includes("3d")?(n=Number.parseInt(o[12],10),r=Number.parseInt(o[13],10)):(n=Number.parseInt(o[4],10),r=Number.parseInt(o[5],10))}var s=0,a=0;if(e.targetTouches){if(1===e.targetTouches.length)s=e.targetTouches[0].pageX-n,a=e.targetTouches[0].pageY-r;else if(e.targetTouches.length>1)return}else s=e.pageX-n,a=e.pageY-r;t.dataset.panStart=JSON.stringify({startX:s,startY:a}),t.addEventListener("mousemove",this._onPanning.bind(this)),t.addEventListener("touchmove",this._onPanning.bind(this))}}},{key:"_onPanning",value:function(e){var t=e.currentTarget;if("false"!==t.dataset.panning){var n=0,r=0,i=JSON.parse(t.dataset.panStart),o=i.startX,s=i.startY;if(e.targetTouches){if(1===e.targetTouches.length)n=e.targetTouches[0].pageX-o,r=e.targetTouches[0].pageY-s;else if(e.targetTouches.length>1)return}else n=e.pageX-o,r=e.pageY-s;var a=window.getComputedStyle(t).transform;if("none"===a)a.includes("3d")?t.style.transform="matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, "+n+", "+r+", 0, 1)":t.style.transform="matrix(1, 0, 0, 1, "+n+", "+r+")";else{var l=a.split(",");a.includes("3d")?(l[12]=n,l[13]=r):(l[4]=n,l[5]=r+")"),t.style.transform=l.join(",")}}}},{key:"_onPanEnd",value:function(e){var t=this.chart;"true"===t.dataset.panning&&(t.dataset.panning=!1,t.style.cursor="default",document.body.removeEventListener("mousemove",this._onPanning),document.body.removeEventListener("touchmove",this._onPanning))}},{key:"_setChartScale",value:function(e,t){var n=window.getComputedStyle(e).transform;if("none"===n)e.style.transform="scale("+t+","+t+")";else{var r=n.split(",");n.includes("3d")?e.style.transform=n+" scale3d("+t+","+t+", 1)":(r[0]="matrix("+t,r[3]=t,e.style.transform=n+" scale("+t+","+t+")")}e.dataset.scale=t}},{key:"_onWheeling",value:function(e){e.preventDefault();var t=e.deltaY>0?.8:1.2;this._setChartScale(this.chart,t)}},{key:"_getPinchDist",value:function(e){return Math.sqrt((e.touches[0].clientX-e.touches[1].clientX)*(e.touches[0].clientX-e.touches[1].clientX)+(e.touches[0].clientY-e.touches[1].clientY)*(e.touches[0].clientY-e.touches[1].clientY))}},{key:"_onTouchStart",value:function(e){var t=this.chart;if(e.touches&&2===e.touches.length){var n=this._getPinchDist(e);t.dataset.pinching=!0,t.dataset.pinchDistStart=n}}},{key:"_onTouchMove",value:function(e){var t=this.chart;if(t.dataset.pinching){var n=this._getPinchDist(e);t.dataset.pinchDistEnd=n}}},{key:"_onTouchEnd",value:function(e){var t=this.chart;if(t.dataset.pinching){t.dataset.pinching=!1;var n=t.dataset.pinchDistEnd-t.dataset.pinchDistStart;n>0?this._setChartScale(t,1):n<0&&this._setChartScale(t,-1)}}},{key:"name",get:function(){return this._name}}]),e}(),z=Array.prototype.splice;r.prototype.clear=function(){this.__data__=[],this.size=0},r.prototype.delete=function(e){var t=this.__data__,r=n(t,e);return!(r<0||(r==t.length-1?t.pop():z.call(t,r,1),--this.size,0))},r.prototype.get=function(e){var t=this.__data__,r=n(t,e);return r<0?void 0:t[r][1]},r.prototype.has=function(e){return n(this.__data__,e)>-1},r.prototype.set=function(e,t){var r=this.__data__,i=n(r,e);return i<0?(++this.size,r.push([e,t])):r[i][1]=t,this};var H="object"==typeof global&&global&&global.Object===Object&&global,R="object"==typeof self&&self&&self.Object===Object&&self,I=H||R||Function("return this")(),M=I.Symbol,F=Object.prototype,U=F.hasOwnProperty,V=F.toString,J=M?M.toStringTag:void 0,X=Object.prototype.toString,Y="[object Null]",$="[object Undefined]",W=M?M.toStringTag:void 0,G="[object AsyncFunction]",Z="[object Function]",K="[object GeneratorFunction]",Q="[object Proxy]",ee=I["__core-js_shared__"],te=function(){var e=/[^.]+$/.exec(ee&&ee.keys&&ee.keys.IE_PROTO||"");return e?"Symbol(src)_1."+e:""}(),ne=Function.prototype.toString,re=/^\[object .+?Constructor\]$/,ie=Function.prototype,oe=Object.prototype,se=ie.toString,ae=oe.hasOwnProperty,le=RegExp("^"+se.call(ae).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),ce=l(I,"Map"),de=l(Object,"create"),ue="__lodash_hash_undefined__",he=Object.prototype.hasOwnProperty,fe=Object.prototype.hasOwnProperty,pe="__lodash_hash_undefined__";c.prototype.clear=function(){this.__data__=de?de(null):{},this.size=0},c.prototype.delete=function(e){var t=this.has(e)&&delete this.__data__[e];return this.size-=t?1:0,t},c.prototype.get=function(e){var t=this.__data__;if(de){var n=t[e];return n===ue?void 0:n}return he.call(t,e)?t[e]:void 0},c.prototype.has=function(e){var t=this.__data__;return de?void 0!==t[e]:fe.call(t,e)},c.prototype.set=function(e,t){var n=this.__data__;return this.size+=this.has(e)?0:1,n[e]=de&&void 0===t?pe:t,this},u.prototype.clear=function(){this.size=0,this.__data__={hash:new c,map:new(ce||r),string:new c}},u.prototype.delete=function(e){var t=d(this,e).delete(e);return this.size-=t?1:0,t},u.prototype.get=function(e){return d(this,e).get(e)},u.prototype.has=function(e){return d(this,e).has(e)},u.prototype.set=function(e,t){var n=d(this,e),r=n.size;return n.set(e,t),this.size+=n.size==r?0:1,this};var ve=200;h.prototype.clear=function(){this.__data__=new r,this.size=0},h.prototype.delete=function(e){var t=this.__data__,n=t.delete(e);return this.size=t.size,n},h.prototype.get=function(e){return this.__data__.get(e)},h.prototype.has=function(e){return this.__data__.has(e)},h.prototype.set=function(e,t){var n=this.__data__;if(n instanceof r){var i=n.__data__;if(!ce||i.length0){if(++t>=it)return arguments[0]}else t=0;return e.apply(void 0,arguments)}}(rt),lt=function(e){return q(function(n,r){var i=-1,s=r.length,a=s>1?r[s-1]:void 0,l=s>2?r[2]:void 0;for(a=e.length>3&&"function"==typeof a?(s--,a):void 0,l&&function(e,n,r){if(!o(r))return!1;var i=typeof n;return!!("number"==i?_(r)&&S(n,r.length):"string"==i&&n in r)&&t(r[n],e)}(r[0],r[1],l)&&(a=s<3?void 0:a,s=1),n=Object(n);++i 6 | 7 | 8 | 9 | 30 | ``` 31 | -------------------------------------------------------------------------------- /docs/props.md: -------------------------------------------------------------------------------- 1 | ### Vue-OrgChart props 2 | 3 | ### Example 4 | 5 | `` 6 | 7 | `` 8 | 9 | ### Props 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 |
NameTypeRequiredDefaultDescription
datajson or stringyesdatasource usded to build out structure of orgchart. It could be a json object or a string containing the URL to which the ajax request is sent.
panbooleannofalseUsers could pan the orgchart by mouse drag&drop if they enable this option.
zoombooleannofalseUsers could zoomin/zoomout the orgchart by mouse wheel if they enable this option.
directionstringno"t2b"The available values are t2b(implies "top to bottom", it's default value), b2t(implies "bottom to top"), l2r(implies "left to right"), r2l(implies "right to left").
verticalDepthintegernoUsers can make use of this option to align the nodes vertically from the specified depth.
toggleSiblingsRespbooleannofalseOnce enable this option, users can show/hide left/right sibling nodes respectively by clicking left/right arrow.
toggleCollapsebooleannotrueShow the arrow and you can click it to collapse the node
ajaxURLjsonnoIt inclueds four properites -- parent, children, siblings, families(ask for parent node and siblings nodes). As their names imply, different propety provides the URL to which ajax request for different nodes is sent.
depthpositive integerno999It indicates the level that at the very beginning orgchart is expanded to.
nodeTitlestringno"name"It sets one property of datasource as text content of title section of orgchart node. In fact, users can create a simple orghcart with only nodeTitle option.
parentNodeSymbolstringno" "Using font awesome icon to imply that the node has child nodes.
nodeContentstringnoIt sets one property of datasource as text content of content section of orgchart node.
nodeIdstringno"id"It sets one property of datasource as unique identifier of every orgchart node.
createNodefunctionnoIt's a callback function used to customize every orgchart node. It recieves two parament: "$node" stands for jquery object of single node div; "data" stands for datasource of single node.
exportButtonbooleannofalseIt enable the export button for orgchart.
exportButtonNamestringnothe name for export Button
exportFilenamestringno"Orgchart"It's filename when you export current orgchart as a picture.
chartClassstringno""when you wanna instantiate multiple orgcharts on one page, you should add diffent classname to them in order to distinguish them.
draggablebooleannofalseUsers can drag & drop the nodes of orgchart if they enable this option. **Note**: this feature doesn't work on IE due to its poor support for HTML5 drag & drop API.
dropCriteriafunctionnoUsers can construct their own criteria to limit the relationships between dragged node and drop zone. Furtherly, this function accept three arguments(draggedNode, dragZone, dropZone) and just only return boolen values.
78 | -------------------------------------------------------------------------------- /docs/quickstart.md: -------------------------------------------------------------------------------- 1 | ## Quick Start 2 | 3 | ### Install 4 | ```shell 5 | npm install vue-orgchart -S 6 | ``` 7 | 8 | ### Import in your project 9 | 10 | > `main.js` 11 | 12 | ```js 13 | import 'vue-orgchart/dist/style.min.css' 14 | ``` 15 | 16 | > In `*.vue` 17 | 18 | ```js 19 | 20 | import { VoBasic } from 'vue-orgchart' 21 | export default { 22 | components: { VoEdit }, 23 | created () { 24 | this.chartData = { 25 | name: 'JavaScript', 26 | children: [ 27 | { name: 'Angular' }, 28 | { 29 | name: 'React', 30 | children: [{ name: 'Preact' }] 31 | }, 32 | { 33 | name: 'Vue', 34 | children: [{ name: 'Moon' }] 35 | } 36 | ] 37 | } 38 | } 39 | } 40 | ``` 41 | 42 | ### CDN 43 | ```html 44 | 45 | 46 | ``` 47 | -------------------------------------------------------------------------------- /docs/style.css: -------------------------------------------------------------------------------- 1 | iframe { 2 | border: 2px solid #eee; 3 | } 4 | 5 | * { 6 | -webkit-font-smoothing: inherit !important 7 | } 8 | 9 | .vuep { 10 | height: 460px; 11 | } 12 | 13 | .cm-error { 14 | color: rgba(255, 83, 112, 1) !important; 15 | background-color: inherit !important; 16 | } 17 | 18 | .data-empty { 19 | position: absolute; 20 | left: 0; 21 | right: 0; 22 | top: 0; 23 | bottom: 0; 24 | display: flex; 25 | justify-content: center; 26 | align-items: center; 27 | background-color: rgba(255, 255, 255, .7); 28 | color: #888; 29 | font-size: 14px; 30 | } 31 | 32 | .demo-block .source { 33 | text-align: center; 34 | } 35 | 36 | .markdown-section tr { 37 | border: 1px solid #fff; 38 | background:#fff; 39 | } 40 | -------------------------------------------------------------------------------- /docs/style.min.css: -------------------------------------------------------------------------------- 1 | #wrapper { 2 | width: 50%; 3 | margin: 0 auto; 4 | } 5 | 6 | #wrapper li { 7 | margin-top: 20px; 8 | } 9 | 10 | #wrapper a { 11 | font-size: 24px; 12 | } 13 | 14 | #wrapper span { 15 | font-size: 24px; 16 | } 17 | 18 | #chart-container { 19 | position: relative; 20 | display: inline-block; 21 | border-radius: 5px; 22 | overflow: auto; 23 | overflow-x: hidden; 24 | text-align: center; 25 | font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif; 26 | font-size: 14px; 27 | } 28 | .markdown-section p.tip, .markdown-section tr:nth-child(2n) { 29 | background:#fff !important; 30 | } 31 | .vuep-error, .vuep-preview { 32 | padding: 0; 33 | } 34 | #edit-panel button { 35 | background-color:#fff; 36 | } 37 | table { 38 | border-color:#fff; 39 | } 40 | .orgchart { 41 | display: inline-block; 42 | min-height: 100%; 43 | min-width: 100%; 44 | -webkit-touch-callout: none; 45 | -webkit-user-select: none; 46 | -khtml-user-select: none; 47 | -moz-user-select: none; 48 | -ms-user-select: none; 49 | user-select: none; 50 | background-size: 10px 10px; 51 | border: 1px dashed transparent; 52 | } 53 | 54 | .orgchart .hidden, .orgchart~.hidden { 55 | display: none; 56 | } 57 | 58 | .orgchart div, 59 | .orgchart div::before, 60 | .orgchart div::after { 61 | -webkit-box-sizing: border-box; 62 | -moz-box-sizing: border-box; 63 | box-sizing: border-box; 64 | } 65 | 66 | .orgchart.b2t { 67 | -ms-transform: rotate(180deg); 68 | -moz-transform: rotate(180deg); 69 | -webkit-transform: rotate(180deg); 70 | transform: rotate(180deg); 71 | } 72 | 73 | .orgchart.l2r { 74 | position: absolute; 75 | -ms-transform: rotate(-90deg) rotateY(180deg); 76 | -moz-transform: rotate(-90deg) rotateY(180deg); 77 | -webkit-transform: rotate(-90deg) rotateY(180deg); 78 | transform: rotate(-90deg) rotateY(180deg); 79 | -ms-transform-origin: left top; 80 | -moz-transform-origin: left top; 81 | -webkit-transform-origin: left top; 82 | transform-origin: left top; 83 | } 84 | 85 | .orgchart .verticalNodes ul { 86 | list-style: none; 87 | margin: 0; 88 | padding-left: 18px; 89 | text-align: left; 90 | } 91 | 92 | .orgchart .verticalNodes ul:first-child { 93 | margin-top: 3px; 94 | } 95 | 96 | .orgchart .verticalNodes>td::before { 97 | content: ''; 98 | border: 1px solid rgba(217, 83, 79, 0.8); 99 | } 100 | 101 | .orgchart .verticalNodes>td>ul>li:first-child::before { 102 | top: -4px; 103 | height: 30px; 104 | width: calc(50% - 2px); 105 | border-width: 2px 0 0 2px; 106 | } 107 | 108 | .orgchart .verticalNodes ul>li { 109 | position: relative; 110 | } 111 | 112 | .orgchart .verticalNodes ul>li::before, 113 | .orgchart .verticalNodes ul>li::after { 114 | content: ''; 115 | position: absolute; 116 | left: -6px; 117 | border-color: rgba(217, 83, 79, 0.8); 118 | border-style: solid; 119 | border-width: 0 0 2px 2px; 120 | -webkit-box-sizing: border-box; 121 | -moz-box-sizing: border-box; 122 | box-sizing: border-box; 123 | } 124 | 125 | .orgchart .verticalNodes ul>li::before { 126 | top: -4px; 127 | height: 30px; 128 | width: 11px; 129 | } 130 | 131 | .orgchart .verticalNodes ul>li::after { 132 | top: 1px; 133 | height: 100%; 134 | } 135 | 136 | .orgchart .verticalNodes ul>li:first-child::after { 137 | top: 24px; 138 | width: 11px; 139 | border-width: 2px 0 0 2px; 140 | } 141 | 142 | .orgchart .verticalNodes ul>li:last-child::after { 143 | border-width: 2px 0 0; 144 | } 145 | 146 | .orgchart.r2l { 147 | position: absolute; 148 | -ms-transform: rotate(90deg); 149 | -moz-transform: rotate(90deg); 150 | -webkit-transform: rotate(90deg); 151 | transform: rotate(90deg); 152 | -ms-transform-origin: left top; 153 | -moz-transform-origin: left top; 154 | -webkit-transform-origin: left top; 155 | transform-origin: left top; 156 | } 157 | 158 | .orgchart>.spinner { 159 | font-size: 100px; 160 | margin-top: 30px; 161 | color: rgba(68, 157, 68, 0.8); 162 | } 163 | 164 | .orgchart table { 165 | overflow: hidden; 166 | border-spacing: 0; 167 | border-collapse: separate; 168 | } 169 | 170 | .orgchart>table:first-child{ 171 | margin: 20px auto; 172 | } 173 | 174 | .orgchart td { 175 | text-align: center; 176 | vertical-align: top; 177 | padding: 0; 178 | border:#fff; 179 | } 180 | 181 | .orgchart tr.lines .topLine { 182 | border-top: 2px solid #616161; 183 | } 184 | 185 | .orgchart tr.lines .rightLine { 186 | border-right: 1px solid #616161; 187 | float: none; 188 | border-radius: 0; 189 | } 190 | 191 | .orgchart tr.lines .leftLine { 192 | border-left: 1px solid #616161; 193 | float: none; 194 | border-radius: 0; 195 | } 196 | 197 | .orgchart tr.lines .downLine { 198 | background-color: #616161; 199 | margin: 0 auto; 200 | height: 20px; 201 | width: 2px; 202 | float: none; 203 | } 204 | 205 | /* node styling */ 206 | .orgchart .node { 207 | display: inline-block; 208 | position: relative; 209 | margin: 0; 210 | padding: 3px; 211 | border: 2px transparent; 212 | text-align: center; 213 | width: 130px; 214 | } 215 | 216 | .orgchart.l2r .node, .orgchart.r2l .node { 217 | width: 50px; 218 | height: 130px; 219 | } 220 | 221 | .orgchart .node>.hazy { 222 | opacity: 0.2; 223 | } 224 | 225 | .orgchart .node>.spinner { 226 | position: absolute; 227 | top: calc(50% - 15px); 228 | left: calc(50% - 15px); 229 | vertical-align: middle; 230 | font-size: 30px; 231 | color: rgba(68, 157, 68, 0.8); 232 | } 233 | 234 | .orgchart .node:hover { 235 | background-color: rgba(238, 217, 54, 0.5); 236 | transition: .5s; 237 | cursor: default; 238 | z-index: 20; 239 | } 240 | 241 | .orgchart .node.focused { 242 | background-color: rgba(238, 217, 54, 0.5); 243 | } 244 | 245 | .orgchart .ghost-node { 246 | position: fixed; 247 | left: -10000px; 248 | top: -10000px; 249 | } 250 | 251 | .orgchart .ghost-node rect { 252 | fill: #ffffff; 253 | stroke: #bf0000; 254 | } 255 | 256 | .orgchart .node.allowedDrop { 257 | border-color: rgba(68, 157, 68, 0.9); 258 | } 259 | 260 | .orgchart .node .title { 261 | text-align: center; 262 | font-size: 12px; 263 | font-weight: 300; 264 | height: 20px; 265 | line-height: 20px; 266 | overflow: hidden; 267 | text-overflow: ellipsis; 268 | white-space: nowrap; 269 | background-color: #42b983; 270 | color: #fff; 271 | border-radius: 4px 4px 0 0; 272 | } 273 | 274 | .orgchart.b2t .node .title { 275 | -ms-transform: rotate(-180deg); 276 | -moz-transform: rotate(-180deg); 277 | -webkit-transform: rotate(-180deg); 278 | transform: rotate(-180deg); 279 | -ms-transform-origin: center bottom; 280 | -moz-transform-origin: center bottom; 281 | -webkit-transform-origin: center bottom; 282 | transform-origin: center bottom; 283 | } 284 | 285 | .orgchart.l2r .node .title { 286 | -ms-transform: rotate(-90deg) translate(-40px, -40px) rotateY(180deg); 287 | -moz-transform: rotate(-90deg) translate(-40px, -40px) rotateY(180deg); 288 | -webkit-transform: rotate(-90deg) translate(-40px, -40px) rotateY(180deg); 289 | transform: rotate(-90deg) translate(-40px, -40px) rotateY(180deg); 290 | -ms-transform-origin: bottom center; 291 | -moz-transform-origin: bottom center; 292 | -webkit-transform-origin: bottom center; 293 | transform-origin: bottom center; 294 | width: 120px; 295 | } 296 | 297 | .orgchart.r2l .node .title { 298 | -ms-transform: rotate(-90deg) translate(-40px, -40px); 299 | -moz-transform: rotate(-90deg) translate(-40px, -40px); 300 | -webkit-transform: rotate(-90deg) translate(-40px, -40px); 301 | transform: rotate(-90deg) translate(-40px, -40px); 302 | -ms-transform-origin: bottom center; 303 | -moz-transform-origin: bottom center; 304 | -webkit-transform-origin: bottom center; 305 | transform-origin: bottom center; 306 | width: 120px; 307 | } 308 | 309 | .orgchart .node .title .symbol { 310 | float: left; 311 | margin-top: 4px; 312 | margin-left: 2px; 313 | } 314 | 315 | .orgchart .node .content { 316 | width: 100%; 317 | height: 20px; 318 | font-size: 11px; 319 | line-height: 18px; 320 | border: 1px solid #42b983; 321 | border-radius: 0 0 4px 4px; 322 | text-align: center; 323 | background-color: #fff; 324 | color: #333; 325 | overflow: hidden; 326 | text-overflow: ellipsis; 327 | white-space: nowrap; 328 | } 329 | 330 | .orgchart.b2t .node .content { 331 | -ms-transform: rotate(180deg); 332 | -moz-transform: rotate(180deg); 333 | -webkit-transform: rotate(180deg); 334 | transform: rotate(180deg); 335 | -ms-transform-origin: center top; 336 | -moz-transform-origin: center top; 337 | -webkit-transform-origin: center top; 338 | transform-origin: center top; 339 | } 340 | 341 | .orgchart.l2r .node .content { 342 | -ms-transform: rotate(-90deg) translate(-40px, -40px) rotateY(180deg); 343 | -moz-transform: rotate(-90deg) translate(-40px, -40px) rotateY(180deg); 344 | -webkit-transform: rotate(-90deg) translate(-40px, -40px) rotateY(180deg); 345 | transform: rotate(-90deg) translate(-40px, -40px) rotateY(180deg); 346 | -ms-transform-origin: top center; 347 | -moz-transform-origin: top center; 348 | -webkit-transform-origin: top center; 349 | transform-origin: top center; 350 | width: 120px; 351 | } 352 | 353 | .orgchart.r2l .node .content { 354 | -ms-transform: rotate(-90deg) translate(-40px, -40px); 355 | -moz-transform: rotate(-90deg) translate(-40px, -40px); 356 | -webkit-transform: rotate(-90deg) translate(-40px, -40px); 357 | transform: rotate(-90deg) translate(-40px, -40px); 358 | -ms-transform-origin: top center; 359 | -moz-transform-origin: top center; 360 | -webkit-transform-origin: top center; 361 | transform-origin: top center; 362 | width: 120px; 363 | } 364 | 365 | .orgchart .node .edge { 366 | font-size: 15px; 367 | position: absolute; 368 | color: rgba(68, 157, 68, 0.5); 369 | cursor: default; 370 | transition: .2s; 371 | -webkit-transition: .2s; 372 | } 373 | 374 | .orgchart.noncollapsable .node .edge { 375 | display: none; 376 | } 377 | 378 | .orgchart .edge:hover { 379 | color: #449d44; 380 | cursor: pointer; 381 | } 382 | 383 | .orgchart .node .verticalEdge { 384 | width: calc(100% - 10px); 385 | width: -webkit-calc(100% - 10px); 386 | width: -moz-calc(100% - 10px); 387 | left: 5px; 388 | } 389 | 390 | .orgchart .node .topEdge { 391 | top: -4px; 392 | } 393 | 394 | .orgchart .node .bottomEdge { 395 | bottom: -4px; 396 | } 397 | 398 | .orgchart .node .horizontalEdge { 399 | width: 15px; 400 | height: calc(100% - 10px); 401 | height: -webkit-calc(100% - 10px); 402 | height: -moz-calc(100% - 10px); 403 | top: 5px; 404 | } 405 | 406 | .orgchart .node .rightEdge { 407 | right: -4px; 408 | } 409 | 410 | .orgchart .node .leftEdge { 411 | left: -4px; 412 | } 413 | 414 | .orgchart .node .horizontalEdge::before { 415 | position: absolute; 416 | top: calc(50% - 7px); 417 | top: -webkit-calc(50% - 7px); 418 | top: -moz-calc(50% - 7px); 419 | } 420 | 421 | .orgchart .node .rightEdge::before { 422 | right: 3px; 423 | } 424 | 425 | .orgchart .node .leftEdge::before { 426 | left: 3px; 427 | } 428 | 429 | .orgchart .node .toggleBtn { 430 | position: absolute; 431 | left: 5px; 432 | bottom: -2px; 433 | color: rgba(68, 157, 68, 0.6); 434 | } 435 | 436 | .orgchart .node .toggleBtn:hover { 437 | color: rgba(68, 157, 68, 0.8); 438 | } 439 | 440 | .oc-export-btn { 441 | display: inline-block; 442 | position: absolute; 443 | right: 5px; 444 | bottom: 5px; 445 | padding: 6px 12px; 446 | margin-bottom: 0; 447 | font-size: 14px; 448 | font-weight: 400; 449 | line-height: 1.42857143; 450 | text-align: center; 451 | white-space: nowrap; 452 | vertical-align: middle; 453 | -ms-touch-action: manipulation; 454 | touch-action: manipulation; 455 | cursor: pointer; 456 | -webkit-user-select: none; 457 | -moz-user-select: none; 458 | -ms-user-select: none; 459 | user-select: none; 460 | color: #fff; 461 | background-color: #409eff; 462 | border: 1px solid transparent; 463 | border-color: #409eff; 464 | border-radius: 4px; 465 | } 466 | 467 | .oc-export-btn:hover,.oc-export-btn:focus,.oc-export-btn:active { 468 | background-color: #409eff; 469 | border-color: #409eff; 470 | } 471 | 472 | .orgchart~.mask { 473 | position: absolute; 474 | top: 0; 475 | right: 0; 476 | bottom: 0; 477 | left: 0; 478 | z-index: 999; 479 | text-align: center; 480 | background-color: rgba(0,0,0,0.3); 481 | } 482 | 483 | .orgchart~.mask .spinner { 484 | position: absolute; 485 | top: calc(50% - 54px); 486 | left: calc(50% - 54px); 487 | color: rgba(255,255,255,0.8); 488 | font-size: 108px; 489 | } 490 | 491 | .orgchart .node { 492 | -webkit-transition: all 0.3s; 493 | transition: all 0.3s; 494 | top: 0; 495 | left: 0; 496 | } 497 | 498 | .orgchart .slide-down { 499 | opacity: 0; 500 | top: 40px; 501 | } 502 | 503 | .orgchart.l2r .node.slide-down, .orgchart.r2l .node.slide-down { 504 | top: 130px; 505 | } 506 | 507 | .orgchart .slide-up { 508 | opacity: 0; 509 | top: -40px; 510 | } 511 | 512 | .orgchart.l2r .node.slide-up, .orgchart.r2l .node.slide-up { 513 | top: -130px; 514 | } 515 | 516 | .orgchart .slide-right { 517 | opacity: 0; 518 | left: 130px; 519 | } 520 | 521 | .orgchart.l2r .node.slide-right, .orgchart.r2l .node.slide-right { 522 | left: 40px; 523 | } 524 | 525 | .orgchart .slide-left { 526 | opacity: 0; 527 | left: -130px; 528 | } 529 | 530 | .orgchart.l2r .node.slide-left, .orgchart.r2l .node.slide-left { 531 | left: -40px; 532 | } 533 | #edit-panel { 534 | position: relative; 535 | left: 10px; 536 | width: calc(100% - 40px); 537 | border-radius: 4px; 538 | float: left; 539 | margin-top: 20px; 540 | padding: 10px 5px 10px 10px; 541 | font-size: 14px; 542 | line-height: 1.5; 543 | border-radius: 2px; 544 | color: rgba(0, 0, 0, 0.65); 545 | background-color: #fff; 546 | } 547 | 548 | #edit-panel .btn-inputs { 549 | font-size: 24px; 550 | } 551 | 552 | #edit-panel label { 553 | font-weight: bold; 554 | } 555 | 556 | #edit-panel .new-node { 557 | height: 24px; 558 | -webkit-appearance: none; 559 | background-color:#fff; 560 | background-image: none; 561 | border-radius: 4px; 562 | line-height: 1; 563 | border: 1px solid #d8dce5; 564 | box-sizing: border-box; 565 | color: #5a5e66; 566 | display: inline-block; 567 | transition: border-color .2s cubic-bezier(.645,.045,.355,1); 568 | } 569 | 570 | #edit-panel .new-node:focus { 571 | border-color: #409eff; 572 | outline: none; 573 | } 574 | 575 | #edit-panel .new-node:hover { 576 | border-color: #b4bccc; 577 | } 578 | 579 | #edit-panel.edit-parent-node .selected-node-group{ 580 | display: none; 581 | } 582 | 583 | #chart-state-panel, #selected-node, #btn-remove-input { 584 | margin-right: 20px; 585 | } 586 | 587 | #edit-panel button { 588 | /* color: #333; 589 | background-color: #fff; */ 590 | display: inline-block; 591 | padding: 6px 12px; 592 | margin-bottom: 0; 593 | line-height: 1.42857143; 594 | text-align: center; 595 | white-space: nowrap; 596 | border-radius: 4px; 597 | vertical-align: middle; 598 | -ms-touch-action: manipulation; 599 | touch-action: manipulation; 600 | cursor: pointer; 601 | -webkit-user-select: none; 602 | -moz-user-select: none; 603 | -ms-user-select: none; 604 | user-select: none; 605 | background-image: none; 606 | } 607 | 608 | #edit-panel.edit-parent-node button:not(#btn-add-nodes) { 609 | display: none; 610 | } 611 | 612 | #edit-panel button:hover,.edit-panel button:focus,.edit-panel button:active { 613 | border-color: #409eff; 614 | box-shadow: 0 0 10px #409eff; 615 | } 616 | 617 | #new-nodelist { 618 | display: inline-block; 619 | list-style:none; 620 | margin-top: -2px; 621 | padding: 0; 622 | vertical-align: text-top; 623 | } 624 | 625 | #new-nodelist>* { 626 | padding-bottom: 4px; 627 | } 628 | 629 | .btn-inputs { 630 | vertical-align: sub; 631 | } 632 | 633 | 634 | .btn-inputs:hover { 635 | text-shadow: 0 0 4px #fff; 636 | } 637 | 638 | .radio-panel input[type='radio'] { 639 | border: 1px solid #d8dce5; 640 | border-radius: 100%; 641 | cursor: pointer; 642 | box-sizing: border-box; 643 | display: inline-block; 644 | height: 14px; 645 | width: 14px; 646 | vertical-align: top; 647 | } 648 | 649 | #edit-panel.view-state .radio-panel input[type='radio']+label { 650 | font-size: 14px; 651 | font-weight: 500; 652 | /* color: #5a5e66; */ 653 | line-height: 1; 654 | } 655 | 656 | #btn-add-nodes { 657 | margin-left: 20px; 658 | } 659 | -------------------------------------------------------------------------------- /docs/zh-cn/README.md: -------------------------------------------------------------------------------- 1 | ## vue-orgchart 2 | 3 | > A vue wrapper for OrgChart.js. 4 | 5 | ### 前言 6 | - 首先感谢dabeng的Orgchart.js -- [OrgChart.js](https://github.com/dabeng/OrgChart.js) 7 | - 如果你想用OrgChart.js的Vue封装,可以直接用 [我的项目](https://github.com/spiritree/vue-orgchart) 8 | 9 | ### 功能 10 | - JSON格式导入导出树形关系图 11 | - 支持树形关系图导出图片 12 | - 可拖拉树形关系图 13 | - 可编辑树形关系图 14 | 15 | ... 16 | -------------------------------------------------------------------------------- /docs/zh-cn/_navbar.md: -------------------------------------------------------------------------------- 1 | - Translations 2 | - [:cn: 中文](/zh-cn/) 3 | - [:uk: English](/) 4 | -------------------------------------------------------------------------------- /docs/zh-cn/_sidebar.md: -------------------------------------------------------------------------------- 1 | - 入门 2 | - [快速开始](zh-cn/quickstart) 3 | - [图表属性](zh-cn/props) 4 | - 图表 5 | - [基础组织树图](zh-cn/basic) 6 | - [缩放组织树图](zh-cn/panzoom) 7 | - [可拖拉组织树图](zh-cn/drag) 8 | - [可导出组织树形图图片](zh-cn/exportpic) 9 | - [可编辑组织树图](zh-cn/edit) 10 | -------------------------------------------------------------------------------- /docs/zh-cn/basic.md: -------------------------------------------------------------------------------- 1 | ## 基础组织树图 2 | 3 | ```html 4 | /*vue*/ 5 | 8 | 9 | 29 | ``` 30 | -------------------------------------------------------------------------------- /docs/zh-cn/drag.md: -------------------------------------------------------------------------------- 1 | ## 可拖拉组织树图 2 | 3 | ```html 4 | /*vue*/ 5 | 8 | 9 | 29 | ``` 30 | 31 | -------------------------------------------------------------------------------- /docs/zh-cn/edit.md: -------------------------------------------------------------------------------- 1 | ## 可编辑组织树图 2 | 3 | ```html 4 | /*vue*/ 5 | 34 | 35 | 170 | ``` 171 | ```json 172 | ``` 173 | -------------------------------------------------------------------------------- /docs/zh-cn/exportpic.md: -------------------------------------------------------------------------------- 1 | ## 可导出组织树图图片 2 | 3 | ```html 4 | /*vue*/ 5 | 8 | 9 | 30 | ``` 31 | -------------------------------------------------------------------------------- /docs/zh-cn/panzoom.md: -------------------------------------------------------------------------------- 1 | ## 缩放组织树图 2 | 3 | 4 | ```html 5 | /*vue*/ 6 | 9 | 10 | 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/zh-cn/props.md: -------------------------------------------------------------------------------- 1 | ### 图表属性 2 | 3 | ### 例子 4 | 5 | `` 6 | 7 | `` 8 | 9 | !> 在非webpack等编译打包环境中,注意将camelCase (驼峰式命名) 的 prop 需要转换为相对应的 kebab-case (短横线分隔式命名),如`chartName`=>`chart-name` 10 | 11 | ### 属性 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 |
配置项类型需要默认描述
dataObject,Stringyes图表数据
panBooleannofalse鼠标拖放来平移该组织图
zoomBooleannofalse通过鼠标滚轮放大/缩小组织图
directionStringno"t2b"t2b(表示 "top to bottom", it's default value), b2t(表示 "bottom to top"), l2r(表示 "left to right"), r2l(表示 "right to left").
verticalDepthIntergerno垂直深度
toggleSiblingsRespBooleannofalse一旦启用此选项,用户可以显示/隐藏左/右兄弟节点分别点击左/右箭头
toggleCollapseBooleannotrue你可以设值为false来关闭节点的箭头图标
ajaxURLStringnoAjax获取JSON数据
depthPositive Intergerno999最大级别
nodeTitleStringno"name"树形组织图中的元素名称
parentNodeSymbolStringno""父元素节点的图标class
nodeContentStringno树形组织图中二级元素名称
nodeIdStringno"id"节点的ID值
createNodeFunctionno一个回调函数来定制创造节点的规则
exportButtonBooleannofalse导出图片
exportButtonNamestringno导出图片按钮标题
exportFilenameStringno"Orgchart"导出图片名称
chartClassStringno""图标的class
draggableBooleannofalse可拖拉选项
dropCriteriaFunctionno可以通过函数来限制拖拽节点和放置区之间的关系。另外,这个函数接受三个参数(draggedNode,dragZone,dropZone),只返回boolean值。
80 | -------------------------------------------------------------------------------- /docs/zh-cn/quickstart.md: -------------------------------------------------------------------------------- 1 | ## 快速开始 2 | 3 | ### 安装 4 | ```shell 5 | npm install vue-orgchart -S 6 | ``` 7 | 8 | ### 在项目中导入 9 | 10 | > `main.js` 11 | 12 | ```js 13 | import 'vue-orgchart/dist/style.min.css' 14 | ``` 15 | 16 | > In `*.vue` 17 | 18 | ```js 19 | 20 | import { VoBasic } from 'vue-orgchart' 21 | export default { 22 | components: { VoEdit }, 23 | created () { 24 | this.chartData = { 25 | name: 'JavaScript', 26 | children: [ 27 | { name: 'Angular' }, 28 | { 29 | name: 'React', 30 | children: [{ name: 'Preact' }] 31 | }, 32 | { 33 | name: 'Vue', 34 | children: [{ name: 'Moon' }] 35 | } 36 | ] 37 | } 38 | } 39 | } 40 | ``` 41 | 42 | ### CDN 43 | ```html 44 | 45 | 46 | ``` 47 | -------------------------------------------------------------------------------- /examples/Ajax.vue: -------------------------------------------------------------------------------- 1 | 41 | 42 | 189 | 239 | 240 | -------------------------------------------------------------------------------- /examples/App.vue: -------------------------------------------------------------------------------- 1 | 42 | 43 | 170 | 220 | -------------------------------------------------------------------------------- /examples/data/basic.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: '基础树形关系图(Basic orgchart)', 3 | type: 'basic', 4 | data: [ 5 | { 6 | name: 'Basic orgchart', 7 | data: { 8 | name: 'JavaScript', 9 | children: [ 10 | { name: 'Angular' }, 11 | { 12 | name: 'React', 13 | children: [{ name: 'Preact' }] 14 | }, 15 | { 16 | name: 'Vue', 17 | children: [{ name: 'Moon' }] 18 | } 19 | ] 20 | } 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /examples/data/edit.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: '可编辑树形关系图(Editable orgchart)', 3 | type: 'edit', 4 | data: [ 5 | { 6 | name: 'Editable orgchart', 7 | data: { 8 | name: 'JavaScript', 9 | children: [ 10 | { name: 'Angular' }, 11 | { 12 | name: 'React', 13 | children: [{ name: 'Preact' }] 14 | }, 15 | { 16 | name: 'Vue', 17 | children: [{ name: 'Moon' }] 18 | } 19 | ] 20 | } 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /examples/data/index.js: -------------------------------------------------------------------------------- 1 | import basic from './basic' 2 | import edit from './edit' 3 | 4 | export default { 5 | basic, 6 | edit 7 | } 8 | -------------------------------------------------------------------------------- /examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | vue-orgchart 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import store from './store' 4 | import '../dist/style.min.css' 5 | 6 | new Vue({ 7 | el: '#app', 8 | store, 9 | render: h => h(App) 10 | }) 11 | -------------------------------------------------------------------------------- /examples/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import { getData } from './service' 4 | 5 | Vue.use(Vuex) 6 | 7 | const state = { 8 | treeData: {} 9 | } 10 | 11 | const actions = { 12 | async getAreas ({ commit }) { 13 | const res = await getData() 14 | commit('getAreas', res) 15 | }, 16 | } 17 | 18 | const mutations = { 19 | 'getAreas' (state, treeData) { 20 | state.treeData = treeData 21 | }, 22 | } 23 | 24 | export default new Vuex.Store({ 25 | state, 26 | // getters, 27 | actions, 28 | mutations 29 | }) 30 | -------------------------------------------------------------------------------- /examples/store/service.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | 3 | export const getData = () => { 4 | return axios 5 | .get("https://easy-mock.com/mock/5a2f9181c430642f15c5fef8/chart/orgtree") 6 | .then((res) => res.data) 7 | } 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-orgchart", 3 | "description": "A vue wrapper for OrgChart.js", 4 | "version": "1.1.7", 5 | "author": { 6 | "name": "spiritree", 7 | "email": "spiritreess@gmail.com", 8 | "url": "https://github.com/spiritree" 9 | }, 10 | "files": [ 11 | "dist", 12 | "src", 13 | "docs" 14 | ], 15 | "main": "dist/vue-orgchart.min.js", 16 | "license": "MIT", 17 | "homepage": "https://spiritree.github.io/vue-orgchart", 18 | "bugs": { 19 | "url": "https://github.com/spiritree/vue-orgchart/issues" 20 | }, 21 | "scripts": { 22 | "dev": "webpack-dev-server --config ./build/webpack.config.js", 23 | "build": "webpack --progress --hide-modules --config ./build/webpack.config.build.js && cross-env NODE_ENV=production webpack --progress --hide-modules --config ./build/webpack.config.build.min.js", 24 | "rollup": "node build/rollup.config.js", 25 | "docs": "docsify serve docs --port 3002", 26 | "test": "karma start ./test/karma.conf.js" 27 | }, 28 | "repository": { 29 | "type": "git", 30 | "url": "git+https://github.com/spiritree/vue-orgchart.git" 31 | }, 32 | "keywords": [ 33 | "vue", 34 | "orgchart" 35 | ], 36 | "dependencies": { 37 | "axios": "^0.17.1", 38 | "orgchart.js": "0.0.4", 39 | "vue": "^2.5.13", 40 | "vue-loader": "^14.1.1", 41 | "vue-style-loader": "^3.1.2", 42 | "vue-template-compiler": "^2.5.13", 43 | "vuex": "^3.0.1" 44 | }, 45 | "browserslist": [ 46 | "> 1%", 47 | "last 2 versions", 48 | "not ie <= 8" 49 | ], 50 | "devDependencies": { 51 | "autoprefixer": "^7.1.6", 52 | "babel-core": "^6.26.0", 53 | "babel-eslint": "^8.0.2", 54 | "babel-loader": "^7.1.2", 55 | "babel-plugin-external-helpers": "^6.22.0", 56 | "babel-plugin-transform-object-assign": "^6.22.0", 57 | "babel-plugin-transform-runtime": "^6.23.0", 58 | "babel-preset-env": "^1.6.0", 59 | "babel-preset-es2015": "^6.24.1", 60 | "babel-preset-latest": "^6.24.1", 61 | "babel-preset-stage-2": "^6.24.1", 62 | "cross-env": "^5.0.5", 63 | "css-loader": "^0.28.7", 64 | "cssnano": "^3.10.0", 65 | "docsify-cli": "^4.2.0", 66 | "es6-promise": "^4.1.1", 67 | "eslint": "^4.12.0", 68 | "eslint-config-standard": "^10.2.1", 69 | "eslint-friendly-formatter": "^3.0.0", 70 | "eslint-loader": "^1.9.0", 71 | "eslint-plugin-html": "^4.0.1", 72 | "eslint-plugin-import": "^2.8.0", 73 | "eslint-plugin-node": "^5.2.1", 74 | "eslint-plugin-promise": "^3.6.0", 75 | "eslint-plugin-standard": "^3.0.1", 76 | "extract-text-webpack-plugin": "^3.0.2", 77 | "file-loader": "^1.1.4", 78 | "html-webpack-plugin": "^2.30.1", 79 | "jasmine-core": "^2.8.0", 80 | "json-loader": "^0.5.7", 81 | "karma": "^1.7.0", 82 | "karma-babel-preprocessor": "^6.0.1", 83 | "karma-chrome-launcher": "^2.1.1", 84 | "karma-commonjs": "^1.0.0", 85 | "karma-jasmine": "^1.1.0", 86 | "karma-phantomjs-launcher": "^1.0.4", 87 | "karma-spec-reporter": "^0.0.31", 88 | "karma-webpack": "^2.0.3", 89 | "lodash-es": "^4.17.4", 90 | "opn": "^5.1.0", 91 | "rollup": "^0.52.0", 92 | "rollup-plugin-alias": "^1.4.0", 93 | "rollup-plugin-babel": "^3.0.2", 94 | "rollup-plugin-commonjs": "^8.2.6", 95 | "rollup-plugin-node-resolve": "^3.0.0", 96 | "rollup-plugin-uglify": "^2.0.1", 97 | "rollup-plugin-vue": "^2.5.2", 98 | "webpack": "^3.8.0", 99 | "webpack-dev-server": "^2.9.1" 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/components/VoBasic.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 66 | 67 | 676 | -------------------------------------------------------------------------------- /src/components/VoEdit.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 75 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import VoBasic from '../src/components/VoBasic.vue' 2 | import VoEdit from '../src/components/VoEdit.vue' 3 | 4 | export { 5 | VoBasic, 6 | VoEdit 7 | } 8 | 9 | if (typeof window !== 'undefined' && window.Vue) { 10 | window.Vue.component('vo-basic', VoBasic) 11 | window.Vue.component('vo-edit', VoEdit) 12 | } 13 | -------------------------------------------------------------------------------- /src/lib/lodash.js: -------------------------------------------------------------------------------- 1 | import merge from 'lodash-es/merge' 2 | 3 | export const mergeOptions = (obj, src) => { 4 | return merge(obj, src) 5 | } 6 | -------------------------------------------------------------------------------- /src/lib/utils.js: -------------------------------------------------------------------------------- 1 | export const closest = (el, fn) => { 2 | return el && ((fn(el) && el !== document.querySelector('.orgchart')) ? el : closest(el.parentNode, fn)) 3 | } 4 | 5 | export const addClass = (elements, classNames) => { 6 | elements.forEach((el) => { 7 | if (classNames.includes(' ')) { 8 | classNames.split(' ').forEach((className) => el.classList.add(className)) 9 | } else { 10 | el.classList.add(classNames) 11 | } 12 | }) 13 | } 14 | 15 | export const removeClass = (elements, classNames) => { 16 | elements.forEach((el) => { 17 | if (classNames.includes(' ')) { 18 | classNames.split(' ').forEach((className) => el.classList.remove(className)) 19 | } else { 20 | el.classList.remove(classNames) 21 | } 22 | }) 23 | } 24 | 25 | export const bindEventHandler = (selector, type, fn, parentSelector) => { 26 | if (parentSelector) { 27 | document.querySelector(parentSelector).addEventListener(type, function (event) { 28 | if ((event.target.classList && event.target.classList.contains(selector.slice(1))) || 29 | closest(event.target, el => el.classList && el.classList.contains(selector.slice(1)))) { 30 | fn(event) 31 | } 32 | }) 33 | } else { 34 | document.querySelectorAll(selector).forEach(element => { 35 | element.addEventListener(type, fn) 36 | }) 37 | } 38 | } 39 | 40 | export const clickNode = (event) => { 41 | let sNode = closest(event.target, el => el.classList && el.classList.contains('node')) 42 | let sNodeInput = document.getElementById('selected-node') 43 | 44 | sNodeInput.value = sNode.querySelector('.title').textContent 45 | sNodeInput.dataset.node = sNode.id 46 | } 47 | 48 | export const clickChart = (event) => { 49 | if (!closest(event.target, el => el.classList && el.classList.contains('node'))) { 50 | document.getElementById('selected-node').textContent = '' 51 | } 52 | } 53 | 54 | export const addInputs = () => { 55 | let newNode = document.createElement('li') 56 | newNode.innerHTML = `` 57 | document.getElementById('new-nodelist').appendChild(newNode) 58 | } 59 | 60 | export const removeInputs = () => { 61 | let inputs = Array.from(document.getElementById('new-nodelist').children) 62 | if (inputs.length > 1) { 63 | inputs.pop().remove() 64 | } 65 | } 66 | 67 | export const addNodes = (orgchart) => { 68 | let chartContainer = document.getElementById('chart-container') 69 | let nodeVals = [] 70 | 71 | Array.from(document.getElementById('new-nodelist').querySelectorAll('.new-node')) 72 | .forEach(item => { 73 | let validVal = item.value.trim() 74 | 75 | if (validVal) { 76 | nodeVals.push(validVal) 77 | } 78 | }) 79 | let selectedNode = document.getElementById(document.getElementById('selected-node').dataset.node) 80 | 81 | if (!nodeVals.length) { 82 | alert('Please input value for new node') 83 | return 84 | } 85 | let nodeType = document.querySelector('input[name="node-type"]:checked') 86 | 87 | if (!nodeType) { 88 | alert('Please select a node type') 89 | return 90 | } 91 | if (nodeType.value !== 'parent' && !document.querySelector('.orgchart')) { 92 | alert('Please creat the root node firstly when you want to build up the orgchart from the scratch') 93 | return 94 | } 95 | if (nodeType.value !== 'parent' && !selectedNode) { 96 | alert('Please select one node in orgchart') 97 | return 98 | } 99 | /* eslint-disable */ 100 | if (nodeType.value === 'parent') { 101 | if (!chartContainer.children.length) {// if the original chart has been deleted 102 | orgchart = new OrgChart({ 103 | 'chartContainer': '#chart-container', 104 | 'data': { 'name': nodeVals[0] }, 105 | 'parentNodeSymbol': 'fa-th-large', 106 | 'createNode': function (node, data) { 107 | node.id = getId() 108 | } 109 | }) 110 | orgchart.chart.classList.add('view-state') 111 | } else { 112 | orgchart.addParent(chartContainer.querySelector('.node'), { 'name': nodeVals[0], 'Id': getId() }) 113 | } 114 | } else if (nodeType.value === 'siblings') { 115 | orgchart.addSiblings(selectedNode, { 116 | 'siblings': nodeVals.map(item => { 117 | return { 'name': item, 'relationship': '110', 'Id': getId() } 118 | }) 119 | }) 120 | } else { 121 | let hasChild = selectedNode.parentNode.colSpan > 1 122 | 123 | if (!hasChild) { 124 | let rel = nodeVals.length > 1 ? '110' : '100' 125 | 126 | orgchart.addChildren(selectedNode, { 127 | 'children': nodeVals.map(item => { 128 | return { 'name': item, 'relationship': rel, 'Id': getId() } 129 | }) 130 | }) 131 | } else { 132 | orgchart.addSiblings(closest(selectedNode, el => el.nodeName === 'TABLE').querySelector('.nodes').querySelector('.node'), 133 | { 'siblings': nodeVals.map(function (item) { return { 'name': item, 'relationship': '110', 'Id': getId() } }) 134 | }) 135 | } 136 | } 137 | } 138 | 139 | export const deleteNodes = (orgchart) => { 140 | let sNodeInput = document.getElementById('selected-node') 141 | let sNode = document.getElementById(sNodeInput.dataset.node) 142 | 143 | if (!sNode) { 144 | alert('Please select one node in orgchart') 145 | return 146 | } else if (sNode === document.querySelector('.orgchart').querySelector('.node')) { 147 | if (!window.confirm('Are you sure you want to delete the whole chart?')) { 148 | return 149 | } 150 | } 151 | orgchart.removeNodes(sNode) 152 | sNodeInput.value = '' 153 | sNodeInput.dataset.node = '' 154 | } 155 | 156 | export const resetPanel = () => { 157 | let fNode = document.querySelector('.orgchart').querySelector('.focused') 158 | 159 | if (fNode) { 160 | fNode.classList.remove('focused') 161 | } 162 | document.getElementById('selected-node').value = '' 163 | document.getElementById('new-nodelist').querySelector('input').value = '' 164 | Array.from(document.getElementById('new-nodelist').children).slice(1).forEach(item => item.remove()) 165 | document.getElementById('node-type-panel').querySelectorAll('input').forEach(item => { 166 | item.checked = false 167 | }) 168 | } 169 | 170 | export const getId = () => { 171 | return (new Date().getTime()) * 1000 + Math.floor(Math.random() * 1001) 172 | } 173 | 174 | export const exportJSON = (orgchart) => { 175 | let datasourceJSON = {} 176 | let ChartJSON = orgchart.getChartJSON() 177 | datasourceJSON = JSON.stringify(ChartJSON, null, 2) 178 | if(document.getElementsByTagName('code')[1]) { 179 | let code = document.getElementsByTagName('code')[1] 180 | code.innerHTML = datasourceJSON 181 | } 182 | return datasourceJSON 183 | } 184 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable*/ 2 | import Vue from 'vue' 3 | import chartData from '../examples/data/index.js' 4 | 5 | window.Promise = require('es6-promise').Promise 6 | import { 7 | VoBasic, 8 | VoEdit 9 | } from '../dist/vue-orgchart.esm.js' 10 | 11 | const comps = { 12 | basic: VoBasic, 13 | edit: VoEdit, 14 | } 15 | 16 | let box 17 | let vm = {} 18 | createBox() 19 | 20 | afterEach(() => { 21 | if (vm.$el) document.body.removeChild(vm.$el) 22 | createBox() 23 | }) 24 | 25 | Object.keys(comps).forEach(type => { 26 | chartData[type].data.forEach(item => { 27 | describe(type + ': ', () => { 28 | testMount(type, comps[type], item) 29 | }) 30 | }) 31 | }) 32 | 33 | function testMount (type, comp, item) { 34 | it(item.name, () => { 35 | const Ctor = Vue.extend(comp) 36 | const vm = new Ctor({ 37 | propsData: { data: item.data } 38 | }).$mount(box) 39 | expect(vm.$el.classList.contains('vo-' + type)).toEqual(true) 40 | }) 41 | } 42 | 43 | function createBox () { 44 | box = document.createElement('div') 45 | box.id = 'app' 46 | document.body.appendChild(box) 47 | } 48 | -------------------------------------------------------------------------------- /test/karma.conf.js: -------------------------------------------------------------------------------- 1 | module.exports = function (config) { 2 | config.set({ 3 | frameworks: ['jasmine'], 4 | files: [ 5 | './index.js' 6 | ], 7 | browsers: ['PhantomJS'], 8 | reporters: ['spec'], 9 | preprocessors: { 10 | './index.js': ['webpack'] 11 | }, 12 | webpack: { 13 | devtool: 'inline-source-map', 14 | module: { 15 | loaders: [ 16 | { 17 | test: /\.(js)$/, 18 | loader: 'babel-loader' 19 | } 20 | ] 21 | }, 22 | resolve: { 23 | extensions: ['.js', '.vue'] 24 | } 25 | }, 26 | singleRun: true 27 | }) 28 | } 29 | -------------------------------------------------------------------------------- /test/load/webpack/basic/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 27 | -------------------------------------------------------------------------------- /test/load/webpack/basic/index.js: -------------------------------------------------------------------------------- 1 | 2 | import Vue from 'vue' 3 | import App from './App.vue' 4 | 5 | Vue.config.productionTip = false 6 | 7 | /* eslint-disable no-new */ 8 | new Vue({ 9 | el: '#app', 10 | render: h => h(App) 11 | }) 12 | -------------------------------------------------------------------------------- /test/load/webpack/basic/webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack') 2 | const path = require('path') 3 | const HtmlWebpackPlugin = require('html-webpack-plugin') 4 | 5 | function resolve (dir) { 6 | return path.join(__dirname, '..', dir) 7 | } 8 | 9 | module.exports = { 10 | entry: { 11 | app: './index.js' 12 | }, 13 | output: { 14 | path: path.resolve(__dirname, '../dist'), 15 | filename: 'index.js', 16 | publicPath: '/' 17 | }, 18 | resolve: { 19 | alias: { 20 | 'vue$': 'vue/dist/vue.esm.js' 21 | }, 22 | extensions: ['*', '.js', '.vue', '.json'] 23 | }, 24 | devServer: { 25 | port: '8180', 26 | hot: true, 27 | stats: 'errors-only' 28 | }, 29 | performance: { 30 | hints: false 31 | }, 32 | module: { 33 | rules: [ 34 | { 35 | test: /\.vue$/, 36 | loader: 'vue-loader' 37 | }, 38 | { 39 | test: /\.js$/, 40 | loader: 'babel-loader' 41 | }, 42 | { 43 | test: /\.css$/, 44 | use: ['style-loader', 'css-loader'] 45 | } 46 | ] 47 | }, 48 | plugins: [ 49 | new webpack.DefinePlugin({ 50 | 'process.env': { 51 | NODE_ENV: '"development"' 52 | } 53 | }), 54 | new webpack.HotModuleReplacementPlugin(), 55 | new HtmlWebpackPlugin({ 56 | filename: 'index.html', 57 | template: '../index.html', 58 | inject: true 59 | }) 60 | ] 61 | } 62 | -------------------------------------------------------------------------------- /test/load/webpack/edit/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 27 | -------------------------------------------------------------------------------- /test/load/webpack/edit/index.js: -------------------------------------------------------------------------------- 1 | 2 | import Vue from 'vue' 3 | import App from './App.vue' 4 | 5 | Vue.config.productionTip = false 6 | 7 | /* eslint-disable no-new */ 8 | new Vue({ 9 | el: '#app', 10 | render: h => h(App) 11 | }) 12 | -------------------------------------------------------------------------------- /test/load/webpack/edit/webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack') 2 | const path = require('path') 3 | const HtmlWebpackPlugin = require('html-webpack-plugin') 4 | 5 | function resolve (dir) { 6 | return path.join(__dirname, '..', dir) 7 | } 8 | 9 | module.exports = { 10 | entry: { 11 | app: './index.js' 12 | }, 13 | output: { 14 | path: path.resolve(__dirname, '../dist'), 15 | filename: 'index.js', 16 | publicPath: '/' 17 | }, 18 | resolve: { 19 | alias: { 20 | 'vue$': 'vue/dist/vue.esm.js' 21 | }, 22 | extensions: ['*', '.js', '.vue', '.json'] 23 | }, 24 | devServer: { 25 | port: '8180', 26 | hot: true, 27 | stats: 'errors-only' 28 | }, 29 | performance: { 30 | hints: false 31 | }, 32 | module: { 33 | rules: [ 34 | { 35 | test: /\.vue$/, 36 | loader: 'vue-loader' 37 | }, 38 | { 39 | test: /\.js$/, 40 | loader: 'babel-loader' 41 | }, 42 | { 43 | test: /\.css$/, 44 | use: ['style-loader', 'css-loader'] 45 | } 46 | ] 47 | }, 48 | plugins: [ 49 | new webpack.DefinePlugin({ 50 | 'process.env': { 51 | NODE_ENV: '"development"' 52 | } 53 | }), 54 | new webpack.HotModuleReplacementPlugin(), 55 | new HtmlWebpackPlugin({ 56 | filename: 'index.html', 57 | template: '../index.html', 58 | inject: true 59 | }) 60 | ] 61 | } 62 | -------------------------------------------------------------------------------- /test/load/webpack/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | vue-orgchart 7 | 8 | 9 |
10 | 11 | 12 | --------------------------------------------------------------------------------