Repository: jbaysolutions/vue-grid-layout Branch: master Commit: 6e536767937f Files: 123 Total size: 1.4 MB Directory structure: gitextract_yc_usgoh/ ├── .browserslistrc ├── .eslintrc.js ├── .github/ │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.md │ │ └── feature_request.md │ └── workflows/ │ ├── build-test.yml │ └── vuepress-deploy.yml ├── .gitignore ├── LICENSE ├── README-zh_CN.md ├── README.md ├── babel.config.js ├── dist/ │ ├── vue-grid-layout.common.js │ └── vue-grid-layout.umd.js ├── jest.config.js ├── package.json ├── postcss.config.js ├── public/ │ ├── app.css │ └── index.html ├── src/ │ ├── App.vue │ ├── components/ │ │ ├── CustomDragElement.vue │ │ ├── GridItem.vue │ │ ├── GridLayout.vue │ │ ├── TestElement.vue │ │ └── index.js │ ├── helpers/ │ │ ├── DOM.js │ │ ├── draggableUtils.js │ │ ├── responsiveUtils.js │ │ └── utils.js │ └── main.js ├── test/ │ ├── interact-test.html │ ├── interact-test.js │ └── unit/ │ ├── GridItem.spec.js │ └── utils.spec.js ├── vue.config.js └── website/ ├── TODOS.md ├── docs/ │ ├── .vuepress/ │ │ ├── Autocomplete.js │ │ ├── components/ │ │ │ ├── Example01Basic.vue │ │ │ ├── Example02Events.vue │ │ │ ├── Example03MultipleGrids.vue │ │ │ ├── Example04AllowIgnore.vue │ │ │ ├── Example05Mirrored.vue │ │ │ ├── Example06Responsive.vue │ │ │ ├── Example07PreventCollision.vue │ │ │ ├── Example08ResponsivePredefinedLayouts.vue │ │ │ ├── Example09DynamicAddRemove.vue │ │ │ ├── Example10DragFromOutside.vue │ │ │ ├── Example11Bounded.vue │ │ │ ├── ExampleStylingGridLines.vue │ │ │ ├── ExampleStylingPlaceholder.vue │ │ │ ├── HomeFooter.vue │ │ │ └── HomepageGrid.vue │ │ ├── config.js │ │ ├── enhanceApp.js │ │ ├── public/ │ │ │ └── examples/ │ │ │ ├── 01-basic.html │ │ │ ├── 01-basic.js │ │ │ ├── 02-events.html │ │ │ ├── 02-events.js │ │ │ ├── 03-multiple-grids.html │ │ │ ├── 04-allow-ignore.html │ │ │ ├── 05-mirrored.html │ │ │ ├── 06-responsive.html │ │ │ ├── 06-responsive.js │ │ │ ├── 07-prevent-collision.html │ │ │ ├── 07-prevent-collision.js │ │ │ ├── 08-responsive-predefined-layouts.html │ │ │ ├── 08-responsive-predefined-layouts.js │ │ │ ├── 09-dynamic-add-remove.html │ │ │ ├── 09-dynamic-add-remove.js │ │ │ ├── 10-drag-from-outside.html │ │ │ ├── 10-drag-from-outside.js │ │ │ ├── 11-bounded.html │ │ │ ├── 11-bounded.js │ │ │ ├── app.css │ │ │ └── vue.js │ │ ├── styles/ │ │ │ └── index.styl │ │ └── theme/ │ │ ├── components/ │ │ │ ├── CarbonAds.vue │ │ │ └── Home.vue │ │ ├── index.js │ │ └── layouts/ │ │ └── Layout.vue │ ├── README.md │ ├── changelog/ │ │ └── README.md │ ├── guide/ │ │ ├── 01-basic.md │ │ ├── 02-events.md │ │ ├── 03-multiple-grids.md │ │ ├── 04-allow-ignore.md │ │ ├── 05-mirrored.md │ │ ├── 06-responsive.md │ │ ├── 07-prevent-collision.md │ │ ├── 08-responsive-predefined-layouts.md │ │ ├── 09-dynamic-add-remove.md │ │ ├── 10-drag-from-outside.md │ │ ├── 11-bounded.md │ │ ├── README.md │ │ ├── auto-size.md │ │ ├── events.md │ │ ├── examples.md │ │ ├── properties.md │ │ ├── styling.md │ │ └── usage.md │ ├── logo.psd │ ├── logo.xcf │ └── zh/ │ ├── README.md │ ├── changelog/ │ │ └── README.md │ └── guide/ │ ├── 01-basic.md │ ├── 02-events.md │ ├── 03-multiple-grids.md │ ├── 04-allow-ignore.md │ ├── 05-mirrored.md │ ├── 06-responsive.md │ ├── 07-prevent-collision.md │ ├── 08-responsive-predefined-layouts.md │ ├── 09-dynamic-add-remove.md │ ├── 10-drag-from-outside.md │ ├── 11-bounded.md │ ├── README.md │ ├── auto-size.md │ ├── events.md │ ├── examples.md │ ├── properties.md │ ├── styling.md │ └── usage.md └── package.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .browserslistrc ================================================ > 1% last 2 versions not ie <= 8 ================================================ FILE: .eslintrc.js ================================================ module.exports = { root: true, env: { node: true }, 'extends': [ 'plugin:vue/essential', 'eslint:recommended' ], rules: { 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' }, parserOptions: { parser: 'babel-eslint' } } ================================================ FILE: .github/FUNDING.yml ================================================ github: jbaysolutions ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.md ================================================ --- name: Bug report about: Create a report to help us improve title: '' labels: '' assignees: '' --- **Software version (please complete the following information):** - Browser [e.g. chrome, safari] - Vue Version [e.g. 2.5.7] - vue-grid-layout Version: [e.g. 2.3.3] **Describe the bug** A clear and concise description of what the bug is. Please use the [CodeSandbox Template](https://codesandbox.io/s/5wy3rz5z1x?module=%2Fsrc%2FShowcaseLayout.js) to demonstrate your bug. It is much easier for us to help you if you do. **To Reproduce** Steps to reproduce the behavior: 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error **Expected behavior** A clear and concise description of what you expected to happen. **Screenshots** If applicable, add screenshots to help explain your problem. **Additional context** Add any other context about the problem here. ================================================ FILE: .github/ISSUE_TEMPLATE/feature_request.md ================================================ --- name: Feature request about: Suggest an idea for this project title: '' labels: '' assignees: '' --- ## If you have a feature request, please try to implement it before requesting it.
This is free software and the author is busy with other projects. **Is your feature request related to a problem? Please describe.** A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] **Describe the solution you'd like** A clear and concise description of what you want to happen. **Describe alternatives you've considered** A clear and concise description of any alternative solutions or features you've considered. **Additional context** Add any other context or screenshots about the feature request here. ================================================ FILE: .github/workflows/build-test.yml ================================================ name: Build and Test on: push: branches: [ master ] pull_request: branches: [ master ] jobs: build: runs-on: ubuntu-latest strategy: matrix: node-version: [10.x, 12.x, 14.x, 15.x] # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ steps: - uses: actions/checkout@v2 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} - name: Install dependency run: yarn - name: Lint check run: yarn lint - name: Build run: yarn build - name: Unit test run: yarn test:unit ================================================ FILE: .github/workflows/vuepress-deploy.yml ================================================ name: Deploy vuepress website on: push: branches: - master jobs: build-and-deploy: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@master - uses: actions/setup-node@v2 with: node-version: '16' - name: vuepress-deploy uses: jenkey2011/vuepress-deploy@master env: ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }} TARGET_REPO: jbaysolutions/vue-grid-layout TARGET_BRANCH: gh-pages BUILD_SCRIPT: cd website && yarn && yarn build BUILD_DIR: public ================================================ FILE: .gitignore ================================================ .DS_Store node_modules #/dist dist/demo.html # local env files .env.local .env.*.local # Log files npm-debug.log* yarn-debug.log* yarn-error.log* # Editor directories and files .idea .vscode *.suo *.ntvs* *.njsproj *.sln *.sw* yarn-error.log website/docs/dist ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2015 greyby Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README-zh_CN.md ================================================

vue-grid-layout

vue-grid-layout是一个类似于[Gridster](http://dsmorse.github.io/gridster.js/)的栅格布局系统, 适用于Vue.js。 **灵感源自于 [React-Grid-Layout](https://github.com/STRML/react-grid-layout)** ### **当前版本:** 2.4.0 (支持 Vue 2.2+) ### **Vue 2.1.10 及以下请使用 [2.1.3](https://github.com/jbaysolutions/vue-grid-layout/tree/2.1.3)** ### **Vue 1 请使用 [1.0.3](https://github.com/jbaysolutions/vue-grid-layout/tree/1.0.3)**
[**[在线演示](https://jbaysolutions.github.io/vue-grid-layout/examples/01-basic.html) | [更新日志](/CHANGELOG.md)**] [English](./README.md) | 简体中文 #### 成功案例 - [DocsFold](https://www.docsfold.com/?utm_source=github&utm_medium=web&utm_campaign=vue-grid-layout) - [Draxed](https://www.draxed.com/?utm_source=github&utm_medium=web&utm_campaign=vue-grid-layout) - [Data Providers](https://www.dataproviders.io/?utm_source=github&utm_medium=web&utm_campaign=vue-grid-layout) - [Cataholic](https://cataholic.glitch.me/) *您还知悉其他项目? 请创建一个PR,谢谢!* ## 特性 * 可拖拽 * 可调整大小 * 静态部件(不可拖拽、调整大小) * 拖拽和调整大小时进行边界检查 * 增减部件时避免重建栅格 * 可序列化和还原的布局 * 自动化 RTL 支持 * 响应式 ## 入门指南 ### 安装 #### npm # 使用 npm npm install vue-grid-layout --save # 使用 yarn yarn add vue-grid-layout 引入 ```javascript import VueGridLayout from 'vue-grid-layout'; ``` 加入到 Vue 组件 ```javascript export default { components: { GridLayout: VueGridLayout.GridLayout, GridItem: VueGridLayout.GridItem }, // ... data, methods, mounted (), etc. } ``` #### 浏览器 在页面中使用已打包好的 [文件](https://github.com/jbaysolutions/vue-grid-layout/releases)。 此时组件已为可用状态。 ```html ``` ### 使用 ```javascript var testLayout = [ {"x":0,"y":0,"w":2,"h":2,"i":"0"}, {"x":2,"y":0,"w":2,"h":4,"i":"1"}, {"x":4,"y":0,"w":2,"h":5,"i":"2"}, {"x":6,"y":0,"w":2,"h":3,"i":"3"}, {"x":8,"y":0,"w":2,"h":3,"i":"4"}, {"x":10,"y":0,"w":2,"h":3,"i":"5"}, {"x":0,"y":5,"w":2,"h":5,"i":"6"}, {"x":2,"y":5,"w":2,"h":5,"i":"7"}, {"x":4,"y":5,"w":2,"h":5,"i":"8"}, {"x":6,"y":3,"w":2,"h":4,"i":"9"}, {"x":8,"y":4,"w":2,"h":4,"i":"10"}, {"x":10,"y":4,"w":2,"h":4,"i":"11"}, {"x":0,"y":10,"w":2,"h":5,"i":"12"}, {"x":2,"y":10,"w":2,"h":5,"i":"13"}, {"x":4,"y":8,"w":2,"h":4,"i":"14"}, {"x":6,"y":8,"w":2,"h":4,"i":"15"}, {"x":8,"y":10,"w":2,"h":5,"i":"16"}, {"x":10,"y":4,"w":2,"h":2,"i":"17"}, {"x":0,"y":9,"w":2,"h":3,"i":"18"}, {"x":2,"y":6,"w":2,"h":2,"i":"19"} ]; new Vue({ el: '#app', data: { layout: testLayout, }, }); ``` ```html {{item.i}} ``` ### 文档 #### 属性 ##### GridLayout * **layout** * type: `Array` * required: `true` 数据源。值必须为 `Array`,其数据项为 `Object`。 每条数据项必须有 `i`, `x`, `y`, `w` 和 `h` 属性。 请参考下面的 `GridItem`。 * **responsiveLayouts** * type: `Object` * required: `false` * default: `{}` 如果 `responsive` 设置为 `true`,该配置将作为栅格中每个断点的初始布局。键值是断点名称,每项的值都是类似 `layout` 属性定义的数据结构,值必须为 `Array`,其数据项为 `Object`。例如: `{lg: [layout items], md: [layout items]}`。需要注意的是,在创建栅格布局后设置该属性无效。 * **colNum** * type: `Number` * required: `false` * default: `12` 定义栅格系统的列数,其值需为自然数。 * **rowHeight** * type: `Number` * required: `false` * default: `150` 每行的高度,单位像素。 * **maxRows** * type: `Number` * required: `false` * default: `Infinity` 定义最大行数。 * **margin** * type: `Array` * required: `false` * default: `[10, 10]` 定义栅格中的元素边距。 值必须是包含两个 `Number`的数组,数组中第一个元素表示水平边距,第二个表示垂直边距,单位为像素。 * **isDraggable** * type: `Boolean` * required: `false` * default: `true` 标识栅格中的元素是否可拖拽。 * **isResizable** * type: `Boolean` * required: `false` * default: `true` 标识栅格中的元素是否可调整大小。 * **isMirrored** * type: `Boolean` * required: `false` * default: `false` 标识栅格中的元素是否可镜像反转。 * **autoSize** * type: `Boolean` * required: `false` * default: `true` 标识容器是否自动调整大小。 * **verticalCompact** * type: `Boolean` * required: `false` * default: `true` 标识布局是否垂直压缩。 * **useCssTransforms** * type: `Boolean` * required: `false` * default: `true` 标识是否使用CSS属性 `transition-property: transform;`。 * **responsive** * type: `Boolean` * required: `false` * default: `false` 标识布局是否为响应式。 * **breakpoints** * type: `Object` * required: `false` * default: { lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 } 为响应式布局设置断点,其中参数代表不同设备的宽度:lg(large),md(medium),sm(small),xs(extra small)。 * **cols** * type: `Object` * required: `false` * default: { lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 } 设置每个断点对应的列数。 * **useStyleCursor** * type: `Boolean` * required: `false` * default: `true` 标识是否使用动态鼠标指针样式。当拖动出现卡顿时,将此值设为 `false`也许可以缓解布局问题。 * **preventCollision** * type: `Boolean` * default: `false` 值设置为ture时,栅格只能拖动至空白处。 ##### GridItem * **i** * type: `String` * required: `true` 栅格中元素的ID。 * **x** * type: `Number` * required: `true` 标识栅格元素位于第几列,需为自然数。 * **y** * type: `Number` * required: `true` 标识栅格元素位于第几行,需为自然数。 * **w** * type: `Number` * required: `true` 标识栅格元素的初始宽度,值为`colWidth`的倍数。 * **h** * type: `Number` * required: `true` 标识栅格元素的初始高度,值为`rowHeight`的倍数。 * **minW** * type: `Number` * required: `false` * default: `1` 栅格元素的最小宽度,值为`colWidth`的倍数。 如果`w`小于`minW`,则`minW`的值会被`w`覆盖。 * **minH** * type: `Number` * required: `false` * default: `1` 栅格元素的最小高度,值为`rowHeight`的倍数。 如果`h`小于`minH`,则`minH`的值会被`h`覆盖。 * **maxW** * type: `Number` * required: `false` * default: `Infinity` 栅格元素的最大宽度,值为`colWidth`的倍数。 如果`w`大于`maxW`,则`maxW`的值会被`w`覆盖。 * **maxH** * type: `Number` * required: `false` * default: `Infinity` 栅格元素的最大高度,值为`rowHeight`的倍数。 如果`h`大于`maxH`,则`maxH`的值会被`h`覆盖。 * **isDraggable** * type: `Boolean` * required: `false` * default: `null` 标识栅格元素是否可拖拽。如果值为`null`则取决于父容器。 * **isResizable** * type: `Boolean` * required: `false` * default: `null` 标识栅格元素是否可调整大小。如果值为`null`则取决于父容器。 * **static** * type: `Boolean` * required: `false` * default: `false` 标识栅格元素是否为静态的(无法拖拽、调整大小或被其他元素移动)。 * **dragIgnoreFrom** * type: `String` * required: `false` * default: `'a, button'` 标识栅格元素中哪些子元素无法触发拖拽事件,值为`css-like`选择器。 请参考 [interact.js docs](http://interactjs.io/docs/#ignorable-selectors)中的`ignoreFrom`。 * **dragAllowFrom** * type: `String` * required: `false` * default: `null` 标识栅格元素中哪些子元素可以触发拖拽事件,值为`css-like`选择器。 如果值为`null`则表示所有子元素(`dragIgnoreFrom`的除外)。 请参考 [interact.js docs](http://interactjs.io/docs/#ignorable-selectors)中的`allowFrom`。 * **resizeIgnoreFrom** * type: `String` * required: `false` * default: `'a, button'` 标识栅格元素中哪些子元素无法触发调整大小的事件,值为`css-like`选择器。 请参考 [interact.js docs](http://interactjs.io/docs/#ignorable-selectors)中的`ignoreFrom`。 #### 事件 每一个栅格元素`grid-item`上都可以添加监听器,用于监听移动和调整大小事件,这样父级Vue对象就可以收到通知。 [示例](https://jbaysolutions.github.io/vue-grid-layout/examples/02-events.html) ````html {{item.i}} ```` * **layoutCreatedEvent** 对应Vue生命周期的`created` ```javascript layoutCreatedEvent: function(newLayout){ console.log("Created layout: ", newLayout) } ``` * **layoutBeforeMountEvent** 对应Vue生命周期的`beforeMount` ```javascript layoutBeforeMountEvent: function(newLayout){ console.log("beforeMount layout: ", newLayout) } ``` * **layoutMountedEvent** 对应Vue生命周期的`mounted` ```javascript layoutMountedEvent: function(newLayout){ console.log("Mounted layout: ", newLayout) } ``` * **layoutReadyEvent** 当完成mount中的所有操作时生成的事件 ```javascript layoutReadyEvent: function(newLayout){ console.log("Ready layout: ", newLayout) } ``` * **layoutUpdatedEvent** 更新事件(布局更新或栅格元素的位置重新计算) ```javascript layoutUpdatedEvent: function(newLayout){ console.log("Updated layout: ", newLayout) } ``` * **moveEvent** 移动时的事件 ```javascript moveEvent: function(i, newX, newY){ console.log("MOVE i=" + i + ", X=" + newX + ", Y=" + newY); }, ``` * **resizeEvent** 调整大小时的事件 ```javascript resizeEvent: function(i, newH, newW, newHPx, newWPx){ console.log("RESIZE i=" + i + ", H=" + newH + ", W=" + newW + ", H(px)=" + newHPx + ", W(px)=" + newWPx); }, ``` * **movedEvent** 移动后的事件 ```javascript movedEvent: function(i, newX, newY){ console.log("MOVED i=" + i + ", X=" + newX + ", Y=" + newY); }, ``` * **resizedEvent** 调整大小后的事件 ```javascript /** * * @param i the item id/index * @param newH new height in grid rows * @param newW new width in grid columns * @param newHPx new height in pixels * @param newWPx new width in pixels * */ resizedEvent: function(i, newH, newW, newHPx, newWPx){ console.log("RESIZED i=" + i + ", H=" + newH + ", W=" + newW + ", H(px)=" + newHPx + ", W(px)=" + newWPx); }, ``` ## 如何贡献 请提交issue或PR。 ## 待办事项 - [x] 基础栅格布局 - [x] 响应式 - [x] 可拖拽的栅格元素 - [x] 可调整大小的栅格元素 - [x] 静态元素 - [x] 每个元素的Min/max w/h ================================================ FILE: README.md ================================================

Vue Grid Layout

vue-grid-layout

Documentation Website

## What is Vue Grid Layout? vue-grid-layout is a grid layout system, like [Gridster](http://dsmorse.github.io/gridster.js/), for Vue.js. **Heavily inspired by [React-Grid-Layout](https://github.com/STRML/react-grid-layout)** ## Features * Draggable widgets * Resizable widgets * Static widgets * Bounds checking for dragging and resizing * Widgets may be added or removed without rebuilding grid * Layout can be serialized and restored * Automatic RTL support (resizing not working with RTL on 2.2.0) * Responsive ## **Current version:** 2.4.0 (Supports Vue 2.2+) #### **For legacy browsers**, like IE11, use version [2.3.12-legacy](https://github.com/jbaysolutions/vue-grid-layout/tree/legacy) #### **For Vue 2.1.10 and below use version [2.1.3](https://github.com/jbaysolutions/vue-grid-layout/tree/2.1.3)** #### **For Vue 1 use version [1.0.3](https://github.com/jbaysolutions/vue-grid-layout/tree/1.0.3)** ## Documentation Check out the Documentation Website #### Projects using vue-grid-layout - [DocsFold](https://www.docsfold.com/?utm_source=github&utm_medium=web&utm_campaign=vue-grid-layout) - [Draxed](https://www.draxed.com/?utm_source=github&utm_medium=web&utm_campaign=vue-grid-layout) - [Data Providers](https://www.dataproviders.io/?utm_source=github&utm_medium=web&utm_campaign=vue-grid-layout) - [Cataholic](https://cataholic.glitch.me/) *Know of others? Create a PR to let me know!* ## Contribute If you have a feature request, please add it as an issue or make a pull request. Developed by JBay Solutions ================================================ FILE: babel.config.js ================================================ module.exports = { presets: [ '@vue/app', '@babel/preset-env' ], "plugins": [ "transform-flow-comments" ] } ================================================ FILE: dist/vue-grid-layout.common.js ================================================ /*! vue-grid-layout - 2.4.0 | (c) 2015, 2022 Gustavo Santos (JBay Solutions) (http://www.jbaysolutions.com) | https://github.com/jbaysolutions/vue-grid-layout */ module.exports = /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); /******/ } /******/ }; /******/ /******/ // define __esModule on exports /******/ __webpack_require__.r = function(exports) { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ /******/ // create a fake namespace object /******/ // mode & 1: value is a module id, require it /******/ // mode & 2: merge all properties of value into the ns /******/ // mode & 4: return value when already ns object /******/ // mode & 8|1: behave like require /******/ __webpack_require__.t = function(value, mode) { /******/ if(mode & 1) value = __webpack_require__(value); /******/ if(mode & 8) return value; /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; /******/ var ns = Object.create(null); /******/ __webpack_require__.r(ns); /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); /******/ return ns; /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = "fb15"); /******/ }) /************************************************************************/ /******/ ({ /***/ "01f9": /***/ (function(module, exports, __webpack_require__) { "use strict"; var LIBRARY = __webpack_require__("2d00"); var $export = __webpack_require__("5ca1"); var redefine = __webpack_require__("2aba"); var hide = __webpack_require__("32e9"); var Iterators = __webpack_require__("84f2"); var $iterCreate = __webpack_require__("41a0"); var setToStringTag = __webpack_require__("7f20"); var getPrototypeOf = __webpack_require__("38fd"); var ITERATOR = __webpack_require__("2b4c")('iterator'); var BUGGY = !([].keys && 'next' in [].keys()); // Safari has buggy iterators w/o `next` var FF_ITERATOR = '@@iterator'; var KEYS = 'keys'; var VALUES = 'values'; var returnThis = function () { return this; }; module.exports = function (Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED) { $iterCreate(Constructor, NAME, next); var getMethod = function (kind) { if (!BUGGY && kind in proto) return proto[kind]; switch (kind) { case KEYS: return function keys() { return new Constructor(this, kind); }; case VALUES: return function values() { return new Constructor(this, kind); }; } return function entries() { return new Constructor(this, kind); }; }; var TAG = NAME + ' Iterator'; var DEF_VALUES = DEFAULT == VALUES; var VALUES_BUG = false; var proto = Base.prototype; var $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT]; var $default = $native || getMethod(DEFAULT); var $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined; var $anyNative = NAME == 'Array' ? proto.entries || $native : $native; var methods, key, IteratorPrototype; // Fix native if ($anyNative) { IteratorPrototype = getPrototypeOf($anyNative.call(new Base())); if (IteratorPrototype !== Object.prototype && IteratorPrototype.next) { // Set @@toStringTag to native iterators setToStringTag(IteratorPrototype, TAG, true); // fix for some old engines if (!LIBRARY && typeof IteratorPrototype[ITERATOR] != 'function') hide(IteratorPrototype, ITERATOR, returnThis); } } // fix Array#{values, @@iterator}.name in V8 / FF if (DEF_VALUES && $native && $native.name !== VALUES) { VALUES_BUG = true; $default = function values() { return $native.call(this); }; } // Define iterator if ((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])) { hide(proto, ITERATOR, $default); } // Plug for library Iterators[NAME] = $default; Iterators[TAG] = returnThis; if (DEFAULT) { methods = { values: DEF_VALUES ? $default : getMethod(VALUES), keys: IS_SET ? $default : getMethod(KEYS), entries: $entries }; if (FORCED) for (key in methods) { if (!(key in proto)) redefine(proto, key, methods[key]); } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods); } return methods; }; /***/ }), /***/ "02f4": /***/ (function(module, exports, __webpack_require__) { var toInteger = __webpack_require__("4588"); var defined = __webpack_require__("be13"); // true -> String#at // false -> String#codePointAt module.exports = function (TO_STRING) { return function (that, pos) { var s = String(defined(that)); var i = toInteger(pos); var l = s.length; var a, b; if (i < 0 || i >= l) return TO_STRING ? '' : undefined; a = s.charCodeAt(i); return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff ? TO_STRING ? s.charAt(i) : a : TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000; }; }; /***/ }), /***/ "0390": /***/ (function(module, exports, __webpack_require__) { "use strict"; var at = __webpack_require__("02f4")(true); // `AdvanceStringIndex` abstract operation // https://tc39.github.io/ecma262/#sec-advancestringindex module.exports = function (S, index, unicode) { return index + (unicode ? at(S, index).length : 1); }; /***/ }), /***/ "0bfb": /***/ (function(module, exports, __webpack_require__) { "use strict"; // 21.2.5.3 get RegExp.prototype.flags var anObject = __webpack_require__("cb7c"); module.exports = function () { var that = anObject(this); var result = ''; if (that.global) result += 'g'; if (that.ignoreCase) result += 'i'; if (that.multiline) result += 'm'; if (that.unicode) result += 'u'; if (that.sticky) result += 'y'; return result; }; /***/ }), /***/ "0d58": /***/ (function(module, exports, __webpack_require__) { // 19.1.2.14 / 15.2.3.14 Object.keys(O) var $keys = __webpack_require__("ce10"); var enumBugKeys = __webpack_require__("e11e"); module.exports = Object.keys || function keys(O) { return $keys(O, enumBugKeys); }; /***/ }), /***/ "1156": /***/ (function(module, exports, __webpack_require__) { // style-loader: Adds some css to the DOM by adding a ================================================ FILE: src/components/CustomDragElement.vue ================================================ ================================================ FILE: src/components/GridItem.vue ================================================ ================================================ FILE: src/components/GridLayout.vue ================================================ ================================================ FILE: src/components/TestElement.vue ================================================ ================================================ FILE: src/components/index.js ================================================ import GridItem from './GridItem.vue'; import GridLayout from './GridLayout.vue'; // import ResponsiveGridLayout from './ResponsiveGridLayout.vue'; const VueGridLayout = { // ResponsiveGridLayout, GridLayout, GridItem } export function install(Vue) { if (install.installed) return; install.installed = true; Object.keys(VueGridLayout).forEach(name => { Vue.component(name, VueGridLayout[name]); }); } const plugin = { install, }; let GlobalVue = null; if (typeof window !== 'undefined') { GlobalVue = window.Vue; } else if (typeof global !== 'undefined') { GlobalVue = global.Vue; } if (GlobalVue) { GlobalVue.use(plugin); } export default VueGridLayout; export { GridLayout, GridItem }; ================================================ FILE: src/helpers/DOM.js ================================================ let currentDir: "ltr" | "rtl" | "auto" = "auto"; // let currentDir = "auto"; function hasDocument(){ return (typeof document !== "undefined"); } function hasWindow(){ return (typeof window !== "undefined"); } export function getDocumentDir(){ if(!hasDocument()){ return currentDir; } const direction = (typeof document.dir !== "undefined") ? document.dir : document.getElementsByTagName("html")[0].getAttribute("dir"); return direction; } export function setDocumentDir(dir: "ltr" | "rtl" | "auto"){ // export function setDocumentDir(dir){ if(!hasDocument){ currentDir = dir; return; } const html = document.getElementsByTagName("html")[0]; html.setAttribute("dir", dir); } export function addWindowEventListener(event:string, callback: () => mixed){ if(!hasWindow){ callback(); return; } window.addEventListener(event, callback); } export function removeWindowEventListener(event:string, callback: () => mixed){ if(!hasWindow){ return; } window.removeEventListener(event, callback); } ================================================ FILE: src/helpers/draggableUtils.js ================================================ // Get {x, y} positions from event. export function getControlPosition(e) { return offsetXYFromParentOf(e); } // Get from offsetParent export function offsetXYFromParentOf(evt) { const offsetParent = evt.target.offsetParent || document.body; const offsetParentRect = evt.offsetParent === document.body ? {left: 0, top: 0} : offsetParent.getBoundingClientRect(); const x = evt.clientX + offsetParent.scrollLeft - offsetParentRect.left; const y = evt.clientY + offsetParent.scrollTop - offsetParentRect.top; /*const x = Math.round(evt.clientX + offsetParent.scrollLeft - offsetParentRect.left); const y = Math.round(evt.clientY + offsetParent.scrollTop - offsetParentRect.top);*/ return {x, y}; } // Create an data object exposed by 's events export function createCoreData(lastX, lastY, x, y) { // State changes are often (but not always!) async. We want the latest value. const isStart = !isNum(lastX); if (isStart) { // If this is our first move, use the x and y as last coords. return { deltaX: 0, deltaY: 0, lastX: x, lastY: y, x: x, y: y }; } else { // Otherwise calculate proper values. return { deltaX: x - lastX, deltaY: y - lastY, lastX: lastX, lastY: lastY, x: x, y: y }; } } function isNum(num) { return typeof num === 'number' && !isNaN(num); } ================================================ FILE: src/helpers/responsiveUtils.js ================================================ // @flow import {cloneLayout, compact, correctBounds} from './utils'; import type {Layout} from './utils'; export type ResponsiveLayout = {lg?: Layout, md?: Layout, sm?: Layout, xs?: Layout, xxs?: Layout}; type Breakpoint = string; type Breakpoints = {lg?: number, md?: number, sm?: number, xs?: number, xxs?: number}; /** * Given a width, find the highest breakpoint that matches is valid for it (width > breakpoint). * * @param {Object} breakpoints Breakpoints object (e.g. {lg: 1200, md: 960, ...}) * @param {Number} width Screen width. * @return {String} Highest breakpoint that is less than width. */ export function getBreakpointFromWidth(breakpoints: Breakpoints, width: number): Breakpoint { const sorted = sortBreakpoints(breakpoints); let matching = sorted[0]; for (let i = 1, len = sorted.length; i < len; i++) { const breakpointName = sorted[i]; if (width > breakpoints[breakpointName]) matching = breakpointName; } return matching; } /** * Given a breakpoint, get the # of cols set for it. * @param {String} breakpoint Breakpoint name. * @param {Object} cols Map of breakpoints to cols. * @return {Number} Number of cols. */ export function getColsFromBreakpoint(breakpoint: Breakpoint, cols: Breakpoints): number { if (!cols[breakpoint]) { throw new Error("ResponsiveGridLayout: `cols` entry for breakpoint " + breakpoint + " is missing!"); } return cols[breakpoint]; } /** * Given existing layouts and a new breakpoint, find or generate a new layout. * * This finds the layout above the new one and generates from it, if it exists. * * @param {Array} orgLayout Original layout. * @param {Object} layouts Existing layouts. * @param {Array} breakpoints All breakpoints. * @param {String} breakpoint New breakpoint. * @param {String} breakpoint Last breakpoint (for fallback). * @param {Number} cols Column count at new breakpoint. * @param {Boolean} verticalCompact Whether or not to compact the layout * vertically. * @return {Array} New layout. */ export function findOrGenerateResponsiveLayout(orgLayout: Layout, layouts: ResponsiveLayout, breakpoints: Breakpoints, breakpoint: Breakpoint, lastBreakpoint: Breakpoint, cols: number, verticalCompact: boolean): Layout { // If it already exists, just return it. if (layouts[breakpoint]) return cloneLayout(layouts[breakpoint]); // Find or generate the next layout let layout = orgLayout; const breakpointsSorted = sortBreakpoints(breakpoints); const breakpointsAbove = breakpointsSorted.slice(breakpointsSorted.indexOf(breakpoint)); for (let i = 0, len = breakpointsAbove.length; i < len; i++) { const b = breakpointsAbove[i]; if (layouts[b]) { layout = layouts[b]; break; } } layout = cloneLayout(layout || []); // clone layout so we don't modify existing items return compact(correctBounds(layout, {cols: cols}), verticalCompact); } export function generateResponsiveLayout(layout: Layout, breakpoints: Breakpoints, breakpoint: Breakpoint, lastBreakpoint: Breakpoint, cols: number, verticalCompact: boolean): Layout { // If it already exists, just return it. /*if (layouts[breakpoint]) return cloneLayout(layouts[breakpoint]); // Find or generate the next layout let layout = layouts[lastBreakpoint];*/ /*const breakpointsSorted = sortBreakpoints(breakpoints); const breakpointsAbove = breakpointsSorted.slice(breakpointsSorted.indexOf(breakpoint)); for (let i = 0, len = breakpointsAbove.length; i < len; i++) { const b = breakpointsAbove[i]; if (layouts[b]) { layout = layouts[b]; break; } }*/ layout = cloneLayout(layout || []); // clone layout so we don't modify existing items return compact(correctBounds(layout, {cols: cols}), verticalCompact); } /** * Given breakpoints, return an array of breakpoints sorted by width. This is usually * e.g. ['xxs', 'xs', 'sm', ...] * * @param {Object} breakpoints Key/value pair of breakpoint names to widths. * @return {Array} Sorted breakpoints. */ export function sortBreakpoints(breakpoints: Breakpoints): Array { const keys: Array = Object.keys(breakpoints); return keys.sort(function(a, b) { return breakpoints[a] - breakpoints[b]; }); } ================================================ FILE: src/helpers/utils.js ================================================ // @flow export type LayoutItemRequired = {w: number, h: number, x: number, y: number, i: string}; export type LayoutItem = LayoutItemRequired & {minW?: number, minH?: number, maxW?: number, maxH?: number, moved?: boolean, static?: boolean, isDraggable?: ?boolean, isResizable?: ?boolean}; export type Layout = Array; // export type Position = {left: number, top: number, width: number, height: number}; /* export type DragCallbackData = { node: HTMLElement, x: number, y: number, deltaX: number, deltaY: number, lastX: number, lastY: number }; */ // export type DragEvent = {e: Event} & DragCallbackData; export type Size = {width: number, height: number}; // export type ResizeEvent = {e: Event, node: HTMLElement, size: Size}; // const isProduction = process.env.NODE_ENV === 'production'; /** * Return the bottom coordinate of the layout. * * @param {Array} layout Layout array. * @return {Number} Bottom coordinate. */ export function bottom(layout: Layout): number { let max = 0, bottomY; for (let i = 0, len = layout.length; i < len; i++) { bottomY = layout[i]. y + layout[i].h; if (bottomY > max) max = bottomY; } return max; } export function cloneLayout(layout: Layout): Layout { const newLayout = Array(layout.length); for (let i = 0, len = layout.length; i < len; i++) { newLayout[i] = cloneLayoutItem(layout[i]); } return newLayout; } // Fast path to cloning, since this is monomorphic export function cloneLayoutItem(layoutItem: LayoutItem): LayoutItem { /*return { w: layoutItem.w, h: layoutItem.h, x: layoutItem.x, y: layoutItem.y, i: layoutItem.i, minW: layoutItem.minW, maxW: layoutItem.maxW, minH: layoutItem.minH, maxH: layoutItem.maxH, moved: Boolean(layoutItem.moved), static: Boolean(layoutItem.static), // These can be null isDraggable: layoutItem.isDraggable, isResizable: layoutItem.isResizable };*/ return JSON.parse(JSON.stringify(layoutItem)); } /** * Given two layoutitems, check if they collide. * * @return {Boolean} True if colliding. */ export function collides(l1: LayoutItem, l2: LayoutItem): boolean { if (l1 === l2) return false; // same element if (l1.x + l1.w <= l2.x) return false; // l1 is left of l2 if (l1.x >= l2.x + l2.w) return false; // l1 is right of l2 if (l1.y + l1.h <= l2.y) return false; // l1 is above l2 if (l1.y >= l2.y + l2.h) return false; // l1 is below l2 return true; // boxes overlap } /** * Given a layout, compact it. This involves going down each y coordinate and removing gaps * between items. * * @param {Array} layout Layout. * @param {Boolean} verticalCompact Whether or not to compact the layout * vertically. * @param {Object} minPositions * @return {Array} Compacted Layout. */ export function compact(layout: Layout, verticalCompact: Boolean, minPositions): Layout { // Statics go in the compareWith array right away so items flow around them. const compareWith = getStatics(layout); // We go through the items by row and column. const sorted = sortLayoutItemsByRowCol(layout); // Holding for new items. const out = Array(layout.length); for (let i = 0, len = sorted.length; i < len; i++) { let l = sorted[i]; // Don't move static elements if (!l.static) { l = compactItem(compareWith, l, verticalCompact, minPositions); // Add to comparison array. We only collide with items before this one. // Statics are already in this array. compareWith.push(l); } // Add to output array to make sure they still come out in the right order. out[layout.indexOf(l)] = l; // Clear moved flag, if it exists. l.moved = false; } return out; } /** * Compact an item in the layout. */ export function compactItem(compareWith: Layout, l: LayoutItem, verticalCompact: boolean, minPositions): LayoutItem { if (verticalCompact) { // Move the element up as far as it can go without colliding. while (l.y > 0 && !getFirstCollision(compareWith, l)) { l.y--; } } else if (minPositions) { const minY = minPositions[l.i].y; while (l.y > minY && !getFirstCollision(compareWith, l)) { l.y--; } } // Move it down, and keep moving it down if it's colliding. let collides; while((collides = getFirstCollision(compareWith, l))) { l.y = collides.y + collides.h; } return l; } /** * Given a layout, make sure all elements fit within its bounds. * * @param {Array} layout Layout array. * @param {Number} bounds Number of columns. */ export function correctBounds(layout: Layout, bounds: {cols: number}): Layout { const collidesWith = getStatics(layout); for (let i = 0, len = layout.length; i < len; i++) { const l = layout[i]; // Overflows right if (l.x + l.w > bounds.cols) l.x = bounds.cols - l.w; // Overflows left if (l.x < 0) { l.x = 0; l.w = bounds.cols; } if (!l.static) collidesWith.push(l); else { // If this is static and collides with other statics, we must move it down. // We have to do something nicer than just letting them overlap. while(getFirstCollision(collidesWith, l)) { l.y++; } } } return layout; } /** * Get a layout item by ID. Used so we can override later on if necessary. * * @param {Array} layout Layout array. * @param {String} id ID * @return {LayoutItem} Item at ID. */ export function getLayoutItem(layout: Layout, id: string): ?LayoutItem { for (let i = 0, len = layout.length; i < len; i++) { if (layout[i].i === id) return layout[i]; } } /** * Returns the first item this layout collides with. * It doesn't appear to matter which order we approach this from, although * perhaps that is the wrong thing to do. * * @param {Object} layoutItem Layout item. * @return {Object|undefined} A colliding layout item, or undefined. */ export function getFirstCollision(layout: Layout, layoutItem: LayoutItem): ?LayoutItem { for (let i = 0, len = layout.length; i < len; i++) { if (collides(layout[i], layoutItem)) return layout[i]; } } export function getAllCollisions(layout: Layout, layoutItem: LayoutItem): Array { return layout.filter((l) => collides(l, layoutItem)); } /** * Get all static elements. * @param {Array} layout Array of layout objects. * @return {Array} Array of static layout items.. */ export function getStatics(layout: Layout): Array { //return []; return layout.filter((l) => l.static); } /** * Move an element. Responsible for doing cascading movements of other elements. * * @param {Array} layout Full layout to modify. * @param {LayoutItem} l element to move. * @param {Number} [x] X position in grid units. * @param {Number} [y] Y position in grid units. * @param {Boolean} [isUserAction] If true, designates that the item we're moving is * being dragged/resized by th euser. */ export function moveElement(layout: Layout, l: LayoutItem, x: Number, y: Number, isUserAction: Boolean, preventCollision: Boolean): Layout { if (l.static) return layout; // Short-circuit if nothing to do. //if (l.y === y && l.x === x) return layout; const oldX = l.x; const oldY = l.y; const movingUp = y && l.y > y; // This is quite a bit faster than extending the object if (typeof x === 'number') l.x = x; if (typeof y === 'number') l.y = y; l.moved = true; // If this collides with anything, move it. // When doing this comparison, we have to sort the items we compare with // to ensure, in the case of multiple collisions, that we're getting the // nearest collision. let sorted = sortLayoutItemsByRowCol(layout); if (movingUp) sorted = sorted.reverse(); const collisions = getAllCollisions(sorted, l); if (preventCollision && collisions.length) { l.x = oldX; l.y = oldY; l.moved = false; return layout; } // Move each item that collides away from this element. for (let i = 0, len = collisions.length; i < len; i++) { const collision = collisions[i]; // console.log('resolving collision between', l.i, 'at', l.y, 'and', collision.i, 'at', collision.y); // Short circuit so we can't infinite loop if (collision.moved) continue; // This makes it feel a bit more precise by waiting to swap for just a bit when moving up. if (l.y > collision.y && l.y - collision.y > collision.h / 4) continue; // Don't move static items - we have to move *this* element away if (collision.static) { layout = moveElementAwayFromCollision(layout, collision, l, isUserAction); } else { layout = moveElementAwayFromCollision(layout, l, collision, isUserAction); } } return layout; } /** * This is where the magic needs to happen - given a collision, move an element away from the collision. * We attempt to move it up if there's room, otherwise it goes below. * * @param {Array} layout Full layout to modify. * @param {LayoutItem} collidesWith Layout item we're colliding with. * @param {LayoutItem} itemToMove Layout item we're moving. * @param {Boolean} [isUserAction] If true, designates that the item we're moving is being dragged/resized * by the user. */ export function moveElementAwayFromCollision(layout: Layout, collidesWith: LayoutItem, itemToMove: LayoutItem, isUserAction: ?boolean): Layout { const preventCollision = false // we're already colliding // If there is enough space above the collision to put this element, move it there. // We only do this on the main collision as this can get funky in cascades and cause // unwanted swapping behavior. if (isUserAction) { // Make a mock item so we don't modify the item here, only modify in moveElement. const fakeItem: LayoutItem = { x: itemToMove.x, y: itemToMove.y, w: itemToMove.w, h: itemToMove.h, i: '-1' }; fakeItem.y = Math.max(collidesWith.y - itemToMove.h, 0); if (!getFirstCollision(layout, fakeItem)) { return moveElement(layout, itemToMove, undefined, fakeItem.y, preventCollision); } } // Previously this was optimized to move below the collision directly, but this can cause problems // with cascading moves, as an item may actually leapflog a collision and cause a reversal in order. return moveElement(layout, itemToMove, undefined, itemToMove.y + 1, preventCollision); } /** * Helper to convert a number to a percentage string. * * @param {Number} num Any number * @return {String} That number as a percentage. */ export function perc(num: number): string { return num * 100 + '%'; } export function setTransform(top, left, width, height): Object { // Replace unitless items with px const translate = "translate3d(" + left + "px," + top + "px, 0)"; return { transform: translate, WebkitTransform: translate, MozTransform: translate, msTransform: translate, OTransform: translate, width: width + "px", height: height + "px", position: 'absolute' }; } /** * Just like the setTransform method, but instead it will return a negative value of right. * * @param top * @param right * @param width * @param height * @returns {{transform: string, WebkitTransform: string, MozTransform: string, msTransform: string, OTransform: string, width: string, height: string, position: string}} */ export function setTransformRtl(top, right, width, height): Object { // Replace unitless items with px const translate = "translate3d(" + right * -1 + "px," + top + "px, 0)"; return { transform: translate, WebkitTransform: translate, MozTransform: translate, msTransform: translate, OTransform: translate, width: width + "px", height: height + "px", position: 'absolute' }; } export function setTopLeft(top, left, width, height): Object { return { top: top + "px", left: left + "px", width: width + "px", height: height + "px", position: 'absolute' }; } /** * Just like the setTopLeft method, but instead, it will return a right property instead of left. * * @param top * @param right * @param width * @param height * @returns {{top: string, right: string, width: string, height: string, position: string}} */ export function setTopRight(top, right, width, height): Object { return { top: top + "px", right: right+ "px", width: width + "px", height: height + "px", position: 'absolute' }; } /** * Get layout items sorted from top left to right and down. * * @return {Array} Array of layout objects. * @return {Array} Layout, sorted static items first. */ export function sortLayoutItemsByRowCol(layout: Layout): Layout { return [].concat(layout).sort(function(a, b) { if (a.y === b.y && a.x === b.x) { return 0; } if (a.y > b.y || (a.y === b.y && a.x > b.x)) { return 1; } return -1; }); } /** * Generate a layout using the initialLayout and children as a template. * Missing entries will be added, extraneous ones will be truncated. * * @param {Array} initialLayout Layout passed in through props. * @param {String} breakpoint Current responsive breakpoint. * @param {Boolean} verticalCompact Whether or not to compact the layout vertically. * @return {Array} Working layout. */ /* export function synchronizeLayoutWithChildren(initialLayout: Layout, children: Array|React.Element, cols: number, verticalCompact: boolean): Layout { // ensure 'children' is always an array if (!Array.isArray(children)) { children = [children]; } initialLayout = initialLayout || []; // Generate one layout item per child. let layout: Layout = []; for (let i = 0, len = children.length; i < len; i++) { let newItem; const child = children[i]; // Don't overwrite if it already exists. const exists = getLayoutItem(initialLayout, child.key || "1" /!* FIXME satisfies Flow *!/); if (exists) { newItem = exists; } else { const g = child.props._grid; // Hey, this item has a _grid property, use it. if (g) { if (!isProduction) { validateLayout([g], 'ReactGridLayout.children'); } // Validated; add it to the layout. Bottom 'y' possible is the bottom of the layout. // This allows you to do nice stuff like specify {y: Infinity} if (verticalCompact) { newItem = cloneLayoutItem({...g, y: Math.min(bottom(layout), g.y), i: child.key}); } else { newItem = cloneLayoutItem({...g, y: g.y, i: child.key}); } } // Nothing provided: ensure this is added to the bottom else { newItem = cloneLayoutItem({w: 1, h: 1, x: 0, y: bottom(layout), i: child.key || "1"}); } } layout[i] = newItem; } // Correct the layout. layout = correctBounds(layout, {cols: cols}); layout = compact(layout, verticalCompact); return layout; } */ /** * Validate a layout. Throws errors. * * @param {Array} layout Array of layout items. * @param {String} [contextName] Context name for errors. * @throw {Error} Validation error. */ export function validateLayout(layout: Layout, contextName: string): void { contextName = contextName || "Layout"; const subProps = ['x', 'y', 'w', 'h']; let keyArr = []; if (!Array.isArray(layout)) throw new Error(contextName + " must be an array!"); for (let i = 0, len = layout.length; i < len; i++) { const item = layout[i]; for (let j = 0; j < subProps.length; j++) { if (typeof item[subProps[j]] !== 'number') { throw new Error('VueGridLayout: ' + contextName + '[' + i + '].' + subProps[j] + ' must be a number!'); } } if (item.i === undefined || item.i === null) { throw new Error('VueGridLayout: ' + contextName + '[' + i + '].i cannot be null!'); } if (typeof item.i !== 'number' && typeof item.i !== 'string') { throw new Error('VueGridLayout: ' + contextName + '[' + i + '].i must be a string or number!'); } if (keyArr.indexOf(item.i) >= 0) { throw new Error('VueGridLayout: ' + contextName + '[' + i + '].i must be unique!'); } keyArr.push(item.i); if (item.static !== undefined && typeof item.static !== 'boolean') { throw new Error('VueGridLayout: ' + contextName + '[' + i + '].static must be a boolean!'); } } } // Flow can't really figure this out, so we just use Object export function autoBindHandlers(el: Object, fns: Array): void { fns.forEach((key) => el[key] = el[key].bind(el)); } /** * Convert a JS object to CSS string. Similar to React's output of CSS. * @param obj * @returns {string} */ export function createMarkup(obj) { var keys = Object.keys(obj); if (!keys.length) return ''; var i, len = keys.length; var result = ''; for (i = 0; i < len; i++) { var key = keys[i]; var val = obj[key]; result += hyphenate(key) + ':' + addPx(key, val) + ';'; } return result; } /* The following list is defined in React's core */ export var IS_UNITLESS = { animationIterationCount: true, boxFlex: true, boxFlexGroup: true, boxOrdinalGroup: true, columnCount: true, flex: true, flexGrow: true, flexPositive: true, flexShrink: true, flexNegative: true, flexOrder: true, gridRow: true, gridColumn: true, fontWeight: true, lineClamp: true, lineHeight: true, opacity: true, order: true, orphans: true, tabSize: true, widows: true, zIndex: true, zoom: true, // SVG-related properties fillOpacity: true, stopOpacity: true, strokeDashoffset: true, strokeOpacity: true, strokeWidth: true }; /** * Will add px to the end of style values which are Numbers. * @param name * @param value * @returns {*} */ export function addPx(name, value) { if(typeof value === 'number' && !IS_UNITLESS[ name ]) { return value + 'px'; } else { return value; } } /** * Hyphenate a camelCase string. * * @param {String} str * @return {String} */ export var hyphenateRE = /([a-z\d])([A-Z])/g; export function hyphenate(str) { return str.replace(hyphenateRE, '$1-$2').toLowerCase(); } export function findItemInArray(array, property, value) { for (var i=0; i < array.length; i++) if (array[i][property] == value) return true; return false; } export function findAndRemove(array, property, value) { array.forEach(function (result, index) { if (result[property] === value) { //Remove from array array.splice(index, 1); } }); } ================================================ FILE: src/main.js ================================================ import Vue from 'vue' import App from './App.vue' new Vue({ render: h => h(App) }).$mount('#app') ================================================ FILE: test/interact-test.html ================================================ Interact TEST
Resize from any edge or corner
================================================ FILE: test/interact-test.js ================================================ function dragMoveListener (event) { var target = event.target, // keep the dragged position in the data-x/data-y attributes x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx, y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy; // translate the element target.style.webkitTransform = target.style.transform = 'translate(' + x + 'px, ' + y + 'px)'; // update the posiion attributes target.setAttribute('data-x', x); target.setAttribute('data-y', y); } // this is used later in the resizing and gesture demos window.dragMoveListener = dragMoveListener; interact('.resize-drag') .draggable({ onmove: window.dragMoveListener, restrict: { restriction: 'parent', elementRect: { top: 0, left: 0, bottom: 1, right: 1 } }, }) .resizable({ // resize from all edges and corners edges: { left: true, right: true, bottom: true, top: true }, // keep the edges inside the parent restrictEdges: { outer: 'parent', endOnly: true, }, // minimum size restrictSize: { min: { width: 100, height: 50 }, }, inertia: true, }) .on('resizemove', function (event) { var target = event.target, x = (parseFloat(target.getAttribute('data-x')) || 0), y = (parseFloat(target.getAttribute('data-y')) || 0); // update the element's style target.style.width = event.rect.width + 'px'; target.style.height = event.rect.height + 'px'; // translate when resizing from top or left edges x += event.deltaRect.left; y += event.deltaRect.top; target.style.webkitTransform = target.style.transform = 'translate(' + x + 'px,' + y + 'px)'; target.setAttribute('data-x', x); target.setAttribute('data-y', y); target.textContent = Math.round(event.rect.width) + '\u00D7' + Math.round(event.rect.height); }); ================================================ FILE: test/unit/GridItem.spec.js ================================================ import { shallowMount } from '@vue/test-utils' import GridLayout from '../../src/components/GridLayout.vue' let layout describe('GridLayout test', () => { beforeAll(()=>{ let testLayout = [{"x":0,"y":0,"w":2,"h":2,"i":"0", resizable: true, draggable: true, static: false, minY: 0, maxY: 2}]; layout = JSON.parse(JSON.stringify(testLayout)) }) describe('Interface test', () => { it('should render correct contents', () => { const wrapper = shallowMount(GridLayout, { propsData: { layout: layout } }) const grid = wrapper.findAll('.vue-grid-layout'); expect(grid.selector).toEqual('.vue-grid-layout'); }) }) }) ================================================ FILE: test/unit/utils.spec.js ================================================ // @flow /* eslint-env jest */ import { bottom, collides, compact, moveElement, sortLayoutItemsByRowCol, validateLayout } from "../../src/helpers/utils"; describe("bottom", () => { it("Handles an empty layout as input", () => { expect(bottom([])).toEqual(0); }); it("Returns the bottom coordinate of the layout", () => { expect( bottom([ { i: "1", x: 0, y: 1, w: 1, h: 1 }, { i: "2", x: 1, y: 2, w: 1, h: 1 } ]) ).toEqual(3); }); }); describe("sortLayoutItemsByRowCol", () => { it("should sort by top to bottom right", () => { const layout = [ { x: 1, y: 1, w: 1, h: 1, i: "2" }, { x: 1, y: 0, w: 1, h: 1, i: "1" }, { x: 0, y: 1, w: 2, h: 2, i: "3" } ]; expect(sortLayoutItemsByRowCol(layout)).toEqual([ { x: 1, y: 0, w: 1, h: 1, i: "1" }, { x: 0, y: 1, w: 2, h: 2, i: "3" }, { x: 1, y: 1, w: 1, h: 1, i: "2" } ]); }); }); describe("collides", () => { it("Returns whether the layout items collide", () => { expect( collides( { i: "1", x: 0, y: 1, w: 1, h: 1 }, { i: "2", x: 1, y: 2, w: 1, h: 1 } ) ).toEqual(false); expect( collides( { i: "1", x: 0, y: 1, w: 1, h: 1 }, { i: "2", x: 0, y: 1, w: 1, h: 1 } ) ).toEqual(true); }); }); describe("validateLayout", () => { it("Validates an empty layout", () => { validateLayout([]); }); it("Validates a populated layout", () => { validateLayout([ { i: "1", x: 0, y: 1, w: 1, h: 1 }, { i: "2", x: 1, y: 2, w: 1, h: 1 } ]); }); it("Throws errors on invalid input", () => { expect(() => { validateLayout([ { i: "1", x: 0, y: 1, w: 1, h: 1 }, { i: "2", x: 1, y: 2, w: 1 } ]); }).toThrowError(/layout\[1\]\.h must be a number!/i); }); }); describe("moveElement", () => { function compactAndMove( layout, layoutItem, x, y, isUserAction, preventCollision ) { return compact( moveElement( layout, layoutItem, x, y, isUserAction, preventCollision ) ); } it("Does not change layout when colliding on no rearrangement mode", () => { const layout = [ { i: "1", x: 0, y: 1, w: 1, h: 1, moved: false }, { i: "2", x: 1, y: 2, w: 1, h: 1, moved: false } ]; const layoutItem = layout[0]; expect( moveElement( layout, layoutItem, 1, 2, // x, y true, true // isUserAction, preventCollision ) ).toEqual([ { i: "1", x: 0, y: 1, w: 1, h: 1, moved: false }, { i: "2", x: 1, y: 2, w: 1, h: 1, moved: false } ]); }); it("Does change layout when colliding in rearrangement mode", () => { const layout = [ { i: "1", x: 0, y: 0, w: 1, h: 1, moved: false }, { i: "2", x: 1, y: 0, w: 1, h: 1, moved: false } ]; const layoutItem = layout[0]; expect( moveElement( layout, layoutItem, 1, 0, // x, y true, false // isUserAction, preventCollision ) ).toEqual([ { i: "1", x: 1, y: 0, w: 1, h: 1, moved: true }, { i: "2", x: 1, y: 1, w: 1, h: 1, moved: true } ]); }); it("Moves elements out of the way without causing panel jumps when compaction is vertical", () => { const layout = [ { x: 0, y: 0, w: 1, h: 10, i: "A" }, { x: 0, y: 10, w: 1, h: 1, i: "B" }, { x: 0, y: 11, w: 1, h: 1, i: "C" } ]; // move A down slightly so it collides with C; can cause C to jump above B. // We instead want B to jump above A (it has the room) const itemA = layout[0]; expect( compactAndMove( layout, itemA, 0, 1, // x, y true, false // isUserAction, preventCollision ) ).toEqual([ expect.objectContaining({ x: 0, y: 1, w: 1, h: 10, i: "A" }), expect.objectContaining({ x: 0, y: 0, w: 1, h: 1, i: "B" }), expect.objectContaining({ x: 0, y: 11, w: 1, h: 1, i: "C" }) ]); }); it("Calculates the correct collision when moving large object far", () => { const layout = [ { x: 0, y: 0, w: 1, h: 10, i: "A" }, { x: 0, y: 10, w: 1, h: 1, i: "B" }, { x: 0, y: 11, w: 1, h: 1, i: "C" } ]; // Move A down by 2. This should move B above, but since we don't compact in between, // C should move below. const itemA = layout[0]; expect( moveElement( layout, itemA, 0, 2, // x, y true, false // isUserAction, preventCollision ) ).toEqual([ expect.objectContaining({ x: 0, y: 2, w: 1, h: 10, i: "A" }), expect.objectContaining({ x: 0, y: 1, w: 1, h: 1, i: "B" }), expect.objectContaining({ x: 0, y: 12, w: 1, h: 1, i: "C" }) ]); }); it("Moves elements out of the way without causing panel jumps when compaction is vertical", () => { const layout = [ { x: 0, y: 0, w: 1, h: 1, i: "A" }, { x: 1, y: 0, w: 1, h: 1, i: "B" }, { x: 0, y: 1, w: 2, h: 2, i: "C" } ]; // move A over slightly so it collides with B; can cause C to jump above B // this test will check that that does not happen const itemA = layout[0]; expect( moveElement( layout, itemA, 1, 0, // x, y true, false // isUserAction, preventCollision ) ).toEqual([ { x: 1, y: 0, w: 1, h: 1, i: "A", moved: true }, { x: 1, y: 1, w: 1, h: 1, i: "B", moved: true }, { x: 0, y: 2, w: 2, h: 2, i: "C", moved: true } ]); }); it("Moves one element to another should cause moving down panels, vert compact", () => { // | A | B | // |C| D | const layout = [ { x: 0, y: 0, w: 2, h: 1, i: "A" }, { x: 2, y: 0, w: 2, h: 1, i: "B" }, { x: 0, y: 1, w: 1, h: 1, i: "C" }, { x: 1, y: 1, w: 3, h: 1, i: "D" } ]; // move B left slightly so it collides with A; can cause C to jump above A // this test will check that that does not happen const itemB = layout[1]; expect( compactAndMove( layout, itemB, 1, 0, // x, y true, false // isUserAction, preventCollision ) ).toEqual([ expect.objectContaining({ x: 0, y: 1, w: 2, h: 1, i: "A" }), expect.objectContaining({ x: 1, y: 0, w: 2, h: 1, i: "B" }), expect.objectContaining({ x: 0, y: 2, w: 1, h: 1, i: "C" }), expect.objectContaining({ x: 1, y: 2, w: 3, h: 1, i: "D" }) ]); }); it("Moves one element to another should cause moving down panels, vert compact", () => { // | A | // |B|C| // | | // // Moving C above A should not move B above A const layout = [ { x: 0, y: 0, w: 2, h: 1, i: "A" }, { x: 0, y: 1, w: 1, h: 1, i: "B" }, { x: 1, y: 1, w: 1, h: 2, i: "C" } ]; // Move C up. const itemB = layout[2]; expect( compactAndMove( layout, itemB, 1, 0, // x, y true, false // isUserAction, preventCollision ) ).toEqual([ expect.objectContaining({ x: 0, y: 2, w: 2, h: 1, i: "A" }), expect.objectContaining({ x: 0, y: 3, w: 1, h: 1, i: "B" }), expect.objectContaining({ x: 1, y: 0, w: 1, h: 2, i: "C" }) ]); }); }); describe("compact vertical", () => { it("Removes empty vertical space above item", () => { const layout = [{ i: "1", x: 0, y: 1, w: 1, h: 1 }]; expect(compact(layout, true)).toEqual([ { i: "1", x: 0, y: 0, w: 1, h: 1, moved: false } ]); }); it("Resolve collision by moving item further down in array", () => { const layout = [ { x: 0, y: 0, w: 1, h: 5, i: "1" }, { x: 0, y: 1, w: 1, h: 1, i: "2" } ]; expect(compact(layout, true)).toEqual([ { x: 0, y: 0, w: 1, h: 5, i: "1", moved: false }, { x: 0, y: 5, w: 1, h: 1, i: "2", moved: false } ]); }); it("Handles recursive collision by moving new collisions out of the way before moving item down", () => { const layout = [ { x: 0, y: 0, w: 2, h: 5, i: "1" }, { x: 0, y: 0, w: 10, h: 1, i: "2" }, { x: 5, y: 1, w: 1, h: 1, i: "3" }, { x: 5, y: 2, w: 1, h: 1, i: "4" }, { x: 5, y: 3, w: 1, h: 1, i: "5", static: true } ]; expect(compact(layout, true)).toEqual([ { x: 0, y: 0, w: 2, h: 5, i: "1", moved: false }, { x: 0, y: 5, w: 10, h: 1, i: "2", moved: false }, { x: 5, y: 0, w: 1, h: 1, i: "3", moved: false }, { x: 5, y: 1, w: 1, h: 1, i: "4", moved: false }, { x: 5, y: 3, w: 1, h: 1, i: "5", moved: false, static: true } ]); }); }); ================================================ FILE: vue.config.js ================================================ // https://medium.com/js-dojo/how-to-reduce-your-vue-js-bundle-size-with-webpack-3145bf5019b7 // const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; const webpack = require('webpack'); const PACKAGE = require('./package.json'); const banner = PACKAGE.name + ' - ' + PACKAGE.version + ' | ' + '(c) 2015, ' + new Date().getFullYear() + ' ' + PACKAGE.author + ' | ' + PACKAGE.homepage; module.exports = { configureWebpack: { output: { library: "VueGridLayout", libraryExport: 'default' }, plugins: [ // new BundleAnalyzerPlugin(), new webpack.BannerPlugin(banner) ], }, css: { extract: false }, } ================================================ FILE: website/TODOS.md ================================================ # vue-grid-layout https://github.com/wearebraid/vueformulate.com/tree/master/docs # emit responsiveLayoutUpdatedEvent? https://github.com/jbaysolutions/vue-grid-layout/compare/master...wzquyin:master ================================================ FILE: website/docs/.vuepress/Autocomplete.js ================================================ // import MyFormulateAutocomplete from './components/MyFormulateAutocomplete' // // export default function (formulateInstance) { // formulateInstance.extend({ // components: { // MyFormulateAutocomplete // }, // library: { // autocomplete: { // classification: 'text', // component: 'MyFormulateAutocomplete' // } // } // }) // } ================================================ FILE: website/docs/.vuepress/components/Example01Basic.vue ================================================ ================================================ FILE: website/docs/.vuepress/components/Example02Events.vue ================================================ ================================================ FILE: website/docs/.vuepress/components/Example03MultipleGrids.vue ================================================ ================================================ FILE: website/docs/.vuepress/components/Example04AllowIgnore.vue ================================================ ================================================ FILE: website/docs/.vuepress/components/Example05Mirrored.vue ================================================ ================================================ FILE: website/docs/.vuepress/components/Example06Responsive.vue ================================================ ================================================ FILE: website/docs/.vuepress/components/Example07PreventCollision.vue ================================================ ================================================ FILE: website/docs/.vuepress/components/Example08ResponsivePredefinedLayouts.vue ================================================ ================================================ FILE: website/docs/.vuepress/components/Example09DynamicAddRemove.vue ================================================ ================================================ FILE: website/docs/.vuepress/components/Example10DragFromOutside.vue ================================================ ================================================ FILE: website/docs/.vuepress/components/Example11Bounded.vue ================================================ ================================================ FILE: website/docs/.vuepress/components/ExampleStylingGridLines.vue ================================================ ================================================ FILE: website/docs/.vuepress/components/ExampleStylingPlaceholder.vue ================================================ ================================================ FILE: website/docs/.vuepress/components/HomeFooter.vue ================================================ ================================================ FILE: website/docs/.vuepress/components/HomepageGrid.vue ================================================ ================================================ FILE: website/docs/.vuepress/config.js ================================================ const description = 'A draggable and resizable grid layout, as a Vue component.' const title = 'Vue Grid Layout - ️A grid layout system for Vue.js' module.exports = { base: "/vue-grid-layout/", locales: { '/': { lang: 'en-US', title: 'Vue Grid Layout - ️A grid layout system for Vue.js', description: 'A draggable and resizable grid layout, as a Vue component.' }, '/zh/': { lang: 'zh-CN', title: 'Vue Grid Layout -️ 适用Vue.js的栅格布局系统', description: '可拖动和可调整大小栅格布局的Vue组件。' } }, head: [ ['link', { rel: 'icon', href: `/favicon.ico` }], ['link', { rel: "apple-touch-icon", sizes: "180x180", href: "https://jbaysolutions.github.io/vue-grid-layout/assets/favicon/apple-touch-icon.png"}], // ['script', { src: 'https://cdn.jsdelivr.net/npm/vue-grid-layout@2.3.9/dist/vue-grid-layout.umd.min.js' }] [ 'script', { async: true, src: 'https://www.googletagmanager.com/gtag/js?id=G-9JZJJHRV8R', }, ], [ 'script', {}, [ "window.dataLayer = window.dataLayer || [];\nfunction gtag(){dataLayer.push(arguments);}\ngtag('js', new Date());\ngtag('config', 'G-9JZJJHRV8R');", ], ], ], port: 8081, theme: '@vuepress/vue', themeConfig: { smoothScroll: true, logo: '/assets/img/logo.png', repo: 'jbaysolutions/vue-grid-layout', docsDir: 'website/docs', editLinks: true, algolia: { apiKey: '2f143d1edd24605564065dd02bf0a22b', indexName: 'vue_grid_layout' }, locales: { '/': { selectText: 'Languages', label: 'English', ariaLabel: 'Select language', sidebar: { '/guide/': [ { title: "Guide", collapsable: false, children: [ '', 'usage', 'properties', 'events', 'styling', ] }, { title: "Examples", collapsable: false, children: [ '01-basic', '02-events', '03-multiple-grids', '04-allow-ignore', '05-mirrored', '06-responsive', '07-prevent-collision', '08-responsive-predefined-layouts', '09-dynamic-add-remove', '10-drag-from-outside', '11-bounded', ] } ] }, nav: [ {text: 'Home', link: '/'}, {text: 'Guide', link: '/guide/'}, {text: 'Changelog', link: '/changelog/'} ], searchPlaceholder: 'Search...', editLinkText: 'Help improve this page!', lastUpdated: 'Last Updated' }, '/zh/': { selectText: '选择语言', label: '简体中文', ariaLabel: '选择语言', sidebar: { '/zh/guide/': [ { title: "首页", collapsable: false, children: [ '', 'usage', 'properties', 'events', 'styling', ] }, { title: "例子", collapsable: false, children: [ '01-basic', '02-events', '03-multiple-grids', '04-allow-ignore', '05-mirrored', '06-responsive', '07-prevent-collision', '08-responsive-predefined-layouts', '09-dynamic-add-remove', '10-drag-from-outside', '11-bounded', ] } ] }, nav: [ {text: '首页', link: '/zh/'}, {text: '指南', link: '/zh/guide/'}, {text: '更新日志', link: '/zh/changelog/'} ], searchPlaceholder: '搜索...', editLinkText: '帮助改善此页面!', lastUpdated: '最后更新时间' } } }, plugins: [ '@vuepress/back-to-top', /*['@vuepress/google-analytics', { ga: 'UA-37288388-24' // UA-00000000-0 }],*/ ['seo', { title: $page => `${$page.title} — Vue Grid Layout`, // image: () => 'https://jbaysolutions.github.io/vue-grid-layout/assets/img/og.jpg', siteTitle: (_, $site) => $site.title, description: $page => $page.frontmatter.description || description, author: (_, $site) => $site.themeConfig.author, tags: $page => $page.frontmatter.tags, twitterCard: _ => 'summary_large_image', type: () => 'article', url: (_, $site, path) => ($site.themeConfig.domain || '') + path, publishedAt: $page => $page.frontmatter.date && new Date($page.frontmatter.date), modifiedAt: $page => $page.lastUpdated && new Date($page.lastUpdated), }], ['vuepress-plugin-serve', { port: 8080, staticOptions: { dotfiles: 'allow', }, /*beforeServer(app, server) { app.get('/path/to/my/custom', function(req, res) { res.json({ custom: 'response' }) }) },*/ }], ], dest: 'public', } ================================================ FILE: website/docs/.vuepress/enhanceApp.js ================================================ /** * App level enhancements. Read more here: * https://vuepress.vuejs.org/guide/basic-config.html#app-level-enhancements */ // import pageComponents from '@internal/page-components' import Autocomplete from './Autocomplete' // import ArticleCard from './components/ArticleCard' // import GithubButton from 'vue-github-button' // import VTooltip from 'v-tooltip' // import '../../node_modules/@braid/vue-formulate/themes/snow/snow.scss' export default ({ Vue }) => { /*Vue.prototype.$gridlayout = { async load () { await import('vue-grid-layout'); console.log("LOADED!") }, };*/ /*Vue.use(VueFormulate, { plugins: [ Autocomplete ] })*/ // Vue.use(VTooltip) // for (const [name, component] of Object.entries(pageComponents)) { // Vue.component(name, component) // } // Vue.component('github-button', GithubButton) // Vue.component('ArticleCard', ArticleCard) } ================================================ FILE: website/docs/.vuepress/public/examples/01-basic.html ================================================ Vue Grid Layout Example 1 - Basic

Vue Grid Layout Example 1 - Basic

View project on Github
Next example: Move and resize events
Displayed as [x, y, w, h]:
{{item.i}}: [{{item.x}}, {{item.y}}, {{item.w}}, {{item.h}}]
Draggable Resizable
{{itemTitle(item)}}
================================================ FILE: website/docs/.vuepress/public/examples/01-basic.js ================================================ var testLayout = [ {"x":0,"y":0,"w":2,"h":2,"i":"0", static: false}, {"x":2,"y":0,"w":2,"h":4,"i":"1", static: true}, {"x":4,"y":0,"w":2,"h":5,"i":"2", static: false}, {"x":6,"y":0,"w":2,"h":3,"i":"3", static: false}, {"x":8,"y":0,"w":2,"h":3,"i":"4", static: false}, {"x":10,"y":0,"w":2,"h":3,"i":"5", static: false}, {"x":0,"y":5,"w":2,"h":5,"i":"6", static: false}, {"x":2,"y":5,"w":2,"h":5,"i":"7", static: false}, {"x":4,"y":5,"w":2,"h":5,"i":"8", static: false}, {"x":6,"y":3,"w":2,"h":4,"i":"9", static: true}, {"x":8,"y":4,"w":2,"h":4,"i":"10", static: false}, {"x":10,"y":4,"w":2,"h":4,"i":"11", static: false}, {"x":0,"y":10,"w":2,"h":5,"i":"12", static: false}, {"x":2,"y":10,"w":2,"h":5,"i":"13", static: false}, {"x":4,"y":8,"w":2,"h":4,"i":"14", static: false}, {"x":6,"y":8,"w":2,"h":4,"i":"15", static: false}, {"x":8,"y":10,"w":2,"h":5,"i":"16", static: false}, {"x":10,"y":4,"w":2,"h":2,"i":"17", static: false}, {"x":0,"y":9,"w":2,"h":3,"i":"18", static: false}, {"x":2,"y":6,"w":2,"h":2,"i":"19", static: false} ]; // var GridLayout = VueGridLayout.GridLayout; // var GridItem = VueGridLayout.GridItem; new Vue({ el: '#app', // components: { // "GridLayout": GridLayout, // "GridItem": GridItem // }, data: { layout: testLayout, draggable: true, resizable: true, index: 0 }, /* mounted: function () { this.index = this.layout.length; }, */ methods: { itemTitle(item) { var result = item.i; if (item.static) { result += " - Static"; } return result; } /* increaseWidth: function(item) { var width = document.getElementById("content").offsetWidth; width += 20; document.getElementById("content").style.width = width+"px"; }, decreaseWidth: function(item) { var width = document.getElementById("content").offsetWidth; width -= 20; document.getElementById("content").style.width = width+"px"; }, removeItem: function(item) { //console.log("### REMOVE " + item.i); this.layout.splice(this.layout.indexOf(item), 1); }, addItem: function() { var self = this; //console.log("### LENGTH: " + this.layout.length); var item = {"x":0,"y":0,"w":2,"h":2,"i":this.index+"", whatever: "bbb"}; this.index++; this.layout.push(item); } */ } }); /* function generateLayout() { return _.map(_.range(0, 25), function (item, i) { var y = Math.ceil(Math.random() * 4) + 1; return { x: _.random(0, 5) * 2 % 12, y: Math.floor(i / 6) * y, w: 2, h: y, i: i.toString(), static: Math.random() < 0.05 }; }); }*/ ================================================ FILE: website/docs/.vuepress/public/examples/02-events.html ================================================ Vue Grid Layout Example 2 - Move and resize events

Vue Grid Layout Example 2 - Move and resize events

View project on Github
Previous example: Basic
Next example: Multiple grids
Displayed as [x, y, w, h]:
{{item.i}}: [{{item.x}}, {{item.y}}, {{item.w}}, {{item.h}}]
Events:
{{event}}
{{item.i}}
================================================ FILE: website/docs/.vuepress/public/examples/02-events.js ================================================ var testLayout = [ {"x":0,"y":0,"w":2,"h":2,"i":"0"}, {"x":2,"y":0,"w":2,"h":4,"i":"1"}, {"x":4,"y":0,"w":2,"h":5,"i":"2"}, {"x":6,"y":0,"w":2,"h":3,"i":"3"}, {"x":8,"y":0,"w":2,"h":3,"i":"4"}, {"x":10,"y":0,"w":2,"h":3,"i":"5"}, {"x":0,"y":5,"w":2,"h":5,"i":"6"}, {"x":2,"y":5,"w":2,"h":5,"i":"7"}, {"x":4,"y":5,"w":2,"h":5,"i":"8"}, {"x":6,"y":4,"w":2,"h":4,"i":"9"}, {"x":8,"y":4,"w":2,"h":4,"i":"10"}, {"x":10,"y":4,"w":2,"h":4,"i":"11"}, {"x":0,"y":10,"w":2,"h":5,"i":"12"}, {"x":2,"y":10,"w":2,"h":5,"i":"13"}, {"x":4,"y":8,"w":2,"h":4,"i":"14"}, {"x":6,"y":8,"w":2,"h":4,"i":"15"}, {"x":8,"y":10,"w":2,"h":5,"i":"16"}, {"x":10,"y":4,"w":2,"h":2,"i":"17"}, {"x":0,"y":9,"w":2,"h":3,"i":"18"}, {"x":2,"y":6,"w":2,"h":2,"i":"19"} ]; new Vue({ el: '#app', data: { layout: testLayout, index: 0, eventLog: [] }, watch: { eventLog: function() { var eventsDiv = this.$refs.eventsDiv; eventsDiv.scrollTop = eventsDiv.scrollHeight; } }, methods: { moveEvent: function(i, newX, newY){ var msg = "MOVE i=" + i + ", X=" + newX + ", Y=" + newY; this.eventLog.push(msg); console.log(msg); }, movedEvent: function(i, newX, newY){ var msg = "MOVED i=" + i + ", X=" + newX + ", Y=" + newY; this.eventLog.push(msg); console.log(msg); }, resizeEvent: function(i, newH, newW, newHPx, newWPx){ var msg = "RESIZE i=" + i + ", H=" + newH + ", W=" + newW + ", H(px)=" + newHPx + ", W(px)=" + newWPx; this.eventLog.push(msg); console.log(msg); }, resizedEvent: function(i, newX, newY, newHPx, newWPx){ var msg = "RESIZED i=" + i + ", X=" + newX + ", Y=" + newY + ", H(px)=" + newHPx + ", W(px)=" + newWPx; this.eventLog.push(msg); console.log(msg); }, containerResizedEvent: function(i, newH, newW, newHPx, newWPx){ var msg = "CONTAINER RESIZED i=" + i + ", H=" + newH + ", W=" + newW + ", H(px)=" + newHPx + ", W(px)=" + newWPx; this.eventLog.push(msg); console.log(msg); }, /** * * @param i the item id/index * @param newH new height in grid rows * @param newW new width in grid columns * @param newHPx new height in pixels * @param newWPx new width in pixels * */ resizedEvent: function(i, newH, newW, newHPx, newWPx){ var msg = "RESIZED i=" + i + ", H=" + newH + ", W=" + newW + ", H(px)=" + newHPx + ", W(px)=" + newWPx; this.eventLog.push(msg); console.log(msg); }, layoutCreatedEvent: function(newLayout){ this.eventLog.push("Created layout"); console.log("Created layout: ", newLayout) }, layoutBeforeMountEvent: function(newLayout){ this.eventLog.push("beforeMount layout"); console.log("beforeMount layout: ", newLayout) }, layoutMountedEvent: function(newLayout){ this.eventLog.push("Mounted layout"); console.log("Mounted layout: ", newLayout) }, layoutReadyEvent: function(newLayout){ this.eventLog.push("Ready layout"); console.log("Ready layout: ", newLayout) }, layoutUpdatedEvent: function(newLayout){ this.eventLog.push("Updated layout"); console.log("Updated layout: ", newLayout) }, } }); ================================================ FILE: website/docs/.vuepress/public/examples/03-multiple-grids.html ================================================ Vue Grid Layout Example 3 - Multiple grids

Vue Grid Layout Example 3 - Multiple grids

View project on Github
Previous example: Move and resize events
Next example: Drag allow/ignore elements

Grid 1

Displayed as [x, y, w, h]:
{{item.i}}: [{{item.x}}, {{item.y}}, {{item.w}}, {{item.h}}]
{{item.i}}

Grid 2

Displayed as [x, y, w, h]:
{{item.i}}: [{{item.x}}, {{item.y}}, {{item.w}}, {{item.h}}]
{{item.i}}
================================================ FILE: website/docs/.vuepress/public/examples/04-allow-ignore.html ================================================ Vue Grid Layout Example 4 - Drag allow/ignore elements

Vue Grid Layout Example 4 - Drag allow/ignore elements

View project on Github
Previous example: Multiple grids
Next example: Mirrored grid layout

Ignore drag on certain elements and allow on on others.
Click and drag the dots on the corner of each item to reposition
Displayed as [x, y, w, h]:
{{item.i}}: [{{item.x}}, {{item.y}}, {{item.w}}, {{item.h}}]
{{item.i}}
================================================ FILE: website/docs/.vuepress/public/examples/05-mirrored.html ================================================ Vue Grid Layout Example 4 - Mirrored grid layout

Vue Grid Layout Example 5 - Mirrored grid layout

View project on Github
Previous example: Drag allow/ignore elements
Next example: Responsive
Displayed as [x, y, w, h]:
{{item.i}}: [{{item.x}}, {{item.y}}, {{item.w}}, {{item.h}}]
Draggable Resizable Mirrored
{{item.i}}
================================================ FILE: website/docs/.vuepress/public/examples/06-responsive.html ================================================ Vue Grid Layout Example 1 - Basic Responsive
Displayed as [x, y, w, h]:
{{item.i}}: [{{item.x}}, {{item.y}}, {{item.w}}, {{item.h}}]
Draggable Resizable Responsive
{{item.i}}
================================================ FILE: website/docs/.vuepress/public/examples/06-responsive.js ================================================ var testLayout = [ {"x":0,"y":0,"w":2,"h":2,"i":"0"}, {"x":2,"y":0,"w":2,"h":4,"i":"1"}, {"x":4,"y":0,"w":2,"h":5,"i":"2"}, {"x":6,"y":0,"w":2,"h":3,"i":"3"}, {"x":8,"y":0,"w":2,"h":3,"i":"4"}, {"x":10,"y":0,"w":2,"h":3,"i":"5"}, {"x":0,"y":5,"w":2,"h":5,"i":"6"}, {"x":2,"y":5,"w":2,"h":5,"i":"7"}, {"x":4,"y":5,"w":2,"h":5,"i":"8"}, {"x":6,"y":4,"w":2,"h":4,"i":"9"}, {"x":8,"y":4,"w":2,"h":4,"i":"10"}, {"x":10,"y":4,"w":2,"h":4,"i":"11"}, {"x":0,"y":10,"w":2,"h":5,"i":"12"}, {"x":2,"y":10,"w":2,"h":5,"i":"13"}, {"x":4,"y":8,"w":2,"h":4,"i":"14"}, {"x":6,"y":8,"w":2,"h":4,"i":"15"}, {"x":8,"y":10,"w":2,"h":5,"i":"16"}, {"x":10,"y":4,"w":2,"h":2,"i":"17"}, {"x":0,"y":9,"w":2,"h":3,"i":"18"}, {"x":2,"y":6,"w":2,"h":2,"i":"19"} ]; // var GridLayout = VueGridLayout.GridLayout; // var GridItem = VueGridLayout.GridItem; new Vue({ el: '#app', // components: { // "GridLayout": GridLayout, // "GridItem": GridItem // }, data: { layout: testLayout, draggable: true, resizable: true, responsive: true, index: 0, show: false, }, mounted: function () { this.index = this.layout.length; this.$nextTick(function () { this.show = true; }) }, /* methods: { increaseWidth: function(item) { var width = document.getElementById("content").offsetWidth; width += 20; document.getElementById("content").style.width = width+"px"; }, decreaseWidth: function(item) { var width = document.getElementById("content").offsetWidth; width -= 20; document.getElementById("content").style.width = width+"px"; }, removeItem: function(item) { //console.log("### REMOVE " + item.i); this.layout.splice(this.layout.indexOf(item), 1); }, addItem: function() { var self = this; //console.log("### LENGTH: " + this.layout.length); var item = {"x":0,"y":0,"w":2,"h":2,"i":this.index+"", whatever: "bbb"}; this.index++; this.layout.push(item); } } */ }); /* function generateLayout() { return _.map(_.range(0, 25), function (item, i) { var y = Math.ceil(Math.random() * 4) + 1; return { x: _.random(0, 5) * 2 % 12, y: Math.floor(i / 6) * y, w: 2, h: y, i: i.toString(), static: Math.random() < 0.05 }; }); }*/ ================================================ FILE: website/docs/.vuepress/public/examples/07-prevent-collision.html ================================================ Vue Grid Layout Example 7 - Prevent Collision
Displayed as [x, y, w, h]:
{{item.i}}: [{{item.x}}, {{item.y}}, {{item.w}}, {{item.h}}]

{{item.i}}
================================================ FILE: website/docs/.vuepress/public/examples/07-prevent-collision.js ================================================ var testLayout = [ {"x":0,"y":0,"w":2,"h":5,"i":"0", static: false}, {"x":2,"y":0,"w":2,"h":2,"i":"1", static: false}, {"x":4,"y":0,"w":2,"h":5,"i":"2", static: false}, {"x":6,"y":0,"w":2,"h":3,"i":"3", static: false}, {"x":8,"y":0,"w":2,"h":3,"i":"4", static: false}, {"x":10,"y":0,"w":2,"h":3,"i":"5", static: false}, {"x":0,"y":5,"w":2,"h":5,"i":"6", static: false}, {"x":2,"y":5,"w":2,"h":5,"i":"7", static: false}, {"x":4,"y":5,"w":2,"h":5,"i":"8", static: false}, {"x":6,"y":3,"w":2,"h":4,"i":"9", static: false}, {"x":8,"y":4,"w":2,"h":4,"i":"10", static: false}, {"x":10,"y":4,"w":2,"h":4,"i":"11", static: false}, {"x":0,"y":10,"w":2,"h":5,"i":"12", static: false}, {"x":2,"y":10,"w":2,"h":5,"i":"13", static: false}, {"x":4,"y":8,"w":2,"h":4,"i":"14", static: false}, {"x":6,"y":8,"w":2,"h":4,"i":"15", static: false}, {"x":8,"y":10,"w":2,"h":5,"i":"16", static: false}, {"x":10,"y":4,"w":2,"h":2,"i":"17", static: false}, {"x":0,"y":9,"w":2,"h":3,"i":"18", static: false}, {"x":2,"y":6,"w":2,"h":2,"i":"19", static: false} ]; // var GridLayout = VueGridLayout.GridLayout; // var GridItem = VueGridLayout.GridItem; new Vue({ el: '#app', // components: { // "GridLayout": GridLayout, // "GridItem": GridItem // }, data: { layout: testLayout, draggable: true, resizable: true, index: 0 }, /* mounted: function () { this.index = this.layout.length; }, */ methods: { itemTitle(item) { var result = item.i; if (item.static) { result += " - Static"; } return result; } } }); ================================================ FILE: website/docs/.vuepress/public/examples/08-responsive-predefined-layouts.html ================================================ Vue Grid Layout Example 8 - Responsive with predefined layouts

Vue Grid Layout Example 8 - Responsive with predefined layouts

View project on Github
Previous example: Prevent collision
Next example: Dynamic Add/Remove
Displayed as [x, y, w, h]:
{{item.i}}: [{{item.x}}, {{item.y}}, {{item.w}}, {{item.h}}]
Draggable Resizable Responsive
{{item.i}}
================================================ FILE: website/docs/.vuepress/public/examples/08-responsive-predefined-layouts.js ================================================ var testLayouts = { md: [ {"x":0, "y":0, "w":2, "h":2, "i":"0"}, {"x":2, "y":0, "w":2, "h":4, "i":"1"}, {"x":4, "y":0, "w":2, "h":5, "i":"2"}, {"x":6, "y":0, "w":2, "h":3, "i":"3"}, {"x":2, "y":4, "w":2, "h":3, "i":"4"}, {"x":4, "y":5, "w":2, "h":3, "i":"5"}, {"x":0, "y":2, "w":2, "h":5, "i":"6"}, {"x":2, "y":7, "w":2, "h":5, "i":"7"}, {"x":4, "y":8, "w":2, "h":5, "i":"8"}, {"x":6, "y":3, "w":2, "h":4, "i":"9"}, {"x":0, "y":7, "w":2, "h":4, "i":"10"}, {"x":2, "y":19, "w":2, "h":4, "i":"11"}, {"x":0, "y":14, "w":2, "h":5, "i":"12"}, {"x":2, "y":14, "w":2, "h":5, "i":"13"}, {"x":4, "y":13, "w":2, "h":4, "i":"14"}, {"x":6, "y":7, "w":2, "h":4, "i":"15"}, {"x":0, "y":19, "w":2, "h":5, "i":"16"}, {"x":8, "y":0, "w":2, "h":2, "i":"17"}, {"x":0, "y":11, "w":2, "h":3, "i":"18"}, {"x":2, "y":12, "w":2, "h":2, "i":"19"} ], lg: [ {"x":0,"y":0,"w":2,"h":2,"i":"0"}, {"x":2,"y":0,"w":2,"h":4,"i":"1"}, {"x":4,"y":0,"w":2,"h":5,"i":"2"}, {"x":6,"y":0,"w":2,"h":3,"i":"3"}, {"x":8,"y":0,"w":2,"h":3,"i":"4"}, {"x":10,"y":0,"w":2,"h":3,"i":"5"}, {"x":0,"y":5,"w":2,"h":5,"i":"6"}, {"x":2,"y":5,"w":2,"h":5,"i":"7"}, {"x":4,"y":5,"w":2,"h":5,"i":"8"}, {"x":6,"y":4,"w":2,"h":4,"i":"9"}, {"x":8,"y":4,"w":2,"h":4,"i":"10"}, {"x":10,"y":4,"w":2,"h":4,"i":"11"}, {"x":0,"y":10,"w":2,"h":5,"i":"12"}, {"x":2,"y":10,"w":2,"h":5,"i":"13"}, {"x":4,"y":8,"w":2,"h":4,"i":"14"}, {"x":6,"y":8,"w":2,"h":4,"i":"15"}, {"x":8,"y":10,"w":2,"h":5,"i":"16"}, {"x":10,"y":4,"w":2,"h":2,"i":"17"}, {"x":0,"y":9,"w":2,"h":3,"i":"18"}, {"x":2,"y":6,"w":2,"h":2,"i":"19"} ], }; // var GridLayout = VueGridLayout.GridLayout; // var GridItem = VueGridLayout.GridItem; new Vue({ el: '#app', // components: { // "GridLayout": GridLayout, // "GridItem": GridItem // }, data: { layouts: testLayouts, layout: testLayouts["lg"], draggable: true, resizable: true, responsive: true, index: 0 }, mounted: function () { // this.index = this.layout.length; }, methods: { breakpointChangedEvent: function(newBreakpoint, newLayout){ console.log("BREAKPOINT CHANGED breakpoint=", newBreakpoint, ", layout: ", newLayout ); } } }); ================================================ FILE: website/docs/.vuepress/public/examples/09-dynamic-add-remove.html ================================================ Vue Grid Layout Example 9 - Dynamic Add/Remove
Displayed as [x, y, w, h]:
{{item.i}}: [{{item.x}}, {{item.y}}, {{item.w}}, {{item.h}}]
Draggable Resizable
{{item.i}} x
================================================ FILE: website/docs/.vuepress/public/examples/09-dynamic-add-remove.js ================================================ var testLayout = [ { x: 0, y: 0, w: 2, h: 2, i: "0" }, { x: 2, y: 0, w: 2, h: 2, i: "1" }, { x: 4, y: 0, w: 2, h: 2, i: "2" }, { x: 6, y: 0, w: 2, h: 2, i: "3" }, { x: 8, y: 0, w: 2, h: 2, i: "4" }, ]; // var GridLayout = VueGridLayout.GridLayout; // var GridItem = VueGridLayout.GridItem; new Vue({ el: "#app", // components: { // "GridLayout": GridLayout, // "GridItem": GridItem // }, data: { layout: testLayout, draggable: true, resizable: true, responsive: true, colNum: 12, index: 0, }, mounted: function () { this.index = this.layout.length; }, methods: { addItem: function () { // Add a new item. It must have a unique key! this.layout.push({ x: (this.layout.length * 2) % (this.colNum || 12), y: this.layout.length + (this.colNum || 12), // puts it at the bottom w: 2, h: 2, i: this.index, }); // Increment the counter to ensure key is always unique. this.index++; }, removeItem: function (val) { const index = this.layout.map(item => item.i).indexOf(val); this.layout.splice(index, 1); }, }, }); ================================================ FILE: website/docs/.vuepress/public/examples/10-drag-from-outside.html ================================================ Vue Grid Layout Example 10 - Drag From Outside

Vue Grid Layout Example 09 - Drag From Outside

View project on Github
Previous example: Dynamic Add/Remove
Next example: Bounded
This demo shows what happens when an item is added from outside of the grid.

Once you drop the item within the grid you'll get its coordinates/properties and can perform actions with it accordingly.

Displayed as [x, y, w, h]:
{{item.i}}: [{{item.x}}, {{item.y}}, {{item.w}}, {{item.h}}]

Droppable Element (Drag me!)
{{item.i}}
================================================ FILE: website/docs/.vuepress/public/examples/10-drag-from-outside.js ================================================ var testLayout = [ {"x":0,"y":0,"w":2,"h":2,"i":"0"}, {"x":2,"y":0,"w":2,"h":4,"i":"1"}, {"x":4,"y":0,"w":2,"h":5,"i":"2"}, {"x":6,"y":0,"w":2,"h":3,"i":"3"}, {"x":8,"y":0,"w":2,"h":3,"i":"4"}, {"x":10,"y":0,"w":2,"h":3,"i":"5"}, {"x":0,"y":5,"w":2,"h":5,"i":"6"}, {"x":2,"y":5,"w":2,"h":5,"i":"7"}, {"x":4,"y":5,"w":2,"h":5,"i":"8"}, {"x":5,"y":10,"w":4,"h":3,"i":"9"}, ]; var mouseXY={"x":null,"y":null}; var DragPos = {"x":null,"y":null,"w":1,"h":1,"i":null}; document.addEventListener("dragover", function(e) { mouseXY.x=e.clientX; mouseXY.y=e.clientY; }, false); new Vue({ el: '#app', data: { layout: testLayout, }, methods: { drag:function(e){ let parentRect = document.getElementById('content').getBoundingClientRect(); let mouseInGrid=false; if (((mouseXY.x>parentRect.left) && (mouseXY.xparentRect.top) && (mouseXY.y item.i === 'drop')) == -1){ this.layout.push({ x: (this.layout.length * 2) % (this.colNum || 12), y: this.layout.length + (this.colNum || 12), // puts it at the bottom w: 1, h: 1, i: 'drop', }); } let index=this.layout.findIndex(item => item.i === 'drop'); if (index!=-1){ try { this.$refs.gridLayout.$children[this.layout.length].$refs.item.style.display="none"; } catch { } let el=this.$refs.gridLayout.$children[index]; el.dragging={"top":mouseXY.y-parentRect.top,"left":mouseXY.x-parentRect.left}; let new_pos=el.calcXY(mouseXY.y-parentRect.top, mouseXY.x-parentRect.left); if (mouseInGrid==true){ this.$refs.gridLayout.dragEvent('dragstart', 'drop', new_pos.x,new_pos.y,1,1); DragPos.i=String(index); DragPos.x=this.layout[index].x; DragPos.y=this.layout[index].y; } if (mouseInGrid==false){ this.$refs.gridLayout.dragEvent('dragend', 'drop', new_pos.x,new_pos.y,1,1); this.layout = this.layout.filter(obj => obj.i !=='drop'); } } }, dragend:function(e){ let parentRect = document.getElementById('content').getBoundingClientRect(); let mouseInGrid=false; if (((mouseXY.x>parentRect.left) && (mouseXY.xparentRect.top) && (mouseXY.y obj.i !=='drop'); // UNCOMMENT below if you want to add a grid-item /* this.layout.push({ x: DragPos.x, y: DragPos.y, w: 1, h: 1, i: DragPos.i, }); this.$refs.gridLayout.dragEvent('dragend', DragPos.i, DragPos.x,DragPos.y,1,1); try { this.$refs.gridLayout.$children[this.layout.length].$refs.item.style.display="block"; } catch { } */ } }, }, }); ================================================ FILE: website/docs/.vuepress/public/examples/11-bounded.html ================================================ Vue Grid Layout Example 11 - Bounded

Vue Grid Layout Example 11 - Bounded

View project on Github
Previous example: Drag From Outside
Displayed as [x, y, w, h]:
{{item.i}}: [{{item.x}}, {{item.y}}, {{item.w}}, {{item.h}}]
Draggable Resizable Bounded
{{item.i}}
================================================ FILE: website/docs/.vuepress/public/examples/11-bounded.js ================================================ var testLayout = [ {"x":0,"y":0,"w":2,"h":2,"i":"0"}, {"x":2,"y":0,"w":2,"h":4,"i":"1"}, {"x":4,"y":0,"w":2,"h":5,"i":"2"}, {"x":6,"y":0,"w":2,"h":3,"i":"3"}, {"x":8,"y":0,"w":2,"h":3,"i":"4"}, {"x":10,"y":0,"w":2,"h":3,"i":"5"}, {"x":0,"y":5,"w":2,"h":5,"i":"6"}, {"x":2,"y":5,"w":2,"h":5,"i":"7"}, {"x":4,"y":5,"w":2,"h":5,"i":"8"}, {"x":6,"y":4,"w":2,"h":4,"i":"9"}, {"x":8,"y":4,"w":2,"h":4,"i":"10"}, {"x":10,"y":4,"w":2,"h":4,"i":"11"}, {"x":0,"y":10,"w":2,"h":5,"i":"12"}, {"x":2,"y":10,"w":2,"h":5,"i":"13"}, {"x":4,"y":8,"w":2,"h":4,"i":"14"}, {"x":6,"y":8,"w":2,"h":4,"i":"15"}, {"x":8,"y":10,"w":2,"h":5,"i":"16"}, {"x":10,"y":4,"w":2,"h":2,"i":"17"}, {"x":0,"y":9,"w":2,"h":3,"i":"18"}, {"x":2,"y":6,"w":2,"h":2,"i":"19"} ]; new Vue({ el: '#app', data: { layout: testLayout, draggable: true, resizable: true, bounded: true } }); ================================================ FILE: website/docs/.vuepress/public/examples/app.css ================================================ /*** EXAMPLE ***/ #content { width: 100%; } .vue-grid-layout { background: #eee; } .layoutJSON { background: #ddd; border: 1px solid black; margin-top: 10px; padding: 10px; } .eventsJSON { background: #ddd; border: 1px solid black; margin-top: 10px; padding: 10px; height: 100px; overflow-y: scroll; } .columns { -moz-columns: 120px; -webkit-columns: 120px; columns: 120px; } /*.vue-resizable-handle { z-index: 5000; position: absolute; width: 20px; height: 20px; bottom: 0; right: 0; background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pg08IS0tIEdlbmVyYXRvcjogQWRvYmUgRmlyZXdvcmtzIENTNiwgRXhwb3J0IFNWRyBFeHRlbnNpb24gYnkgQWFyb24gQmVhbGwgKGh0dHA6Ly9maXJld29ya3MuYWJlYWxsLmNvbSkgLiBWZXJzaW9uOiAwLjYuMSAgLS0+DTwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DTxzdmcgaWQ9IlVudGl0bGVkLVBhZ2UlMjAxIiB2aWV3Qm94PSIwIDAgNiA2IiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjojZmZmZmZmMDAiIHZlcnNpb249IjEuMSINCXhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbDpzcGFjZT0icHJlc2VydmUiDQl4PSIwcHgiIHk9IjBweCIgd2lkdGg9IjZweCIgaGVpZ2h0PSI2cHgiDT4NCTxnIG9wYWNpdHk9IjAuMzAyIj4NCQk8cGF0aCBkPSJNIDYgNiBMIDAgNiBMIDAgNC4yIEwgNCA0LjIgTCA0LjIgNC4yIEwgNC4yIDAgTCA2IDAgTCA2IDYgTCA2IDYgWiIgZmlsbD0iIzAwMDAwMCIvPg0JPC9nPg08L3N2Zz4='); background-position: bottom right; padding: 0 3px 3px 0; background-repeat: no-repeat; background-origin: content-box; box-sizing: border-box; cursor: se-resize; }*/ .vue-grid-item:not(.vue-grid-placeholder) { background: #ccc; border: 1px solid black; } .vue-grid-item.resizing { opacity: 0.9; } .vue-grid-item.static { background: #cce; } .vue-grid-item .text { font-size: 24px; text-align: center; position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto; height: 100%; width: 100%; } .vue-grid-item .no-drag { height: 100%; width: 100%; } .vue-grid-item .minMax { font-size: 12px; } .vue-grid-item .add { cursor: pointer; } .vue-draggable-handle { position: absolute; width: 20px; height: 20px; top: 0; left: 0; background: url("data:image/svg+xml;utf8,") no-repeat; background-position: bottom right; padding: 0 8px 8px 0; background-repeat: no-repeat; background-origin: content-box; box-sizing: border-box; cursor: pointer; } ================================================ FILE: website/docs/.vuepress/public/examples/vue.js ================================================ /*! * Vue.js v2.6.7 * (c) 2014-2019 Evan You * Released under the MIT License. */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = global || self, global.Vue = factory()); }(this, function () { 'use strict'; /* */ var emptyObject = Object.freeze({}); // These helpers produce better VM code in JS engines due to their // explicitness and function inlining. function isUndef (v) { return v === undefined || v === null } function isDef (v) { return v !== undefined && v !== null } function isTrue (v) { return v === true } function isFalse (v) { return v === false } /** * Check if value is primitive. */ function isPrimitive (value) { return ( typeof value === 'string' || typeof value === 'number' || // $flow-disable-line typeof value === 'symbol' || typeof value === 'boolean' ) } /** * Quick object check - this is primarily used to tell * Objects from primitive values when we know the value * is a JSON-compliant type. */ function isObject (obj) { return obj !== null && typeof obj === 'object' } /** * Get the raw type string of a value, e.g., [object Object]. */ var _toString = Object.prototype.toString; function toRawType (value) { return _toString.call(value).slice(8, -1) } /** * Strict object type check. Only returns true * for plain JavaScript objects. */ function isPlainObject (obj) { return _toString.call(obj) === '[object Object]' } function isRegExp (v) { return _toString.call(v) === '[object RegExp]' } /** * Check if val is a valid array index. */ function isValidArrayIndex (val) { var n = parseFloat(String(val)); return n >= 0 && Math.floor(n) === n && isFinite(val) } function isPromise (val) { return ( isDef(val) && typeof val.then === 'function' && typeof val.catch === 'function' ) } /** * Convert a value to a string that is actually rendered. */ function toString (val) { return val == null ? '' : Array.isArray(val) || (isPlainObject(val) && val.toString === _toString) ? JSON.stringify(val, null, 2) : String(val) } /** * Convert an input value to a number for persistence. * If the conversion fails, return original string. */ function toNumber (val) { var n = parseFloat(val); return isNaN(n) ? val : n } /** * Make a map and return a function for checking if a key * is in that map. */ function makeMap ( str, expectsLowerCase ) { var map = Object.create(null); var list = str.split(','); for (var i = 0; i < list.length; i++) { map[list[i]] = true; } return expectsLowerCase ? function (val) { return map[val.toLowerCase()]; } : function (val) { return map[val]; } } /** * Check if a tag is a built-in tag. */ var isBuiltInTag = makeMap('slot,component', true); /** * Check if an attribute is a reserved attribute. */ var isReservedAttribute = makeMap('key,ref,slot,slot-scope,is'); /** * Remove an item from an array. */ function remove (arr, item) { if (arr.length) { var index = arr.indexOf(item); if (index > -1) { return arr.splice(index, 1) } } } /** * Check whether an object has the property. */ var hasOwnProperty = Object.prototype.hasOwnProperty; function hasOwn (obj, key) { return hasOwnProperty.call(obj, key) } /** * Create a cached version of a pure function. */ function cached (fn) { var cache = Object.create(null); return (function cachedFn (str) { var hit = cache[str]; return hit || (cache[str] = fn(str)) }) } /** * Camelize a hyphen-delimited string. */ var camelizeRE = /-(\w)/g; var camelize = cached(function (str) { return str.replace(camelizeRE, function (_, c) { return c ? c.toUpperCase() : ''; }) }); /** * Capitalize a string. */ var capitalize = cached(function (str) { return str.charAt(0).toUpperCase() + str.slice(1) }); /** * Hyphenate a camelCase string. */ var hyphenateRE = /\B([A-Z])/g; var hyphenate = cached(function (str) { return str.replace(hyphenateRE, '-$1').toLowerCase() }); /** * Simple bind polyfill for environments that do not support it, * e.g., PhantomJS 1.x. Technically, we don't need this anymore * since native bind is now performant enough in most browsers. * But removing it would mean breaking code that was able to run in * PhantomJS 1.x, so this must be kept for backward compatibility. */ /* istanbul ignore next */ function polyfillBind (fn, ctx) { function boundFn (a) { var l = arguments.length; return l ? l > 1 ? fn.apply(ctx, arguments) : fn.call(ctx, a) : fn.call(ctx) } boundFn._length = fn.length; return boundFn } function nativeBind (fn, ctx) { return fn.bind(ctx) } var bind = Function.prototype.bind ? nativeBind : polyfillBind; /** * Convert an Array-like object to a real Array. */ function toArray (list, start) { start = start || 0; var i = list.length - start; var ret = new Array(i); while (i--) { ret[i] = list[i + start]; } return ret } /** * Mix properties into target object. */ function extend (to, _from) { for (var key in _from) { to[key] = _from[key]; } return to } /** * Merge an Array of Objects into a single Object. */ function toObject (arr) { var res = {}; for (var i = 0; i < arr.length; i++) { if (arr[i]) { extend(res, arr[i]); } } return res } /* eslint-disable no-unused-vars */ /** * Perform no operation. * Stubbing args to make Flow happy without leaving useless transpiled code * with ...rest (https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/). */ function noop (a, b, c) {} /** * Always return false. */ var no = function (a, b, c) { return false; }; /* eslint-enable no-unused-vars */ /** * Return the same value. */ var identity = function (_) { return _; }; /** * Generate a string containing static keys from compiler modules. */ function genStaticKeys (modules) { return modules.reduce(function (keys, m) { return keys.concat(m.staticKeys || []) }, []).join(',') } /** * Check if two values are loosely equal - that is, * if they are plain objects, do they have the same shape? */ function looseEqual (a, b) { if (a === b) { return true } var isObjectA = isObject(a); var isObjectB = isObject(b); if (isObjectA && isObjectB) { try { var isArrayA = Array.isArray(a); var isArrayB = Array.isArray(b); if (isArrayA && isArrayB) { return a.length === b.length && a.every(function (e, i) { return looseEqual(e, b[i]) }) } else if (a instanceof Date && b instanceof Date) { return a.getTime() === b.getTime() } else if (!isArrayA && !isArrayB) { var keysA = Object.keys(a); var keysB = Object.keys(b); return keysA.length === keysB.length && keysA.every(function (key) { return looseEqual(a[key], b[key]) }) } else { /* istanbul ignore next */ return false } } catch (e) { /* istanbul ignore next */ return false } } else if (!isObjectA && !isObjectB) { return String(a) === String(b) } else { return false } } /** * Return the first index at which a loosely equal value can be * found in the array (if value is a plain object, the array must * contain an object of the same shape), or -1 if it is not present. */ function looseIndexOf (arr, val) { for (var i = 0; i < arr.length; i++) { if (looseEqual(arr[i], val)) { return i } } return -1 } /** * Ensure a function is called only once. */ function once (fn) { var called = false; return function () { if (!called) { called = true; fn.apply(this, arguments); } } } var SSR_ATTR = 'data-server-rendered'; var ASSET_TYPES = [ 'component', 'directive', 'filter' ]; var LIFECYCLE_HOOKS = [ 'beforeCreate', 'created', 'beforeMount', 'mounted', 'beforeUpdate', 'updated', 'beforeDestroy', 'destroyed', 'activated', 'deactivated', 'errorCaptured', 'serverPrefetch' ]; /* */ var config = ({ /** * Option merge strategies (used in core/util/options) */ // $flow-disable-line optionMergeStrategies: Object.create(null), /** * Whether to suppress warnings. */ silent: false, /** * Show production mode tip message on boot? */ productionTip: "development" !== 'production', /** * Whether to enable devtools */ devtools: "development" !== 'production', /** * Whether to record perf */ performance: false, /** * Error handler for watcher errors */ errorHandler: null, /** * Warn handler for watcher warns */ warnHandler: null, /** * Ignore certain custom elements */ ignoredElements: [], /** * Custom user key aliases for v-on */ // $flow-disable-line keyCodes: Object.create(null), /** * Check if a tag is reserved so that it cannot be registered as a * component. This is platform-dependent and may be overwritten. */ isReservedTag: no, /** * Check if an attribute is reserved so that it cannot be used as a component * prop. This is platform-dependent and may be overwritten. */ isReservedAttr: no, /** * Check if a tag is an unknown element. * Platform-dependent. */ isUnknownElement: no, /** * Get the namespace of an element */ getTagNamespace: noop, /** * Parse the real tag name for the specific platform. */ parsePlatformTagName: identity, /** * Check if an attribute must be bound using property, e.g. value * Platform-dependent. */ mustUseProp: no, /** * Perform updates asynchronously. Intended to be used by Vue Test Utils * This will significantly reduce performance if set to false. */ async: true, /** * Exposed for legacy reasons */ _lifecycleHooks: LIFECYCLE_HOOKS }); /* */ /** * unicode letters used for parsing html tags, component names and property paths. * using https://www.w3.org/TR/html53/semantics-scripting.html#potentialcustomelementname * skipping \u10000-\uEFFFF due to it freezing up PhantomJS */ var unicodeLetters = 'a-zA-Z\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD'; /** * Check if a string starts with $ or _ */ function isReserved (str) { var c = (str + '').charCodeAt(0); return c === 0x24 || c === 0x5F } /** * Define a property. */ function def (obj, key, val, enumerable) { Object.defineProperty(obj, key, { value: val, enumerable: !!enumerable, writable: true, configurable: true }); } /** * Parse simple path. */ var bailRE = new RegExp(("[^" + unicodeLetters + ".$_\\d]")); function parsePath (path) { if (bailRE.test(path)) { return } var segments = path.split('.'); return function (obj) { for (var i = 0; i < segments.length; i++) { if (!obj) { return } obj = obj[segments[i]]; } return obj } } /* */ // can we use __proto__? var hasProto = '__proto__' in {}; // Browser environment sniffing var inBrowser = typeof window !== 'undefined'; var inWeex = typeof WXEnvironment !== 'undefined' && !!WXEnvironment.platform; var weexPlatform = inWeex && WXEnvironment.platform.toLowerCase(); var UA = inBrowser && window.navigator.userAgent.toLowerCase(); var isIE = UA && /msie|trident/.test(UA); var isIE9 = UA && UA.indexOf('msie 9.0') > 0; var isEdge = UA && UA.indexOf('edge/') > 0; var isAndroid = (UA && UA.indexOf('android') > 0) || (weexPlatform === 'android'); var isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios'); var isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge; var isPhantomJS = UA && /phantomjs/.test(UA); var isFF = UA && UA.match(/firefox\/(\d+)/); // Firefox has a "watch" function on Object.prototype... var nativeWatch = ({}).watch; var supportsPassive = false; if (inBrowser) { try { var opts = {}; Object.defineProperty(opts, 'passive', ({ get: function get () { /* istanbul ignore next */ supportsPassive = true; } })); // https://github.com/facebook/flow/issues/285 window.addEventListener('test-passive', null, opts); } catch (e) {} } // this needs to be lazy-evaled because vue may be required before // vue-server-renderer can set VUE_ENV var _isServer; var isServerRendering = function () { if (_isServer === undefined) { /* istanbul ignore if */ if (!inBrowser && !inWeex && typeof global !== 'undefined') { // detect presence of vue-server-renderer and avoid // Webpack shimming the process _isServer = global['process'] && global['process'].env.VUE_ENV === 'server'; } else { _isServer = false; } } return _isServer }; // detect devtools var devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__; /* istanbul ignore next */ function isNative (Ctor) { return typeof Ctor === 'function' && /native code/.test(Ctor.toString()) } var hasSymbol = typeof Symbol !== 'undefined' && isNative(Symbol) && typeof Reflect !== 'undefined' && isNative(Reflect.ownKeys); var _Set; /* istanbul ignore if */ // $flow-disable-line if (typeof Set !== 'undefined' && isNative(Set)) { // use native Set when available. _Set = Set; } else { // a non-standard Set polyfill that only works with primitive keys. _Set = /*@__PURE__*/(function () { function Set () { this.set = Object.create(null); } Set.prototype.has = function has (key) { return this.set[key] === true }; Set.prototype.add = function add (key) { this.set[key] = true; }; Set.prototype.clear = function clear () { this.set = Object.create(null); }; return Set; }()); } /* */ var warn = noop; var tip = noop; var generateComponentTrace = (noop); // work around flow check var formatComponentName = (noop); { var hasConsole = typeof console !== 'undefined'; var classifyRE = /(?:^|[-_])(\w)/g; var classify = function (str) { return str .replace(classifyRE, function (c) { return c.toUpperCase(); }) .replace(/[-_]/g, ''); }; warn = function (msg, vm) { var trace = vm ? generateComponentTrace(vm) : ''; if (config.warnHandler) { config.warnHandler.call(null, msg, vm, trace); } else if (hasConsole && (!config.silent)) { console.error(("[Vue warn]: " + msg + trace)); } }; tip = function (msg, vm) { if (hasConsole && (!config.silent)) { console.warn("[Vue tip]: " + msg + ( vm ? generateComponentTrace(vm) : '' )); } }; formatComponentName = function (vm, includeFile) { if (vm.$root === vm) { return '' } var options = typeof vm === 'function' && vm.cid != null ? vm.options : vm._isVue ? vm.$options || vm.constructor.options : vm; var name = options.name || options._componentTag; var file = options.__file; if (!name && file) { var match = file.match(/([^/\\]+)\.vue$/); name = match && match[1]; } return ( (name ? ("<" + (classify(name)) + ">") : "") + (file && includeFile !== false ? (" at " + file) : '') ) }; var repeat = function (str, n) { var res = ''; while (n) { if (n % 2 === 1) { res += str; } if (n > 1) { str += str; } n >>= 1; } return res }; generateComponentTrace = function (vm) { if (vm._isVue && vm.$parent) { var tree = []; var currentRecursiveSequence = 0; while (vm) { if (tree.length > 0) { var last = tree[tree.length - 1]; if (last.constructor === vm.constructor) { currentRecursiveSequence++; vm = vm.$parent; continue } else if (currentRecursiveSequence > 0) { tree[tree.length - 1] = [last, currentRecursiveSequence]; currentRecursiveSequence = 0; } } tree.push(vm); vm = vm.$parent; } return '\n\nfound in\n\n' + tree .map(function (vm, i) { return ("" + (i === 0 ? '---> ' : repeat(' ', 5 + i * 2)) + (Array.isArray(vm) ? ((formatComponentName(vm[0])) + "... (" + (vm[1]) + " recursive calls)") : formatComponentName(vm))); }) .join('\n') } else { return ("\n\n(found in " + (formatComponentName(vm)) + ")") } }; } /* */ var uid = 0; /** * A dep is an observable that can have multiple * directives subscribing to it. */ var Dep = function Dep () { this.id = uid++; this.subs = []; }; Dep.prototype.addSub = function addSub (sub) { this.subs.push(sub); }; Dep.prototype.removeSub = function removeSub (sub) { remove(this.subs, sub); }; Dep.prototype.depend = function depend () { if (Dep.target) { Dep.target.addDep(this); } }; Dep.prototype.notify = function notify () { // stabilize the subscriber list first var subs = this.subs.slice(); if (!config.async) { // subs aren't sorted in scheduler if not running async // we need to sort them now to make sure they fire in correct // order subs.sort(function (a, b) { return a.id - b.id; }); } for (var i = 0, l = subs.length; i < l; i++) { subs[i].update(); } }; // The current target watcher being evaluated. // This is globally unique because only one watcher // can be evaluated at a time. Dep.target = null; var targetStack = []; function pushTarget (target) { targetStack.push(target); Dep.target = target; } function popTarget () { targetStack.pop(); Dep.target = targetStack[targetStack.length - 1]; } /* */ var VNode = function VNode ( tag, data, children, text, elm, context, componentOptions, asyncFactory ) { this.tag = tag; this.data = data; this.children = children; this.text = text; this.elm = elm; this.ns = undefined; this.context = context; this.fnContext = undefined; this.fnOptions = undefined; this.fnScopeId = undefined; this.key = data && data.key; this.componentOptions = componentOptions; this.componentInstance = undefined; this.parent = undefined; this.raw = false; this.isStatic = false; this.isRootInsert = true; this.isComment = false; this.isCloned = false; this.isOnce = false; this.asyncFactory = asyncFactory; this.asyncMeta = undefined; this.isAsyncPlaceholder = false; }; var prototypeAccessors = { child: { configurable: true } }; // DEPRECATED: alias for componentInstance for backwards compat. /* istanbul ignore next */ prototypeAccessors.child.get = function () { return this.componentInstance }; Object.defineProperties( VNode.prototype, prototypeAccessors ); var createEmptyVNode = function (text) { if ( text === void 0 ) text = ''; var node = new VNode(); node.text = text; node.isComment = true; return node }; function createTextVNode (val) { return new VNode(undefined, undefined, undefined, String(val)) } // optimized shallow clone // used for static nodes and slot nodes because they may be reused across // multiple renders, cloning them avoids errors when DOM manipulations rely // on their elm reference. function cloneVNode (vnode) { var cloned = new VNode( vnode.tag, vnode.data, // #7975 // clone children array to avoid mutating original in case of cloning // a child. vnode.children && vnode.children.slice(), vnode.text, vnode.elm, vnode.context, vnode.componentOptions, vnode.asyncFactory ); cloned.ns = vnode.ns; cloned.isStatic = vnode.isStatic; cloned.key = vnode.key; cloned.isComment = vnode.isComment; cloned.fnContext = vnode.fnContext; cloned.fnOptions = vnode.fnOptions; cloned.fnScopeId = vnode.fnScopeId; cloned.asyncMeta = vnode.asyncMeta; cloned.isCloned = true; return cloned } /* * not type checking this file because flow doesn't play well with * dynamically accessing methods on Array prototype */ var arrayProto = Array.prototype; var arrayMethods = Object.create(arrayProto); var methodsToPatch = [ 'push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse' ]; /** * Intercept mutating methods and emit events */ methodsToPatch.forEach(function (method) { // cache original method var original = arrayProto[method]; def(arrayMethods, method, function mutator () { var args = [], len = arguments.length; while ( len-- ) args[ len ] = arguments[ len ]; var result = original.apply(this, args); var ob = this.__ob__; var inserted; switch (method) { case 'push': case 'unshift': inserted = args; break case 'splice': inserted = args.slice(2); break } if (inserted) { ob.observeArray(inserted); } // notify change ob.dep.notify(); return result }); }); /* */ var arrayKeys = Object.getOwnPropertyNames(arrayMethods); /** * In some cases we may want to disable observation inside a component's * update computation. */ var shouldObserve = true; function toggleObserving (value) { shouldObserve = value; } /** * Observer class that is attached to each observed * object. Once attached, the observer converts the target * object's property keys into getter/setters that * collect dependencies and dispatch updates. */ var Observer = function Observer (value) { this.value = value; this.dep = new Dep(); this.vmCount = 0; def(value, '__ob__', this); if (Array.isArray(value)) { if (hasProto) { protoAugment(value, arrayMethods); } else { copyAugment(value, arrayMethods, arrayKeys); } this.observeArray(value); } else { this.walk(value); } }; /** * Walk through all properties and convert them into * getter/setters. This method should only be called when * value type is Object. */ Observer.prototype.walk = function walk (obj) { var keys = Object.keys(obj); for (var i = 0; i < keys.length; i++) { defineReactive$$1(obj, keys[i]); } }; /** * Observe a list of Array items. */ Observer.prototype.observeArray = function observeArray (items) { for (var i = 0, l = items.length; i < l; i++) { observe(items[i]); } }; // helpers /** * Augment a target Object or Array by intercepting * the prototype chain using __proto__ */ function protoAugment (target, src) { /* eslint-disable no-proto */ target.__proto__ = src; /* eslint-enable no-proto */ } /** * Augment a target Object or Array by defining * hidden properties. */ /* istanbul ignore next */ function copyAugment (target, src, keys) { for (var i = 0, l = keys.length; i < l; i++) { var key = keys[i]; def(target, key, src[key]); } } /** * Attempt to create an observer instance for a value, * returns the new observer if successfully observed, * or the existing observer if the value already has one. */ function observe (value, asRootData) { if (!isObject(value) || value instanceof VNode) { return } var ob; if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) { ob = value.__ob__; } else if ( shouldObserve && !isServerRendering() && (Array.isArray(value) || isPlainObject(value)) && Object.isExtensible(value) && !value._isVue ) { ob = new Observer(value); } if (asRootData && ob) { ob.vmCount++; } return ob } /** * Define a reactive property on an Object. */ function defineReactive$$1 ( obj, key, val, customSetter, shallow ) { var dep = new Dep(); var property = Object.getOwnPropertyDescriptor(obj, key); if (property && property.configurable === false) { return } // cater for pre-defined getter/setters var getter = property && property.get; var setter = property && property.set; if ((!getter || setter) && arguments.length === 2) { val = obj[key]; } var childOb = !shallow && observe(val); Object.defineProperty(obj, key, { enumerable: true, configurable: true, get: function reactiveGetter () { var value = getter ? getter.call(obj) : val; if (Dep.target) { dep.depend(); if (childOb) { childOb.dep.depend(); if (Array.isArray(value)) { dependArray(value); } } } return value }, set: function reactiveSetter (newVal) { var value = getter ? getter.call(obj) : val; /* eslint-disable no-self-compare */ if (newVal === value || (newVal !== newVal && value !== value)) { return } /* eslint-enable no-self-compare */ if (customSetter) { customSetter(); } // #7981: for accessor properties without setter if (getter && !setter) { return } if (setter) { setter.call(obj, newVal); } else { val = newVal; } childOb = !shallow && observe(newVal); dep.notify(); } }); } /** * Set a property on an object. Adds the new property and * triggers change notification if the property doesn't * already exist. */ function set (target, key, val) { if (isUndef(target) || isPrimitive(target) ) { warn(("Cannot set reactive property on undefined, null, or primitive value: " + ((target)))); } if (Array.isArray(target) && isValidArrayIndex(key)) { target.length = Math.max(target.length, key); target.splice(key, 1, val); return val } if (key in target && !(key in Object.prototype)) { target[key] = val; return val } var ob = (target).__ob__; if (target._isVue || (ob && ob.vmCount)) { warn( 'Avoid adding reactive properties to a Vue instance or its root $data ' + 'at runtime - declare it upfront in the data option.' ); return val } if (!ob) { target[key] = val; return val } defineReactive$$1(ob.value, key, val); ob.dep.notify(); return val } /** * Delete a property and trigger change if necessary. */ function del (target, key) { if (isUndef(target) || isPrimitive(target) ) { warn(("Cannot delete reactive property on undefined, null, or primitive value: " + ((target)))); } if (Array.isArray(target) && isValidArrayIndex(key)) { target.splice(key, 1); return } var ob = (target).__ob__; if (target._isVue || (ob && ob.vmCount)) { warn( 'Avoid deleting properties on a Vue instance or its root $data ' + '- just set it to null.' ); return } if (!hasOwn(target, key)) { return } delete target[key]; if (!ob) { return } ob.dep.notify(); } /** * Collect dependencies on array elements when the array is touched, since * we cannot intercept array element access like property getters. */ function dependArray (value) { for (var e = (void 0), i = 0, l = value.length; i < l; i++) { e = value[i]; e && e.__ob__ && e.__ob__.dep.depend(); if (Array.isArray(e)) { dependArray(e); } } } /* */ /** * Option overwriting strategies are functions that handle * how to merge a parent option value and a child option * value into the final value. */ var strats = config.optionMergeStrategies; /** * Options with restrictions */ { strats.el = strats.propsData = function (parent, child, vm, key) { if (!vm) { warn( "option \"" + key + "\" can only be used during instance " + 'creation with the `new` keyword.' ); } return defaultStrat(parent, child) }; } /** * Helper that recursively merges two data objects together. */ function mergeData (to, from) { if (!from) { return to } var key, toVal, fromVal; var keys = hasSymbol ? Reflect.ownKeys(from) : Object.keys(from); for (var i = 0; i < keys.length; i++) { key = keys[i]; // in case the object is already observed... if (key === '__ob__') { continue } toVal = to[key]; fromVal = from[key]; if (!hasOwn(to, key)) { set(to, key, fromVal); } else if ( toVal !== fromVal && isPlainObject(toVal) && isPlainObject(fromVal) ) { mergeData(toVal, fromVal); } } return to } /** * Data */ function mergeDataOrFn ( parentVal, childVal, vm ) { if (!vm) { // in a Vue.extend merge, both should be functions if (!childVal) { return parentVal } if (!parentVal) { return childVal } // when parentVal & childVal are both present, // we need to return a function that returns the // merged result of both functions... no need to // check if parentVal is a function here because // it has to be a function to pass previous merges. return function mergedDataFn () { return mergeData( typeof childVal === 'function' ? childVal.call(this, this) : childVal, typeof parentVal === 'function' ? parentVal.call(this, this) : parentVal ) } } else { return function mergedInstanceDataFn () { // instance merge var instanceData = typeof childVal === 'function' ? childVal.call(vm, vm) : childVal; var defaultData = typeof parentVal === 'function' ? parentVal.call(vm, vm) : parentVal; if (instanceData) { return mergeData(instanceData, defaultData) } else { return defaultData } } } } strats.data = function ( parentVal, childVal, vm ) { if (!vm) { if (childVal && typeof childVal !== 'function') { warn( 'The "data" option should be a function ' + 'that returns a per-instance value in component ' + 'definitions.', vm ); return parentVal } return mergeDataOrFn(parentVal, childVal) } return mergeDataOrFn(parentVal, childVal, vm) }; /** * Hooks and props are merged as arrays. */ function mergeHook ( parentVal, childVal ) { var res = childVal ? parentVal ? parentVal.concat(childVal) : Array.isArray(childVal) ? childVal : [childVal] : parentVal; return res ? dedupeHooks(res) : res } function dedupeHooks (hooks) { var res = []; for (var i = 0; i < hooks.length; i++) { if (res.indexOf(hooks[i]) === -1) { res.push(hooks[i]); } } return res } LIFECYCLE_HOOKS.forEach(function (hook) { strats[hook] = mergeHook; }); /** * Assets * * When a vm is present (instance creation), we need to do * a three-way merge between constructor options, instance * options and parent options. */ function mergeAssets ( parentVal, childVal, vm, key ) { var res = Object.create(parentVal || null); if (childVal) { assertObjectType(key, childVal, vm); return extend(res, childVal) } else { return res } } ASSET_TYPES.forEach(function (type) { strats[type + 's'] = mergeAssets; }); /** * Watchers. * * Watchers hashes should not overwrite one * another, so we merge them as arrays. */ strats.watch = function ( parentVal, childVal, vm, key ) { // work around Firefox's Object.prototype.watch... if (parentVal === nativeWatch) { parentVal = undefined; } if (childVal === nativeWatch) { childVal = undefined; } /* istanbul ignore if */ if (!childVal) { return Object.create(parentVal || null) } { assertObjectType(key, childVal, vm); } if (!parentVal) { return childVal } var ret = {}; extend(ret, parentVal); for (var key$1 in childVal) { var parent = ret[key$1]; var child = childVal[key$1]; if (parent && !Array.isArray(parent)) { parent = [parent]; } ret[key$1] = parent ? parent.concat(child) : Array.isArray(child) ? child : [child]; } return ret }; /** * Other object hashes. */ strats.props = strats.methods = strats.inject = strats.computed = function ( parentVal, childVal, vm, key ) { if (childVal && "development" !== 'production') { assertObjectType(key, childVal, vm); } if (!parentVal) { return childVal } var ret = Object.create(null); extend(ret, parentVal); if (childVal) { extend(ret, childVal); } return ret }; strats.provide = mergeDataOrFn; /** * Default strategy. */ var defaultStrat = function (parentVal, childVal) { return childVal === undefined ? parentVal : childVal }; /** * Validate component names */ function checkComponents (options) { for (var key in options.components) { validateComponentName(key); } } function validateComponentName (name) { if (!new RegExp(("^[a-zA-Z][\\-\\.0-9_" + unicodeLetters + "]*$")).test(name)) { warn( 'Invalid component name: "' + name + '". Component names ' + 'should conform to valid custom element name in html5 specification.' ); } if (isBuiltInTag(name) || config.isReservedTag(name)) { warn( 'Do not use built-in or reserved HTML elements as component ' + 'id: ' + name ); } } /** * Ensure all props option syntax are normalized into the * Object-based format. */ function normalizeProps (options, vm) { var props = options.props; if (!props) { return } var res = {}; var i, val, name; if (Array.isArray(props)) { i = props.length; while (i--) { val = props[i]; if (typeof val === 'string') { name = camelize(val); res[name] = { type: null }; } else { warn('props must be strings when using array syntax.'); } } } else if (isPlainObject(props)) { for (var key in props) { val = props[key]; name = camelize(key); res[name] = isPlainObject(val) ? val : { type: val }; } } else { warn( "Invalid value for option \"props\": expected an Array or an Object, " + "but got " + (toRawType(props)) + ".", vm ); } options.props = res; } /** * Normalize all injections into Object-based format */ function normalizeInject (options, vm) { var inject = options.inject; if (!inject) { return } var normalized = options.inject = {}; if (Array.isArray(inject)) { for (var i = 0; i < inject.length; i++) { normalized[inject[i]] = { from: inject[i] }; } } else if (isPlainObject(inject)) { for (var key in inject) { var val = inject[key]; normalized[key] = isPlainObject(val) ? extend({ from: key }, val) : { from: val }; } } else { warn( "Invalid value for option \"inject\": expected an Array or an Object, " + "but got " + (toRawType(inject)) + ".", vm ); } } /** * Normalize raw function directives into object format. */ function normalizeDirectives (options) { var dirs = options.directives; if (dirs) { for (var key in dirs) { var def$$1 = dirs[key]; if (typeof def$$1 === 'function') { dirs[key] = { bind: def$$1, update: def$$1 }; } } } } function assertObjectType (name, value, vm) { if (!isPlainObject(value)) { warn( "Invalid value for option \"" + name + "\": expected an Object, " + "but got " + (toRawType(value)) + ".", vm ); } } /** * Merge two option objects into a new one. * Core utility used in both instantiation and inheritance. */ function mergeOptions ( parent, child, vm ) { { checkComponents(child); } if (typeof child === 'function') { child = child.options; } normalizeProps(child, vm); normalizeInject(child, vm); normalizeDirectives(child); // Apply extends and mixins on the child options, // but only if it is a raw options object that isn't // the result of another mergeOptions call. // Only merged options has the _base property. if (!child._base) { if (child.extends) { parent = mergeOptions(parent, child.extends, vm); } if (child.mixins) { for (var i = 0, l = child.mixins.length; i < l; i++) { parent = mergeOptions(parent, child.mixins[i], vm); } } } var options = {}; var key; for (key in parent) { mergeField(key); } for (key in child) { if (!hasOwn(parent, key)) { mergeField(key); } } function mergeField (key) { var strat = strats[key] || defaultStrat; options[key] = strat(parent[key], child[key], vm, key); } return options } /** * Resolve an asset. * This function is used because child instances need access * to assets defined in its ancestor chain. */ function resolveAsset ( options, type, id, warnMissing ) { /* istanbul ignore if */ if (typeof id !== 'string') { return } var assets = options[type]; // check local registration variations first if (hasOwn(assets, id)) { return assets[id] } var camelizedId = camelize(id); if (hasOwn(assets, camelizedId)) { return assets[camelizedId] } var PascalCaseId = capitalize(camelizedId); if (hasOwn(assets, PascalCaseId)) { return assets[PascalCaseId] } // fallback to prototype chain var res = assets[id] || assets[camelizedId] || assets[PascalCaseId]; if (warnMissing && !res) { warn( 'Failed to resolve ' + type.slice(0, -1) + ': ' + id, options ); } return res } /* */ function validateProp ( key, propOptions, propsData, vm ) { var prop = propOptions[key]; var absent = !hasOwn(propsData, key); var value = propsData[key]; // boolean casting var booleanIndex = getTypeIndex(Boolean, prop.type); if (booleanIndex > -1) { if (absent && !hasOwn(prop, 'default')) { value = false; } else if (value === '' || value === hyphenate(key)) { // only cast empty string / same name to boolean if // boolean has higher priority var stringIndex = getTypeIndex(String, prop.type); if (stringIndex < 0 || booleanIndex < stringIndex) { value = true; } } } // check default value if (value === undefined) { value = getPropDefaultValue(vm, prop, key); // since the default value is a fresh copy, // make sure to observe it. var prevShouldObserve = shouldObserve; toggleObserving(true); observe(value); toggleObserving(prevShouldObserve); } { assertProp(prop, key, value, vm, absent); } return value } /** * Get the default value of a prop. */ function getPropDefaultValue (vm, prop, key) { // no default, return undefined if (!hasOwn(prop, 'default')) { return undefined } var def = prop.default; // warn against non-factory defaults for Object & Array if (isObject(def)) { warn( 'Invalid default value for prop "' + key + '": ' + 'Props with type Object/Array must use a factory function ' + 'to return the default value.', vm ); } // the raw prop value was also undefined from previous render, // return previous default value to avoid unnecessary watcher trigger if (vm && vm.$options.propsData && vm.$options.propsData[key] === undefined && vm._props[key] !== undefined ) { return vm._props[key] } // call factory function for non-Function types // a value is Function if its prototype is function even across different execution context return typeof def === 'function' && getType(prop.type) !== 'Function' ? def.call(vm) : def } /** * Assert whether a prop is valid. */ function assertProp ( prop, name, value, vm, absent ) { if (prop.required && absent) { warn( 'Missing required prop: "' + name + '"', vm ); return } if (value == null && !prop.required) { return } var type = prop.type; var valid = !type || type === true; var expectedTypes = []; if (type) { if (!Array.isArray(type)) { type = [type]; } for (var i = 0; i < type.length && !valid; i++) { var assertedType = assertType(value, type[i]); expectedTypes.push(assertedType.expectedType || ''); valid = assertedType.valid; } } if (!valid) { warn( getInvalidTypeMessage(name, value, expectedTypes), vm ); return } var validator = prop.validator; if (validator) { if (!validator(value)) { warn( 'Invalid prop: custom validator check failed for prop "' + name + '".', vm ); } } } var simpleCheckRE = /^(String|Number|Boolean|Function|Symbol)$/; function assertType (value, type) { var valid; var expectedType = getType(type); if (simpleCheckRE.test(expectedType)) { var t = typeof value; valid = t === expectedType.toLowerCase(); // for primitive wrapper objects if (!valid && t === 'object') { valid = value instanceof type; } } else if (expectedType === 'Object') { valid = isPlainObject(value); } else if (expectedType === 'Array') { valid = Array.isArray(value); } else { valid = value instanceof type; } return { valid: valid, expectedType: expectedType } } /** * Use function string name to check built-in types, * because a simple equality check will fail when running * across different vms / iframes. */ function getType (fn) { var match = fn && fn.toString().match(/^\s*function (\w+)/); return match ? match[1] : '' } function isSameType (a, b) { return getType(a) === getType(b) } function getTypeIndex (type, expectedTypes) { if (!Array.isArray(expectedTypes)) { return isSameType(expectedTypes, type) ? 0 : -1 } for (var i = 0, len = expectedTypes.length; i < len; i++) { if (isSameType(expectedTypes[i], type)) { return i } } return -1 } function getInvalidTypeMessage (name, value, expectedTypes) { var message = "Invalid prop: type check failed for prop \"" + name + "\"." + " Expected " + (expectedTypes.map(capitalize).join(', ')); var expectedType = expectedTypes[0]; var receivedType = toRawType(value); var expectedValue = styleValue(value, expectedType); var receivedValue = styleValue(value, receivedType); // check if we need to specify expected value if (expectedTypes.length === 1 && isExplicable(expectedType) && !isBoolean(expectedType, receivedType)) { message += " with value " + expectedValue; } message += ", got " + receivedType + " "; // check if we need to specify received value if (isExplicable(receivedType)) { message += "with value " + receivedValue + "."; } return message } function styleValue (value, type) { if (type === 'String') { return ("\"" + value + "\"") } else if (type === 'Number') { return ("" + (Number(value))) } else { return ("" + value) } } function isExplicable (value) { var explicitTypes = ['string', 'number', 'boolean']; return explicitTypes.some(function (elem) { return value.toLowerCase() === elem; }) } function isBoolean () { var args = [], len = arguments.length; while ( len-- ) args[ len ] = arguments[ len ]; return args.some(function (elem) { return elem.toLowerCase() === 'boolean'; }) } /* */ function handleError (err, vm, info) { // Deactivate deps tracking while processing error handler to avoid possible infinite rendering. // See: https://github.com/vuejs/vuex/issues/1505 pushTarget(); try { if (vm) { var cur = vm; while ((cur = cur.$parent)) { var hooks = cur.$options.errorCaptured; if (hooks) { for (var i = 0; i < hooks.length; i++) { try { var capture = hooks[i].call(cur, err, vm, info) === false; if (capture) { return } } catch (e) { globalHandleError(e, cur, 'errorCaptured hook'); } } } } } globalHandleError(err, vm, info); } finally { popTarget(); } } function invokeWithErrorHandling ( handler, context, args, vm, info ) { var res; try { res = args ? handler.apply(context, args) : handler.call(context); if (res && !res._isVue && isPromise(res)) { // issue #9511 // reassign to res to avoid catch triggering multiple times when nested calls res = res.catch(function (e) { return handleError(e, vm, info + " (Promise/async)"); }); } } catch (e) { handleError(e, vm, info); } return res } function globalHandleError (err, vm, info) { if (config.errorHandler) { try { return config.errorHandler.call(null, err, vm, info) } catch (e) { // if the user intentionally throws the original error in the handler, // do not log it twice if (e !== err) { logError(e, null, 'config.errorHandler'); } } } logError(err, vm, info); } function logError (err, vm, info) { { warn(("Error in " + info + ": \"" + (err.toString()) + "\""), vm); } /* istanbul ignore else */ if ((inBrowser || inWeex) && typeof console !== 'undefined') { console.error(err); } else { throw err } } /* */ var isUsingMicroTask = false; var callbacks = []; var pending = false; function flushCallbacks () { pending = false; var copies = callbacks.slice(0); callbacks.length = 0; for (var i = 0; i < copies.length; i++) { copies[i](); } } // Here we have async deferring wrappers using microtasks. // In 2.5 we used (macro) tasks (in combination with microtasks). // However, it has subtle problems when state is changed right before repaint // (e.g. #6813, out-in transitions). // Also, using (macro) tasks in event handler would cause some weird behaviors // that cannot be circumvented (e.g. #7109, #7153, #7546, #7834, #8109). // So we now use microtasks everywhere, again. // A major drawback of this tradeoff is that there are some scenarios // where microtasks have too high a priority and fire in between supposedly // sequential events (e.g. #4521, #6690, which have workarounds) // or even between bubbling of the same event (#6566). var timerFunc; // The nextTick behavior leverages the microtask queue, which can be accessed // via either native Promise.then or MutationObserver. // MutationObserver has wider support, however it is seriously bugged in // UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It // completely stops working after triggering a few times... so, if native // Promise is available, we will use it: /* istanbul ignore next, $flow-disable-line */ if (typeof Promise !== 'undefined' && isNative(Promise)) { var p = Promise.resolve(); timerFunc = function () { p.then(flushCallbacks); // In problematic UIWebViews, Promise.then doesn't completely break, but // it can get stuck in a weird state where callbacks are pushed into the // microtask queue but the queue isn't being flushed, until the browser // needs to do some other work, e.g. handle a timer. Therefore we can // "force" the microtask queue to be flushed by adding an empty timer. if (isIOS) { setTimeout(noop); } }; isUsingMicroTask = true; } else if (!isIE && typeof MutationObserver !== 'undefined' && ( isNative(MutationObserver) || // PhantomJS and iOS 7.x MutationObserver.toString() === '[object MutationObserverConstructor]' )) { // Use MutationObserver where native Promise is not available, // e.g. PhantomJS, iOS7, Android 4.4 // (#6466 MutationObserver is unreliable in IE11) var counter = 1; var observer = new MutationObserver(flushCallbacks); var textNode = document.createTextNode(String(counter)); observer.observe(textNode, { characterData: true }); timerFunc = function () { counter = (counter + 1) % 2; textNode.data = String(counter); }; isUsingMicroTask = true; } else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) { // Fallback to setImmediate. // Techinically it leverages the (macro) task queue, // but it is still a better choice than setTimeout. timerFunc = function () { setImmediate(flushCallbacks); }; } else { // Fallback to setTimeout. timerFunc = function () { setTimeout(flushCallbacks, 0); }; } function nextTick (cb, ctx) { var _resolve; callbacks.push(function () { if (cb) { try { cb.call(ctx); } catch (e) { handleError(e, ctx, 'nextTick'); } } else if (_resolve) { _resolve(ctx); } }); if (!pending) { pending = true; timerFunc(); } // $flow-disable-line if (!cb && typeof Promise !== 'undefined') { return new Promise(function (resolve) { _resolve = resolve; }) } } /* */ var mark; var measure; { var perf = inBrowser && window.performance; /* istanbul ignore if */ if ( perf && perf.mark && perf.measure && perf.clearMarks && perf.clearMeasures ) { mark = function (tag) { return perf.mark(tag); }; measure = function (name, startTag, endTag) { perf.measure(name, startTag, endTag); perf.clearMarks(startTag); perf.clearMarks(endTag); // perf.clearMeasures(name) }; } } /* not type checking this file because flow doesn't play well with Proxy */ var initProxy; { var allowedGlobals = makeMap( 'Infinity,undefined,NaN,isFinite,isNaN,' + 'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' + 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' + 'require' // for Webpack/Browserify ); var warnNonPresent = function (target, key) { warn( "Property or method \"" + key + "\" is not defined on the instance but " + 'referenced during render. Make sure that this property is reactive, ' + 'either in the data option, or for class-based components, by ' + 'initializing the property. ' + 'See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.', target ); }; var warnReservedPrefix = function (target, key) { warn( "Property \"" + key + "\" must be accessed with \"$data." + key + "\" because " + 'properties starting with "$" or "_" are not proxied in the Vue instance to ' + 'prevent conflicts with Vue internals' + 'See: https://vuejs.org/v2/api/#data', target ); }; var hasProxy = typeof Proxy !== 'undefined' && isNative(Proxy); if (hasProxy) { var isBuiltInModifier = makeMap('stop,prevent,self,ctrl,shift,alt,meta,exact'); config.keyCodes = new Proxy(config.keyCodes, { set: function set (target, key, value) { if (isBuiltInModifier(key)) { warn(("Avoid overwriting built-in modifier in config.keyCodes: ." + key)); return false } else { target[key] = value; return true } } }); } var hasHandler = { has: function has (target, key) { var has = key in target; var isAllowed = allowedGlobals(key) || (typeof key === 'string' && key.charAt(0) === '_' && !(key in target.$data)); if (!has && !isAllowed) { if (key in target.$data) { warnReservedPrefix(target, key); } else { warnNonPresent(target, key); } } return has || !isAllowed } }; var getHandler = { get: function get (target, key) { if (typeof key === 'string' && !(key in target)) { if (key in target.$data) { warnReservedPrefix(target, key); } else { warnNonPresent(target, key); } } return target[key] } }; initProxy = function initProxy (vm) { if (hasProxy) { // determine which proxy handler to use var options = vm.$options; var handlers = options.render && options.render._withStripped ? getHandler : hasHandler; vm._renderProxy = new Proxy(vm, handlers); } else { vm._renderProxy = vm; } }; } /* */ var seenObjects = new _Set(); /** * Recursively traverse an object to evoke all converted * getters, so that every nested property inside the object * is collected as a "deep" dependency. */ function traverse (val) { _traverse(val, seenObjects); seenObjects.clear(); } function _traverse (val, seen) { var i, keys; var isA = Array.isArray(val); if ((!isA && !isObject(val)) || Object.isFrozen(val) || val instanceof VNode) { return } if (val.__ob__) { var depId = val.__ob__.dep.id; if (seen.has(depId)) { return } seen.add(depId); } if (isA) { i = val.length; while (i--) { _traverse(val[i], seen); } } else { keys = Object.keys(val); i = keys.length; while (i--) { _traverse(val[keys[i]], seen); } } } /* */ var normalizeEvent = cached(function (name) { var passive = name.charAt(0) === '&'; name = passive ? name.slice(1) : name; var once$$1 = name.charAt(0) === '~'; // Prefixed last, checked first name = once$$1 ? name.slice(1) : name; var capture = name.charAt(0) === '!'; name = capture ? name.slice(1) : name; return { name: name, once: once$$1, capture: capture, passive: passive } }); function createFnInvoker (fns, vm) { function invoker () { var arguments$1 = arguments; var fns = invoker.fns; if (Array.isArray(fns)) { var cloned = fns.slice(); for (var i = 0; i < cloned.length; i++) { invokeWithErrorHandling(cloned[i], null, arguments$1, vm, "v-on handler"); } } else { // return handler return value for single handlers return invokeWithErrorHandling(fns, null, arguments, vm, "v-on handler") } } invoker.fns = fns; return invoker } function updateListeners ( on, oldOn, add, remove$$1, createOnceHandler, vm ) { var name, def$$1, cur, old, event; for (name in on) { def$$1 = cur = on[name]; old = oldOn[name]; event = normalizeEvent(name); if (isUndef(cur)) { warn( "Invalid handler for event \"" + (event.name) + "\": got " + String(cur), vm ); } else if (isUndef(old)) { if (isUndef(cur.fns)) { cur = on[name] = createFnInvoker(cur, vm); } if (isTrue(event.once)) { cur = on[name] = createOnceHandler(event.name, cur, event.capture); } add(event.name, cur, event.capture, event.passive, event.params); } else if (cur !== old) { old.fns = cur; on[name] = old; } } for (name in oldOn) { if (isUndef(on[name])) { event = normalizeEvent(name); remove$$1(event.name, oldOn[name], event.capture); } } } /* */ function mergeVNodeHook (def, hookKey, hook) { if (def instanceof VNode) { def = def.data.hook || (def.data.hook = {}); } var invoker; var oldHook = def[hookKey]; function wrappedHook () { hook.apply(this, arguments); // important: remove merged hook to ensure it's called only once // and prevent memory leak remove(invoker.fns, wrappedHook); } if (isUndef(oldHook)) { // no existing hook invoker = createFnInvoker([wrappedHook]); } else { /* istanbul ignore if */ if (isDef(oldHook.fns) && isTrue(oldHook.merged)) { // already a merged invoker invoker = oldHook; invoker.fns.push(wrappedHook); } else { // existing plain hook invoker = createFnInvoker([oldHook, wrappedHook]); } } invoker.merged = true; def[hookKey] = invoker; } /* */ function extractPropsFromVNodeData ( data, Ctor, tag ) { // we are only extracting raw values here. // validation and default values are handled in the child // component itself. var propOptions = Ctor.options.props; if (isUndef(propOptions)) { return } var res = {}; var attrs = data.attrs; var props = data.props; if (isDef(attrs) || isDef(props)) { for (var key in propOptions) { var altKey = hyphenate(key); { var keyInLowerCase = key.toLowerCase(); if ( key !== keyInLowerCase && attrs && hasOwn(attrs, keyInLowerCase) ) { tip( "Prop \"" + keyInLowerCase + "\" is passed to component " + (formatComponentName(tag || Ctor)) + ", but the declared prop name is" + " \"" + key + "\". " + "Note that HTML attributes are case-insensitive and camelCased " + "props need to use their kebab-case equivalents when using in-DOM " + "templates. You should probably use \"" + altKey + "\" instead of \"" + key + "\"." ); } } checkProp(res, props, key, altKey, true) || checkProp(res, attrs, key, altKey, false); } } return res } function checkProp ( res, hash, key, altKey, preserve ) { if (isDef(hash)) { if (hasOwn(hash, key)) { res[key] = hash[key]; if (!preserve) { delete hash[key]; } return true } else if (hasOwn(hash, altKey)) { res[key] = hash[altKey]; if (!preserve) { delete hash[altKey]; } return true } } return false } /* */ // The template compiler attempts to minimize the need for normalization by // statically analyzing the template at compile time. // // For plain HTML markup, normalization can be completely skipped because the // generated render function is guaranteed to return Array. There are // two cases where extra normalization is needed: // 1. When the children contains components - because a functional component // may return an Array instead of a single root. In this case, just a simple // normalization is needed - if any child is an Array, we flatten the whole // thing with Array.prototype.concat. It is guaranteed to be only 1-level deep // because functional components already normalize their own children. function simpleNormalizeChildren (children) { for (var i = 0; i < children.length; i++) { if (Array.isArray(children[i])) { return Array.prototype.concat.apply([], children) } } return children } // 2. When the children contains constructs that always generated nested Arrays, // e.g.