diff --git a/CHANGELOG.md b/CHANGELOG.md
index b3fe187..a9c2d40 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,3 +4,7 @@ Changelog
##### 0.1.1-beta
* Removes react-md
* Adds jest and some tests
+
+##### 0.2.0-beta
+* Adds row totals as an optional prop enabled by default
+* Updates React/React-DOM from 15.6.1 to 16.1.0
diff --git a/README.md b/README.md
index a7d8c1e..cabdc3d 100644
--- a/README.md
+++ b/README.md
@@ -101,6 +101,10 @@ You can also use a global-friendly UMD build:
* rowHeaders: all the parent row headers above the current clicked row header cell and at the current cell
* `onLeftHeaderCellClick`
* A function that is fired when clicking on the top left most cell (above the row headers and to the left of the column headers)
+* `rowTotals`
+ * A boolean that when false will not display row totals in the table. Totals are turned on by default.
+* `selectedAggregationDimension`
+ * Sets the default aggregation dimension in the Drawer.
## Example usage with optional props
```js
@@ -185,6 +189,8 @@ function onLeftHeaderCellClick() {
onLeftGridCellClick={onLeftGridCellClick}
onGridHeaderCellClick={onGridHeaderCellClick}
onLeftHeaderCellClick={onLeftHeaderCellClick}
+ rowTotals={true}
+ selectedAggregationDimension={'age'}
/>
```
diff --git a/package.json b/package.json
index bededad..ba65473 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "react-virtualized-pivot",
- "version": "0.1.1-beta",
+ "version": "0.2.0-beta",
"description": "React Virtualized Pivot",
"main": "dist/es/index.js",
"module": "dist/es/index.js",
@@ -49,11 +49,16 @@
"verbose": true
},
"dependencies": {
- "babel-runtime": "^6.26.0",
- "quick-pivot": "^2.2.6",
- "react-draggable": "^2.2.6",
- "react-select": "^1.0.0-rc.5",
- "react-virtualized": "^9.9.0"
+ "enzyme-adapter-react-16": "^1.1.0",
+ "quick-pivot": "^2.3.1",
+ "react": "^16.1.0",
+ "react-dom": "^16.1.0",
+ "react-draggable": "^3.0.3",
+ "react-select": "^1.0.0-rc.10",
+ "react-sortablejs": "^1.3.5",
+ "react-test-renderer": "^16.1.1",
+ "react-virtualized": "^9.12.0",
+ "sortablejs": "^1.7.0"
},
"devDependencies": {
"autoprefixer": "^7.1.2",
@@ -72,9 +77,10 @@
"babel-preset-es2015": "^6.22.0",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-2": "^6.24.1",
+ "babel-runtime": "^6.26.0",
"cross-env": "^5.0.5",
"css-loader": "0.26.1",
- "enzyme": "^2.8.2",
+ "enzyme": "^3.2.0",
"eslint": "^4.4.1",
"eslint-loader": "1.1.0",
"eslint-plugin-import": "^2.7.0",
@@ -94,9 +100,6 @@
"pre-commit": "^1.2.2",
"prop-types": "^15.5.10",
"raf": "^3.3.2",
- "react": "^15.6.1",
- "react-addons-test-utils": "^15.5.1",
- "react-dom": "^15.6.1",
"react-hot-loader": "^3.0.0-beta.7",
"rimraf": "^2.6.1",
"sass-loader": "^6.0.6",
@@ -107,9 +110,5 @@
"webpack-dashboard": "^0.3.0",
"webpack-dev-server": "^2.4.1",
"webpack-node-externals": "^1.6.0"
- },
- "peerDependencies": {
- "react": "^15.6.1",
- "react-dom": "^15.6.1"
}
}
diff --git a/src/app.jsx b/src/app.jsx
index a61afb7..1b3f85d 100644
--- a/src/app.jsx
+++ b/src/app.jsx
@@ -39,11 +39,24 @@ export default class App extends React.Component {
gridBorders: '#e0e0e0',
icons: '#ccc',
},
+ colFields: ['name'],
+ rowFields: ['gender'],
+ onLeftGridCellClick: () => console.log('clicking leftHeader'), // eslint-disable-line no-console
+ pivotOnChangeEnabled: true,
+ pivotOnChangeFunction: (prevState) => {
+ /* eslint-disable */
+ const newState = prevState;
+ newState.colFields=["name","house"];
+ newState.filters={name: ["Cersei"]};
+ console.log('new state', newState)
+ return newState
+ }
};
this.handleFileSelect = this.handleFileSelect.bind(this);
this.onSelectData = this.onSelectData.bind(this);
this.onSelectColorPack = this.onSelectColorPack.bind(this);
+ this.onButtonClick = this.onButtonClick.bind(this);
}
handleFileSelect(evt) {
@@ -63,6 +76,16 @@ export default class App extends React.Component {
data: data.smallData,
isLoaded: true,
selectedAggregationDimension: 'age',
+ colFields: [],
+ rowFields: [],
+ pivotOnChangeFunction: (prevState) => {
+ /* eslint-disable */
+ const newState = prevState;
+ newState.colFields=["name","house"];
+ newState.filters={name: ["Cersei"]};
+ console.log('new state', newState)
+ return newState
+ },
});
}
if (dataSize.value === 'medium') {
@@ -71,6 +94,9 @@ export default class App extends React.Component {
data: data.mediumData,
isLoaded: true,
selectedAggregationDimension: 'Quantity',
+ colFields: [],
+ rowFields: [],
+ pivotOnChangeFunction: undefined,
});
}
if (dataSize.value === 'large') {
@@ -86,12 +112,21 @@ export default class App extends React.Component {
data: results.data,
selectedAggregationDimension: 'Amount Requested',
isLoaded: true,
+ colFields: [],
+ rowFields: [],
+ pivotOnChangeFunction: undefined,
});
},
});
}
}
+ onButtonClick() {
+ this.setState({
+ onLeftHeaderCellClick: function(){console.log('Changes OnClick')},
+ });
+ }
+
onSelectColorPack(colorPack) {
if (colorPack.value === 'standard') {
this.setState({
@@ -206,6 +241,7 @@ export default class App extends React.Component {
+
console.log('clicking leftHeader')} // eslint-disable-line no-console
+ onLeftHeaderCellClick={this.state.onLeftHeaderCellClick} // eslint-disable-line no-console
+ rowTotals={true}
selectedAggregationDimension={selectedAggregationDimension}
/>
diff --git a/src/components/CustomReactSortable/CustomReactSortable.jsx b/src/components/CustomReactSortable/CustomReactSortable.jsx
index f9eee98..54f6035 100644
--- a/src/components/CustomReactSortable/CustomReactSortable.jsx
+++ b/src/components/CustomReactSortable/CustomReactSortable.jsx
@@ -1,3 +1,4 @@
+/* eslint-disable */
/* eslint consistent-return: 0 */
import PropTypes from 'prop-types';
import React, { Component } from 'react';
@@ -5,106 +6,97 @@ import ReactDOM from 'react-dom';
import SortableJS from './CustomSortable';
const store = {
- nextSibling: null,
- activeComponent: null,
+ nextSibling: null,
+ activeComponent: null
};
class Sortable extends Component {
static propTypes = {
- options: PropTypes.object,
- onChange: PropTypes.func,
- tag: PropTypes.string,
- style: PropTypes.object,
+ options: PropTypes.object,
+ onChange: PropTypes.func,
+ tag: PropTypes.string,
+ style: PropTypes.object
};
static defaultProps = {
- options: {},
- tag: 'div',
- style: {},
+ options: {},
+ tag: 'div',
+ style: {}
};
sortable = null;
componentDidMount() {
- const options = { ...this.props.options };
-
- [
- 'onChoose',
- 'onStart',
- 'onEnd',
- 'onAdd',
- 'onUpdate',
- 'onSort',
- 'onRemove',
- 'onFilter',
- 'onMove',
- 'onClone',
- ].forEach((name) => {
- const eventHandler = options[name];
-
- options[name] = (...params) => {
- const [evt] = params;
-
- if (name === 'onChoose') {
- store.nextSibling = evt.item.nextElementSibling;
- store.activeComponent = this;
- } else if ((name === 'onAdd' || name === 'onUpdate') &&
- this.props.onChange) {
- const items = this.sortable.toArray();
- const remote = store.activeComponent;
- const remoteItems = remote.sortable.toArray();
-
- const referenceNode = (store.nextSibling &&
- store.nextSibling.parentNode !== null) ?
- store.nextSibling : null;
-
- evt.from.insertBefore(evt.item, referenceNode);
- if (remote !== this) {
- const remoteOptions = remote.props.options || {};
-
- if ((typeof remoteOptions.group === 'object') &&
- (remoteOptions.group.pull === 'clone')) {
- // Remove the node with the same data-reactid
- evt.item.parentNode.removeChild(evt.item);
- }
-
- remote.props.onChange &&
- remote.props.onChange(remoteItems, remote.sortable, evt);
- }
-
- this.props.onChange &&
- this.props.onChange(items, this.sortable, evt);
- }
-
- if (evt.type === 'move') {
- const [evt, originalEvent] = params;
- const canMove = eventHandler ?
- eventHandler(evt, originalEvent) : true;
-
- return canMove;
- }
-
- setTimeout(() => {
- eventHandler && eventHandler(evt);
- }, 0);
- };
- });
-
- this.sortable = SortableJS.create(ReactDOM.findDOMNode(this), options);
+ const options = { ...this.props.options };
+
+ [
+ 'onChoose',
+ 'onStart',
+ 'onEnd',
+ 'onAdd',
+ 'onUpdate',
+ 'onSort',
+ 'onRemove',
+ 'onFilter',
+ 'onMove',
+ 'onClone'
+ ].forEach((name) => {
+ const eventHandler = options[name];
+
+ options[name] = (...params) => {
+ const [evt] = params;
+
+ if (name === 'onChoose') {
+ store.nextSibling = evt.item.nextElementSibling;
+ store.activeComponent = this;
+ } else if ((name === 'onAdd' || name === 'onUpdate') && this.props.onChange) {
+ const items = this.sortable.toArray();
+ const remote = store.activeComponent;
+ const remoteItems = remote.sortable.toArray();
+
+ const referenceNode = (store.nextSibling && store.nextSibling.parentNode !== null) ? store.nextSibling : null;
+ evt.from.insertBefore(evt.item, referenceNode);
+ if (remote !== this) {
+ const remoteOptions = remote.props.options || {};
+
+ if ((typeof remoteOptions.group === 'object') && (remoteOptions.group.pull === 'clone')) {
+ // Remove the node with the same data-reactid
+ evt.item.parentNode.removeChild(evt.item);
+ }
+
+ remote.props.onChange && remote.props.onChange(remoteItems, remote.sortable, evt);
+ }
+
+ this.props.onChange && this.props.onChange(items, this.sortable, evt);
+ }
+
+ if (evt.type === 'move') {
+ const [evt, originalEvent] = params;
+ const canMove = eventHandler ? eventHandler(evt, originalEvent) : true;
+ return canMove;
+ }
+
+ setTimeout(() => {
+ eventHandler && eventHandler(evt);
+ }, 0);
+ };
+ });
+
+ this.sortable = SortableJS.create(ReactDOM.findDOMNode(this), options);
}
componentWillUnmount() {
- if (this.sortable) {
- this.sortable.destroy();
- this.sortable = null;
- }
+ if (this.sortable) {
+ this.sortable.destroy();
+ this.sortable = null;
+ }
}
render() {
- const { tag: Component, ...props } = this.props;
+ const { tag: Component, ...props } = this.props;
- delete props.options;
- delete props.onChange;
+ delete props.options;
+ delete props.onChange;
- return (
-
- );
+ return (
+
+ );
}
}
diff --git a/src/components/CustomReactSortable/CustomSortable.js b/src/components/CustomReactSortable/CustomSortable.js
index e77d57b..c89a117 100644
--- a/src/components/CustomReactSortable/CustomSortable.js
+++ b/src/components/CustomReactSortable/CustomSortable.js
@@ -1,1492 +1,1541 @@
/* eslint-disable */
/**!
* Sortable
- * @author RubaXa
+ * @author RubaXa
* @license MIT
*/
(function sortableModule(factory) {
- "use strict";
-
- if (typeof define === "function" && define.amd) {
- define(factory);
- }
- else if (typeof module != "undefined" && typeof module.exports != "undefined") {
- module.exports = factory();
- }
- else {
- /* jshint sub:true */
- window["Sortable"] = factory();
- }
+ "use strict";
+
+ if (typeof define === "function" && define.amd) {
+ define(factory);
+ }
+ else if (typeof module != "undefined" && typeof module.exports != "undefined") {
+ module.exports = factory();
+ }
+ else {
+ /* jshint sub:true */
+ window["Sortable"] = factory();
+ }
})(function sortableFactory() {
- "use strict";
+ "use strict";
- if (typeof window == "undefined" || !window.document) {
- return function sortableError() {
- throw new Error("Sortable.js requires a window with a document");
- };
- }
-
- var dragEl,
- parentEl,
- ghostEl,
- cloneEl,
- rootEl,
- nextEl,
- lastDownEl,
-
- scrollEl,
- scrollParentEl,
- scrollCustomFn,
-
- lastEl,
- lastCSS,
- lastParentCSS,
-
- oldIndex,
- newIndex,
-
- activeGroup,
- putSortable,
+ if (typeof window === "undefined" || !window.document) {
+ return function sortableError() {
+ throw new Error("Sortable.js requires a window with a document");
+ };
+ }
+
+ var dragEl,
+ parentEl,
+ ghostEl,
+ cloneEl,
+ rootEl,
+ nextEl,
+ lastDownEl,
+
+ scrollEl,
+ scrollParentEl,
+ scrollCustomFn,
+
+ lastEl,
+ lastCSS,
+ lastParentCSS,
+
+ oldIndex,
+ newIndex,
+
+ activeGroup,
+ putSortable,
+
+ autoScroll = {},
+
+ tapEvt,
+ touchEvt,
+
+ moved,
+
+ /** @const */
+ R_SPACE = /\s+/g,
+ R_FLOAT = /left|right|inline/,
+
+ expando = 'Sortable' + (new Date).getTime(),
+
+ win = window,
+ document = win.document,
+ parseInt = win.parseInt,
+ setTimeout = win.setTimeout,
+
+ $ = win.jQuery || win.Zepto,
+ Polymer = win.Polymer,
+
+ captureMode = false,
+ passiveMode = false,
+
+ supportDraggable = ('draggable' in document.createElement('div')),
+ supportCssPointerEvents = (function (el) {
+ // false when IE11
+ if (!!navigator.userAgent.match(/(?:Trident.*rv[ :]?11\.|msie)/i)) {
+ return false;
+ }
+ el = document.createElement('x');
+ el.style.cssText = 'pointer-events:auto';
+ return el.style.pointerEvents === 'auto';
+ })(),
+
+ _silent = false,
+
+ abs = Math.abs,
+ min = Math.min,
+
+ savedInputChecked = [],
+ touchDragOverListeners = [],
+
+ _autoScroll = _throttle(function (/**Event*/evt, /**Object*/options, /**HTMLElement*/rootEl) {
+ // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521
+ if (rootEl && options.scroll) {
+ var _this = rootEl[expando],
+ el,
+ rect,
+ sens = options.scrollSensitivity,
+ speed = options.scrollSpeed,
+
+ x = evt.clientX,
+ y = evt.clientY,
+
+ winWidth = window.innerWidth,
+ winHeight = window.innerHeight,
+
+ vx,
+ vy,
+
+ scrollOffsetX,
+ scrollOffsetY
+ ;
+
+ // Delect scrollEl
+ if (scrollParentEl !== rootEl) {
+ scrollEl = options.scroll;
+ scrollParentEl = rootEl;
+ scrollCustomFn = options.scrollFn;
+
+ if (scrollEl === true) {
+ scrollEl = rootEl;
+
+ do {
+ if ((scrollEl.offsetWidth < scrollEl.scrollWidth) ||
+ (scrollEl.offsetHeight < scrollEl.scrollHeight)
+ ) {
+ break;
+ }
+ /* jshint boss:true */
+ } while (scrollEl = scrollEl.parentNode);
+ }
+ }
+
+ if (scrollEl) {
+ el = scrollEl;
+ rect = scrollEl.getBoundingClientRect();
+ vx = (abs(rect.right - x) <= sens) - (abs(rect.left - x) <= sens);
+ vy = (abs(rect.bottom - y) <= sens) - (abs(rect.top - y) <= sens);
+ }
+
+
+ if (!(vx || vy)) {
+ vx = (winWidth - x <= sens) - (x <= sens);
+ vy = (winHeight - y <= sens) - (y <= sens);
+
+ /* jshint expr:true */
+ (vx || vy) && (el = win);
+ }
+
+
+ if (autoScroll.vx !== vx || autoScroll.vy !== vy || autoScroll.el !== el) {
+ autoScroll.el = el;
+ autoScroll.vx = vx;
+ autoScroll.vy = vy;
+
+ clearInterval(autoScroll.pid);
+
+ if (el) {
+ autoScroll.pid = setInterval(function () {
+ scrollOffsetY = vy ? vy * speed : 0;
+ scrollOffsetX = vx ? vx * speed : 0;
+
+ if ('function' === typeof(scrollCustomFn)) {
+ return scrollCustomFn.call(_this, scrollOffsetX, scrollOffsetY, evt);
+ }
+
+ if (el === win) {
+ win.scrollTo(win.pageXOffset + scrollOffsetX, win.pageYOffset + scrollOffsetY);
+ } else {
+ el.scrollTop += scrollOffsetY;
+ el.scrollLeft += scrollOffsetX;
+ }
+ }, 24);
+ }
+ }
+ }
+ }, 30),
+
+ _prepareGroup = function (options) {
+ function toFn(value, pull) {
+ if (value === void 0 || value === true) {
+ value = group.name;
+ }
+
+ if (typeof value === 'function') {
+ return value;
+ } else {
+ return function (to, from) {
+ var fromGroup = from.options.group.name;
+
+ return pull
+ ? value
+ : value && (value.join
+ ? value.indexOf(fromGroup) > -1
+ : (fromGroup == value)
+ );
+ };
+ }
+ }
+
+ var group = {};
+ var originalGroup = options.group;
+
+ if (!originalGroup || typeof originalGroup != 'object') {
+ originalGroup = {name: originalGroup};
+ }
+
+ group.name = originalGroup.name;
+ group.checkPull = toFn(originalGroup.pull, true);
+ group.checkPut = toFn(originalGroup.put);
+ group.revertClone = originalGroup.revertClone;
+
+ options.group = group;
+ }
+ ;
+
+ // Detect support a passive mode
+ try {
+ window.addEventListener('test', null, Object.defineProperty({}, 'passive', {
+ get: function () {
+ // `false`, because everything starts to work incorrectly and instead of d'n'd,
+ // begins the page has scrolled.
+ passiveMode = false;
+ captureMode = {
+ capture: false,
+ passive: passiveMode
+ };
+ }
+ }));
+ } catch (err) {}
+
+ /**
+ * @class Sortable
+ * @param {HTMLElement} el
+ * @param {Object} [options]
+ */
+ function Sortable(el, options) {
+ if (!(el && el.nodeType && el.nodeType === 1)) {
+ throw 'Sortable: `el` must be HTMLElement, and not ' + {}.toString.call(el);
+ }
+
+ this.el = el; // root element
+ this.options = options = _extend({}, options);
+
+
+ // Export instance
+ el[expando] = this;
+
+ // Default options
+ var defaults = {
+ group: Math.random(),
+ sort: true,
+ disabled: false,
+ store: null,
+ handle: null,
+ scroll: true,
+ scrollSensitivity: 30,
+ scrollSpeed: 10,
+ draggable: /[uo]l/i.test(el.nodeName) ? 'li' : '>*',
+ ghostClass: 'sortable-ghost',
+ chosenClass: 'sortable-chosen',
+ dragClass: 'sortable-drag',
+ ignore: 'a, img',
+ filter: null,
+ preventOnFilter: true,
+ animation: 0,
+ setData: function (dataTransfer, dragEl) {
+ dataTransfer.setData('Text', dragEl.textContent);
+ },
+ dropBubble: false,
+ dragoverBubble: false,
+ dataIdAttr: 'data-id',
+ delay: 0,
+ forceFallback: false,
+ fallbackClass: 'sortable-fallback',
+ fallbackOnBody: false,
+ fallbackTolerance: 0,
+ fallbackOffset: {x: 0, y: 0},
+ supportPointer: Sortable.supportPointer !== false
+ };
+
+
+ // Set default options
+ for (var name in defaults) {
+ !(name in options) && (options[name] = defaults[name]);
+ }
+
+ _prepareGroup(options);
+
+ // Bind all private methods
+ for (var fn in this) {
+ if (fn.charAt(0) === '_' && typeof this[fn] === 'function') {
+ this[fn] = this[fn].bind(this);
+ }
+ }
+
+ // Setup drag mode
+ this.nativeDraggable = options.forceFallback ? false : supportDraggable;
+
+ // Bind events
+ _on(el, 'mousedown', this._onTapStart);
+ _on(el, 'touchstart', this._onTapStart);
+ options.supportPointer && _on(el, 'pointerdown', this._onTapStart);
+
+ if (this.nativeDraggable) {
+ _on(el, 'dragover', this);
+ _on(el, 'dragenter', this);
+ }
+
+ touchDragOverListeners.push(this._onDragOver);
+
+ // Restore sorting
+ options.store && this.sort(options.store.get(this));
+ }
+
+
+ Sortable.prototype = /** @lends Sortable.prototype */ {
+ constructor: Sortable,
+
+ _onTapStart: function (/** Event|TouchEvent */evt) {
+ var _this = this,
+ el = this.el,
+ options = this.options,
+ preventOnFilter = options.preventOnFilter,
+ type = evt.type,
+ touch = evt.touches && evt.touches[0],
+ target = (touch || evt).target,
+ originalTarget = evt.target.shadowRoot && (evt.path && evt.path[0]) || target,
+ filter = options.filter,
+ startIndex;
+
+ _saveInputCheckedState(el);
+
+
+ // Don't trigger start event when an element is been dragged, otherwise the evt.oldindex always wrong when set option.group.
+ if (dragEl) {
+ return;
+ }
+
+ if (/mousedown|pointerdown/.test(type) && evt.button !== 0 || options.disabled) {
+ return; // only left button or enabled
+ }
+
+ // cancel dnd if original target is content editable
+ if (originalTarget.isContentEditable) {
+ return;
+ }
+
+ target = _closest(target, options.draggable, el);
+
+ if (!target) {
+ return;
+ }
+
+ if (lastDownEl === target) {
+ // Ignoring duplicate `down`
+ return;
+ }
+
+ // Get the index of the dragged element within its parent
+ startIndex = _index(target, options.draggable);
+
+ // Check filter
+ if (typeof filter === 'function') {
+ if (filter.call(this, evt, target, this)) {
+ _dispatchEvent(_this, originalTarget, 'filter', target, el, el, startIndex);
+ preventOnFilter && evt.preventDefault();
+ return; // cancel dnd
+ }
+ }
+ else if (filter) {
+ filter = filter.split(',').some(function (criteria) {
+ criteria = _closest(originalTarget, criteria.trim(), el);
+
+ if (criteria) {
+ _dispatchEvent(_this, criteria, 'filter', target, el, el, startIndex);
+ return true;
+ }
+ });
+
+ if (filter) {
+ preventOnFilter && evt.preventDefault();
+ return; // cancel dnd
+ }
+ }
+
+ if (options.handle && !_closest(originalTarget, options.handle, el)) {
+ return;
+ }
+
+ // Prepare `dragstart`
+ this._prepareDragStart(evt, touch, target, startIndex);
+ },
+
+ _prepareDragStart: function (/** Event */evt, /** Touch */touch, /** HTMLElement */target, /** Number */startIndex) {
+ var _this = this,
+ el = _this.el,
+ options = _this.options,
+ ownerDocument = el.ownerDocument,
+ dragStartFn;
+
+ if (target && !dragEl && (target.parentNode === el)) {
+ tapEvt = evt;
+
+ rootEl = el;
+ dragEl = target;
+ parentEl = dragEl.parentNode;
+ nextEl = dragEl.nextSibling;
+ lastDownEl = target;
+ activeGroup = options.group;
+ oldIndex = startIndex;
+
+ this._lastX = (touch || evt).clientX;
+ this._lastY = (touch || evt).clientY;
+
+ // dragEl.style['will-change'] = 'all';
+
+ dragStartFn = function () {
+ // Delayed drag has been triggered
+ // we can re-enable the events: touchmove/mousemove
+ _this._disableDelayedDrag();
+
+ // Make the element draggable
+ dragEl.draggable = _this.nativeDraggable;
+
+ // Chosen item
+ _toggleClass(dragEl, options.chosenClass, true);
+
+ // Bind the events: dragstart/dragend
+ _this._triggerDragStart(evt, touch);
+
+ // Drag start event
+ _dispatchEvent(_this, rootEl, 'choose', dragEl, rootEl, rootEl, oldIndex);
+ };
+
+ // Disable "draggable"
+ options.ignore.split(',').forEach(function (criteria) {
+ _find(dragEl, criteria.trim(), _disableDraggable);
+ });
+
+ _on(ownerDocument, 'mouseup', _this._onDrop);
+ _on(ownerDocument, 'touchend', _this._onDrop);
+ _on(ownerDocument, 'touchcancel', _this._onDrop);
+ _on(ownerDocument, 'selectstart', _this);
+ options.supportPointer && _on(ownerDocument, 'pointercancel', _this._onDrop);
+
+ if (options.delay) {
+ // If the user moves the pointer or let go the click or touch
+ // before the delay has been reached:
+ // disable the delayed drag
+ _on(ownerDocument, 'mouseup', _this._disableDelayedDrag);
+ _on(ownerDocument, 'touchend', _this._disableDelayedDrag);
+ _on(ownerDocument, 'touchcancel', _this._disableDelayedDrag);
+ _on(ownerDocument, 'mousemove', _this._disableDelayedDrag);
+ _on(ownerDocument, 'touchmove', _this._disableDelayedDrag);
+ options.supportPointer && _on(ownerDocument, 'pointermove', _this._disableDelayedDrag);
+
+ _this._dragStartTimer = setTimeout(dragStartFn, options.delay);
+ } else {
+ dragStartFn();
+ }
+
+
+ }
+ },
+
+ _disableDelayedDrag: function () {
+ var ownerDocument = this.el.ownerDocument;
+
+ clearTimeout(this._dragStartTimer);
+ _off(ownerDocument, 'mouseup', this._disableDelayedDrag);
+ _off(ownerDocument, 'touchend', this._disableDelayedDrag);
+ _off(ownerDocument, 'touchcancel', this._disableDelayedDrag);
+ _off(ownerDocument, 'mousemove', this._disableDelayedDrag);
+ _off(ownerDocument, 'touchmove', this._disableDelayedDrag);
+ _off(ownerDocument, 'pointermove', this._disableDelayedDrag);
+ },
+
+ _triggerDragStart: function (/** Event */evt, /** Touch */touch) {
+ touch = touch || (evt.pointerType == 'touch' ? evt : null);
+
+ if (touch) {
+ // Touch device support
+ tapEvt = {
+ target: dragEl,
+ clientX: touch.clientX,
+ clientY: touch.clientY
+ };
+
+ this._onDragStart(tapEvt, 'touch');
+ }
+ else if (!this.nativeDraggable) {
+ this._onDragStart(tapEvt, true);
+ }
+ else {
+ _on(dragEl, 'dragend', this);
+ _on(rootEl, 'dragstart', this._onDragStart);
+ }
+
+ try {
+ if (document.selection) {
+ // Timeout neccessary for IE9
+ _nextTick(function () {
+ document.selection.empty();
+ });
+ } else {
+ window.getSelection().removeAllRanges();
+ }
+ } catch (err) {
+ }
+ },
+
+ _dragStarted: function () {
+ if (rootEl && dragEl) {
+ var options = this.options;
+
+ // Apply effect
+ _toggleClass(dragEl, options.ghostClass, true);
+ _toggleClass(dragEl, options.dragClass, false);
+
+ Sortable.active = this;
+
+ // Drag start event
+ _dispatchEvent(this, rootEl, 'start', dragEl, rootEl, rootEl, oldIndex);
+ } else {
+ this._nulling();
+ }
+ },
+
+ _emulateDragOver: function () {
+ if (touchEvt) {
+ if (this._lastX === touchEvt.clientX && this._lastY === touchEvt.clientY) {
+ return;
+ }
+
+ this._lastX = touchEvt.clientX;
+ this._lastY = touchEvt.clientY;
+
+ if (!supportCssPointerEvents) {
+ _css(ghostEl, 'display', 'none');
+ }
+
+ var target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY);
+ var parent = target;
+ var i = touchDragOverListeners.length;
+
+ if (target && target.shadowRoot) {
+ target = target.shadowRoot.elementFromPoint(touchEvt.clientX, touchEvt.clientY);
+ parent = target;
+ }
+
+ if (parent) {
+ do {
+ if (parent[expando]) {
+ while (i--) {
+ touchDragOverListeners[i]({
+ clientX: touchEvt.clientX,
+ clientY: touchEvt.clientY,
+ target: target,
+ rootEl: parent
+ });
+ }
+
+ break;
+ }
+
+ target = parent; // store last element
+ }
+ /* jshint boss:true */
+ while (parent = parent.parentNode);
+ }
+
+ if (!supportCssPointerEvents) {
+ _css(ghostEl, 'display', '');
+ }
+ }
+ },
+
+
+ _onTouchMove: function (/**TouchEvent*/evt) {
+ if (tapEvt) {
+ var options = this.options,
+ fallbackTolerance = options.fallbackTolerance,
+ fallbackOffset = options.fallbackOffset,
+ touch = evt.touches ? evt.touches[0] : evt,
+ dx = (touch.clientX - tapEvt.clientX) + fallbackOffset.x,
+ dy = (touch.clientY - tapEvt.clientY) + fallbackOffset.y,
+ translate3d = evt.touches ? 'translate3d(' + dx + 'px,' + dy + 'px,0)' : 'translate(' + dx + 'px,' + dy + 'px)';
+
+ // only set the status to dragging, when we are actually dragging
+ if (!Sortable.active) {
+ if (fallbackTolerance &&
+ min(abs(touch.clientX - this._lastX), abs(touch.clientY - this._lastY)) < fallbackTolerance
+ ) {
+ return;
+ }
+
+ this._dragStarted();
+ }
+
+ // as well as creating the ghost element on the document body
+ this._appendGhost();
+
+ moved = true;
+ touchEvt = touch;
+
+ _css(ghostEl, 'webkitTransform', translate3d);
+ _css(ghostEl, 'mozTransform', translate3d);
+ _css(ghostEl, 'msTransform', translate3d);
+ _css(ghostEl, 'transform', translate3d);
+
+ evt.preventDefault();
+ }
+ },
+
+ _appendGhost: function () {
+ if (!ghostEl) {
+ var rect = dragEl.getBoundingClientRect(),
+ css = _css(dragEl),
+ options = this.options,
+ ghostRect;
+
+ ghostEl = dragEl.cloneNode(true);
+
+ _toggleClass(ghostEl, options.ghostClass, false);
+ _toggleClass(ghostEl, options.fallbackClass, true);
+ _toggleClass(ghostEl, options.dragClass, true);
+
+ _css(ghostEl, 'top', rect.top - parseInt(css.marginTop, 10));
+ _css(ghostEl, 'left', rect.left - parseInt(css.marginLeft, 10));
+ _css(ghostEl, 'width', rect.width);
+ _css(ghostEl, 'height', rect.height);
+ _css(ghostEl, 'opacity', '0.8');
+ _css(ghostEl, 'position', 'fixed');
+ _css(ghostEl, 'zIndex', '100000');
+ _css(ghostEl, 'pointerEvents', 'none');
+
+ options.fallbackOnBody && document.body.appendChild(ghostEl) || rootEl.appendChild(ghostEl);
+
+ // Fixing dimensions.
+ ghostRect = ghostEl.getBoundingClientRect();
+ _css(ghostEl, 'width', rect.width * 2 - ghostRect.width);
+ _css(ghostEl, 'height', rect.height * 2 - ghostRect.height);
+ }
+ },
+
+ _onDragStart: function (/**Event*/evt, /**boolean*/useFallback) {
+ var _this = this;
+ var dataTransfer = evt.dataTransfer;
+ var options = _this.options;
+
+ _this._offUpEvents();
+
+ if (activeGroup.checkPull(_this, _this, dragEl, evt)) {
+ cloneEl = _clone(dragEl);
+
+ cloneEl.draggable = false;
+ // cloneEl.style['will-change'] = '';
+
+ _css(cloneEl, 'display', 'none');
+ _toggleClass(cloneEl, _this.options.chosenClass, false);
+
+ // #1143: IFrame support workaround
+ _this._cloneId = _nextTick(function () {
+ rootEl.insertBefore(cloneEl, dragEl);
+ _dispatchEvent(_this, rootEl, 'clone', dragEl);
+ });
+ }
+
+ _toggleClass(dragEl, options.dragClass, true);
+
+ if (useFallback) {
+ if (useFallback === 'touch') {
+ // Bind touch events
+ _on(document, 'touchmove', _this._onTouchMove);
+ _on(document, 'touchend', _this._onDrop);
+ _on(document, 'touchcancel', _this._onDrop);
+
+ if (options.supportPointer) {
+ _on(document, 'pointermove', _this._onTouchMove);
+ _on(document, 'pointerup', _this._onDrop);
+ }
+ } else {
+ // Old brwoser
+ _on(document, 'mousemove', _this._onTouchMove);
+ _on(document, 'mouseup', _this._onDrop);
+ }
+
+ _this._loopId = setInterval(_this._emulateDragOver, 50);
+ }
+ else {
+ if (dataTransfer) {
+ dataTransfer.effectAllowed = 'move';
+ options.setData && options.setData.call(_this, dataTransfer, dragEl);
+ }
+
+ _on(document, 'drop', _this);
+
+ // #1143: Бывает элемент с IFrame внутри блокирует `drop`,
+ // поэтому если вызвался `mouseover`, значит надо отменять весь d'n'd.
+ // Breaking Chrome 62+
+ // _on(document, 'mouseover', _this);
+
+ _this._dragStartId = _nextTick(_this._dragStarted);
+ }
+ },
+
+ _onDragOver: function (/**Event*/evt) {
+ var el = this.el,
+ target,
+ dragRect,
+ targetRect,
+ revert,
+ options = this.options,
+ group = options.group,
+ activeSortable = Sortable.active,
+ isOwner = (activeGroup === group),
+ isMovingBetweenSortable = false,
+ canSort = options.sort;
+
+ if (evt.preventDefault !== void 0) {
+ evt.preventDefault();
+ !options.dragoverBubble && evt.stopPropagation();
+ }
+
+ if (dragEl.animated) {
+ return;
+ }
+
+ moved = true;
+
+ if (activeSortable && !options.disabled &&
+ (isOwner
+ ? canSort || (revert = !rootEl.contains(dragEl)) // Reverting item into the original list
+ : (
+ putSortable === this ||
+ (
+ (activeSortable.lastPullMode = activeGroup.checkPull(this, activeSortable, dragEl, evt)) &&
+ group.checkPut(this, activeSortable, dragEl, evt)
+ )
+ )
+ ) &&
+ (evt.rootEl === void 0 || evt.rootEl === this.el) // touch fallback
+ ) {
+ // Smart auto-scrolling
+ _autoScroll(evt, options, this.el);
+
+ if (_silent) {
+ return;
+ }
+
+ target = _closest(evt.target, options.draggable, el);
+ dragRect = dragEl.getBoundingClientRect();
+
+ if (putSortable !== this) {
+ putSortable = this;
+ isMovingBetweenSortable = true;
+ }
+
+ if (revert) {
+ _cloneHide(activeSortable, true);
+ parentEl = rootEl; // actualization
+
+ if (cloneEl || nextEl) {
+ rootEl.insertBefore(dragEl, cloneEl || nextEl);
+ }
+ else if (!canSort) {
+ rootEl.appendChild(dragEl);
+ }
+
+ return;
+ }
+
+
+ if ((el.children.length === 0) || (el.children[0] === ghostEl) ||
+ (el === evt.target) && (_ghostIsLast(el, evt))
+ ) {
+ //assign target only if condition is true
+ if (el.children.length !== 0 && el.children[0] !== ghostEl && el === evt.target) {
+ target = el.lastElementChild;
+ }
+
+ if (target) {
+ if (target.animated) {
+ return;
+ }
+
+ targetRect = target.getBoundingClientRect();
+ }
+
+ _cloneHide(activeSortable, isOwner);
+
+ if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt) !== false) {
+ if (!dragEl.contains(el)) {
+ el.appendChild(dragEl);
+ parentEl = el; // actualization
+ }
+
+ this._animate(dragRect, dragEl);
+ target && this._animate(targetRect, target);
+ }
+ }
+ else if (target && !target.animated && target !== dragEl && (target.parentNode[expando] !== void 0)) {
+ if (lastEl !== target) {
+ lastEl = target;
+ lastCSS = _css(target);
+ lastParentCSS = _css(target.parentNode);
+ }
+
+ targetRect = target.getBoundingClientRect();
+
+ var width = targetRect.right - targetRect.left,
+ height = targetRect.bottom - targetRect.top,
+ floating = R_FLOAT.test(lastCSS.cssFloat + lastCSS.display)
+ || (lastParentCSS.display == 'flex' && lastParentCSS['flex-direction'].indexOf('row') === 0),
+ isWide = (target.offsetWidth > dragEl.offsetWidth),
+ isLong = (target.offsetHeight > dragEl.offsetHeight),
+ halfway = (floating ? (evt.clientX - targetRect.left) / width : (evt.clientY - targetRect.top) / height) > 0.5,
+ nextSibling = target.nextElementSibling,
+ after = false
+ ;
+
+ if (floating) {
+ var elTop = dragEl.offsetTop,
+ tgTop = target.offsetTop;
+
+ if (elTop === tgTop) {
+ after = (target.previousElementSibling === dragEl) && !isWide || halfway && isWide;
+ }
+ else if (target.previousElementSibling === dragEl || dragEl.previousElementSibling === target) {
+ after = (evt.clientY - targetRect.top) / height > 0.5;
+ } else {
+ after = tgTop > elTop;
+ }
+ } else if (!isMovingBetweenSortable) {
+ after = (nextSibling !== dragEl) && !isLong || halfway && isLong;
+ }
+
+ var moveVector = _onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, after);
+
+ if (moveVector !== false) {
+ if (moveVector === 1 || moveVector === -1) {
+ after = (moveVector === 1);
+ }
+
+ _silent = true;
+ setTimeout(_unsilent, 30);
+
+ _cloneHide(activeSortable, isOwner);
+
+ if (!dragEl.contains(el)) {
+ if (after && !nextSibling) {
+ el.appendChild(dragEl);
+ } else {
+ target.parentNode.insertBefore(dragEl, after ? nextSibling : target);
+ }
+ }
+
+ parentEl = dragEl.parentNode; // actualization
+
+ this._animate(dragRect, dragEl);
+ this._animate(targetRect, target);
+ }
+ }
+ }
+ },
+
+ _animate: function (prevRect, target) {
+ var ms = this.options.animation;
+
+ if (ms) {
+ var currentRect = target.getBoundingClientRect();
+
+ if (prevRect.nodeType === 1) {
+ prevRect = prevRect.getBoundingClientRect();
+ }
+
+ _css(target, 'transition', 'none');
+ _css(target, 'transform', 'translate3d('
+ + (prevRect.left - currentRect.left) + 'px,'
+ + (prevRect.top - currentRect.top) + 'px,0)'
+ );
+
+ target.offsetWidth; // repaint
+
+ _css(target, 'transition', 'all ' + ms + 'ms');
+ _css(target, 'transform', 'translate3d(0,0,0)');
+
+ clearTimeout(target.animated);
+ target.animated = setTimeout(function () {
+ _css(target, 'transition', '');
+ _css(target, 'transform', '');
+ target.animated = false;
+ }, ms);
+ }
+ },
+
+ _offUpEvents: function () {
+ var ownerDocument = this.el.ownerDocument;
+
+ _off(document, 'touchmove', this._onTouchMove);
+ _off(document, 'pointermove', this._onTouchMove);
+ _off(ownerDocument, 'mouseup', this._onDrop);
+ _off(ownerDocument, 'touchend', this._onDrop);
+ _off(ownerDocument, 'pointerup', this._onDrop);
+ _off(ownerDocument, 'touchcancel', this._onDrop);
+ _off(ownerDocument, 'pointercancel', this._onDrop);
+ _off(ownerDocument, 'selectstart', this);
+ },
+
+ _onDrop: function (/**Event*/evt) {
+ var el = this.el,
+ options = this.options;
+
+ clearInterval(this._loopId);
+ clearInterval(autoScroll.pid);
+ clearTimeout(this._dragStartTimer);
+
+ _cancelNextTick(this._cloneId);
+ _cancelNextTick(this._dragStartId);
+
+ // Unbind events
+ _off(document, 'mouseover', this);
+ _off(document, 'mousemove', this._onTouchMove);
+
+ if (this.nativeDraggable) {
+ _off(document, 'drop', this);
+ _off(el, 'dragstart', this._onDragStart);
+ }
+
+ this._offUpEvents();
+
+ if (evt) {
+ if (moved) {
+ evt.preventDefault();
+ !options.dropBubble && evt.stopPropagation();
+ }
+
+ ghostEl && ghostEl.parentNode && ghostEl.parentNode.removeChild(ghostEl);
+
+ if (rootEl === parentEl || Sortable.active.lastPullMode !== 'clone') {
+ // Remove clone
+ cloneEl && cloneEl.parentNode && cloneEl.parentNode.removeChild(cloneEl);
+ }
+
+ if (dragEl) {
+ if (this.nativeDraggable) {
+ _off(dragEl, 'dragend', this);
+ }
+
+ _disableDraggable(dragEl);
+ // dragEl.style['will-change'] = '';
+
+ // Remove class's
+ _toggleClass(dragEl, this.options.ghostClass, false);
+ _toggleClass(dragEl, this.options.chosenClass, false);
+
+ // Drag stop event
+ _dispatchEvent(this, rootEl, 'unchoose', dragEl, parentEl, rootEl, oldIndex);
+
+ if (rootEl !== parentEl) {
+ newIndex = _index(dragEl, options.draggable);
+
+ if (newIndex >= 0) {
+ // Add event
+ _dispatchEvent(null, parentEl, 'add', dragEl, parentEl, rootEl, oldIndex, newIndex);
+
+ // Remove event
+ _dispatchEvent(this, rootEl, 'remove', dragEl, parentEl, rootEl, oldIndex, newIndex);
+
+ // drag from one list and drop into another
+ _dispatchEvent(null, parentEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex);
+ _dispatchEvent(this, rootEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex);
+ }
+ }
+ else {
+ if (dragEl.nextSibling !== nextEl) {
+ // Get the index of the dragged element within its parent
+ newIndex = _index(dragEl, options.draggable);
+
+ if (newIndex >= 0) {
+ // drag & drop within the same list
+ _dispatchEvent(this, rootEl, 'update', dragEl, parentEl, rootEl, oldIndex, newIndex);
+ _dispatchEvent(this, rootEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex);
+ }
+ }
+ }
+
+ if (Sortable.active) {
+ /* jshint eqnull:true */
+ if (newIndex == null || newIndex === -1) {
+ newIndex = oldIndex;
+ }
+
+ _dispatchEvent(this, rootEl, 'end', dragEl, parentEl, rootEl, oldIndex, newIndex);
+
+ // Save sorting
+ this.save();
+ }
+ }
+
+ }
+
+ this._nulling();
+ },
+
+ _nulling: function() {
+ rootEl =
+ dragEl =
+ parentEl =
+ ghostEl =
+ nextEl =
+ cloneEl =
+ lastDownEl =
+
+ scrollEl =
+ scrollParentEl =
+
+ tapEvt =
+ touchEvt =
+
+ moved =
+ newIndex =
+
+ lastEl =
+ lastCSS =
+
+ putSortable =
+ activeGroup =
+ Sortable.active = null;
+
+ savedInputChecked.forEach(function (el) {
+ el.checked = true;
+ });
+ savedInputChecked.length = 0;
+ },
+
+ handleEvent: function (/**Event*/evt) {
+ switch (evt.type) {
+ case 'drop':
+ case 'dragend':
+ this._onDrop(evt);
+ break;
+
+ case 'dragover':
+ case 'dragenter':
+ if (dragEl) {
+ this._onDragOver(evt);
+ _globalDragOver(evt);
+ }
+ break;
+
+ case 'mouseover':
+ this._onDrop(evt);
+ break;
+
+ case 'selectstart':
+ evt.preventDefault();
+ break;
+ }
+ },
+
+
+ /**
+ * Serializes the item into an array of string.
+ * @returns {String[]}
+ */
+ toArray: function () {
+ var order = [],
+ el,
+ children = this.el.children,
+ i = 0,
+ n = children.length,
+ options = this.options;
+
+ for (; i < n; i++) {
+ el = children[i];
+ if (_closest(el, options.draggable, this.el)) {
+ order.push(el.getAttribute(options.dataIdAttr) || _generateId(el));
+ }
+ }
+
+ return order;
+ },
+
+
+ /**
+ * Sorts the elements according to the array.
+ * @param {String[]} order order of the items
+ */
+ sort: function (order) {
+ var items = {}, rootEl = this.el;
+
+ this.toArray().forEach(function (id, i) {
+ var el = rootEl.children[i];
+
+ if (_closest(el, this.options.draggable, rootEl)) {
+ items[id] = el;
+ }
+ }, this);
+
+ order.forEach(function (id) {
+ if (items[id]) {
+ rootEl.removeChild(items[id]);
+ rootEl.appendChild(items[id]);
+ }
+ });
+ },
+
+
+ /**
+ * Save the current sorting
+ */
+ save: function () {
+ var store = this.options.store;
+ store && store.set(this);
+ },
+
+
+ /**
+ * For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
+ * @param {HTMLElement} el
+ * @param {String} [selector] default: `options.draggable`
+ * @returns {HTMLElement|null}
+ */
+ closest: function (el, selector) {
+ return _closest(el, selector || this.options.draggable, this.el);
+ },
+
+
+ /**
+ * Set/get option
+ * @param {string} name
+ * @param {*} [value]
+ * @returns {*}
+ */
+ option: function (name, value) {
+ var options = this.options;
+
+ if (value === void 0) {
+ return options[name];
+ } else {
+ options[name] = value;
+
+ if (name === 'group') {
+ _prepareGroup(options);
+ }
+ }
+ },
+
+
+ /**
+ * Destroy
+ */
+ destroy: function () {
+ var el = this.el;
+
+ el[expando] = null;
+
+ _off(el, 'mousedown', this._onTapStart);
+ _off(el, 'touchstart', this._onTapStart);
+ _off(el, 'pointerdown', this._onTapStart);
+
+ if (this.nativeDraggable) {
+ _off(el, 'dragover', this);
+ _off(el, 'dragenter', this);
+ }
+
+ // Remove draggable attributes
+ Array.prototype.forEach.call(el.querySelectorAll('[draggable]'), function (el) {
+ el.removeAttribute('draggable');
+ });
+
+ touchDragOverListeners.splice(touchDragOverListeners.indexOf(this._onDragOver), 1);
+
+ this._onDrop();
+
+ this.el = el = null;
+ }
+ };
+
+
+ function _cloneHide(sortable, state) {
+ if (sortable.lastPullMode !== 'clone') {
+ state = true;
+ }
+
+ if (cloneEl && (cloneEl.state !== state)) {
+ _css(cloneEl, 'display', state ? 'none' : '');
+
+ if (!state) {
+ if (cloneEl.state) {
+ if (sortable.options.group.revertClone) {
+ rootEl.insertBefore(cloneEl, nextEl);
+ sortable._animate(dragEl, cloneEl);
+ } else {
+ rootEl.insertBefore(cloneEl, dragEl);
+ }
+ }
+ }
+
+ cloneEl.state = state;
+ }
+ }
- autoScroll = {},
-
- tapEvt,
- touchEvt,
- moved,
+ function _closest(/**HTMLElement*/el, /**String*/selector, /**HTMLElement*/ctx) {
+ if (el) {
+ ctx = ctx || document;
- /** @const */
- R_SPACE = /\s+/g,
- R_FLOAT = /left|right|inline/,
-
- expando = 'Sortable' + (new Date).getTime(),
+ do {
+ if ((selector === '>*' && el.parentNode === ctx) || _matches(el, selector)) {
+ return el;
+ }
+ /* jshint boss:true */
+ } while (el = _getParentOrHost(el));
+ }
- win = window,
- document = win.document,
- parseInt = win.parseInt,
+ return null;
+ }
- $ = win.jQuery || win.Zepto,
- Polymer = win.Polymer,
-
- captureMode = false,
-
- supportDraggable = !!('draggable' in document.createElement('div')),
- supportCssPointerEvents = (function (el) {
- // false when IE11
- if (!!navigator.userAgent.match(/Trident.*rv[ :]?11\./)) {
- return false;
- }
- el = document.createElement('x');
- el.style.cssText = 'pointer-events:auto';
- return el.style.pointerEvents === 'auto';
- })(),
-
- _silent = false,
-
- abs = Math.abs,
- min = Math.min,
-
- savedInputChecked = [],
- touchDragOverListeners = [],
-
- _autoScroll = _throttle(function (/**Event*/evt, /**Object*/options, /**HTMLElement*/rootEl) {
- // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521
- if (rootEl && options.scroll) {
- var _this = rootEl[expando],
- el,
- rect,
- sens = options.scrollSensitivity,
- speed = options.scrollSpeed,
-
- x = evt.clientX,
- y = evt.clientY,
-
- winWidth = window.innerWidth,
- winHeight = window.innerHeight,
-
- vx,
- vy,
-
- scrollOffsetX,
- scrollOffsetY
- ;
-
- // Delect scrollEl
- if (scrollParentEl !== rootEl) {
- scrollEl = options.scroll;
- scrollParentEl = rootEl;
- scrollCustomFn = options.scrollFn;
-
- if (scrollEl === true) {
- scrollEl = rootEl;
-
- do {
- if ((scrollEl.offsetWidth < scrollEl.scrollWidth) ||
- (scrollEl.offsetHeight < scrollEl.scrollHeight)
- ) {
- break;
- }
- /* jshint boss:true */
- } while (scrollEl = scrollEl.parentNode);
- }
- }
-
- if (scrollEl) {
- el = scrollEl;
- rect = scrollEl.getBoundingClientRect();
- vx = (abs(rect.right - x) <= sens) - (abs(rect.left - x) <= sens);
- vy = (abs(rect.bottom - y) <= sens) - (abs(rect.top - y) <= sens);
- }
-
-
- if (!(vx || vy)) {
- vx = (winWidth - x <= sens) - (x <= sens);
- vy = (winHeight - y <= sens) - (y <= sens);
-
- /* jshint expr:true */
- (vx || vy) && (el = win);
- }
-
-
- if (autoScroll.vx !== vx || autoScroll.vy !== vy || autoScroll.el !== el) {
- autoScroll.el = el;
- autoScroll.vx = vx;
- autoScroll.vy = vy;
-
- clearInterval(autoScroll.pid);
-
- if (el) {
- autoScroll.pid = setInterval(function () {
- scrollOffsetY = vy ? vy * speed : 0;
- scrollOffsetX = vx ? vx * speed : 0;
-
- if ('function' === typeof(scrollCustomFn)) {
- return scrollCustomFn.call(_this, scrollOffsetX, scrollOffsetY, evt);
- }
-
- if (el === win) {
- win.scrollTo(win.pageXOffset + scrollOffsetX, win.pageYOffset + scrollOffsetY);
- } else {
- el.scrollTop += scrollOffsetY;
- el.scrollLeft += scrollOffsetX;
- }
- }, 24);
- }
- }
- }
- }, 30),
-
- _prepareGroup = function (options) {
- function toFn(value, pull) {
- if (value === void 0 || value === true) {
- value = group.name;
- }
-
- if (typeof value === 'function') {
- return value;
- } else {
- return function (to, from) {
- var fromGroup = from.options.group.name;
-
- return pull
- ? value
- : value && (value.join
- ? value.indexOf(fromGroup) > -1
- : (fromGroup == value)
- );
- };
- }
- }
-
- var group = {};
- var originalGroup = options.group;
-
- if (!originalGroup || typeof originalGroup != 'object') {
- originalGroup = {name: originalGroup};
- }
-
- group.name = originalGroup.name;
- group.checkPull = toFn(originalGroup.pull, true);
- group.checkPut = toFn(originalGroup.put);
- group.revertClone = originalGroup.revertClone;
-
- options.group = group;
- }
- ;
-
-
- /**
- * @class Sortable
- * @param {HTMLElement} el
- * @param {Object} [options]
- */
- function Sortable(el, options) {
- if (!(el && el.nodeType && el.nodeType === 1)) {
- throw 'Sortable: `el` must be HTMLElement, and not ' + {}.toString.call(el);
- }
-
- this.el = el; // root element
- this.options = options = _extend({}, options);
-
-
- // Export instance
- el[expando] = this;
-
- // Default options
- var defaults = {
- group: Math.random(),
- sort: true,
- disabled: false,
- store: null,
- handle: null,
- scroll: true,
- scrollSensitivity: 30,
- scrollSpeed: 10,
- draggable: /[uo]l/i.test(el.nodeName) ? 'li' : '>*',
- ghostClass: 'sortable-ghost',
- chosenClass: 'sortable-chosen',
- dragClass: 'sortable-drag',
- ignore: 'a, img',
- filter: null,
- preventOnFilter: true,
- animation: 0,
- setData: function (dataTransfer, dragEl) {
- dataTransfer.setData('Text', dragEl.textContent);
- },
- dropBubble: false,
- dragoverBubble: false,
- dataIdAttr: 'data-id',
- delay: 0,
- forceFallback: false,
- fallbackClass: 'sortable-fallback',
- fallbackOnBody: false,
- fallbackTolerance: 0,
- fallbackOffset: {x: 0, y: 0}
- };
-
-
- // Set default options
- for (var name in defaults) {
- !(name in options) && (options[name] = defaults[name]);
- }
-
- _prepareGroup(options);
-
- // Bind all private methods
- for (var fn in this) {
- if (fn.charAt(0) === '_' && typeof this[fn] === 'function') {
- this[fn] = this[fn].bind(this);
- }
- }
-
- // Setup drag mode
- this.nativeDraggable = options.forceFallback ? false : supportDraggable;
-
- // Bind events
- _on(el, 'mousedown', this._onTapStart);
- _on(el, 'touchstart', this._onTapStart);
- _on(el, 'pointerdown', this._onTapStart);
-
- if (this.nativeDraggable) {
- _on(el, 'dragover', this);
- _on(el, 'dragenter', this);
- }
-
- touchDragOverListeners.push(this._onDragOver);
-
- // Restore sorting
- options.store && this.sort(options.store.get(this));
- }
-
-
- Sortable.prototype = /** @lends Sortable.prototype */ {
- constructor: Sortable,
-
- _onTapStart: function (/** Event|TouchEvent */evt) {
- var _this = this,
- el = this.el,
- options = this.options,
- preventOnFilter = options.preventOnFilter,
- type = evt.type,
- touch = evt.touches && evt.touches[0],
- target = (touch || evt).target,
- originalTarget = evt.target.shadowRoot && evt.path[0] || target,
- filter = options.filter,
- startIndex;
-
- _saveInputCheckedState(el);
-
-
- // Don't trigger start event when an element is been dragged, otherwise the evt.oldindex always wrong when set option.group.
- if (dragEl) {
- return;
- }
-
- if (type === 'mousedown' && evt.button !== 0 || options.disabled) {
- return; // only left button or enabled
- }
-
-
- target = _closest(target, options.draggable, el);
-
- if (!target) {
- return;
- }
-
- if (lastDownEl === target) {
- // Ignoring duplicate `down`
- return;
- }
-
- // Get the index of the dragged element within its parent
- startIndex = _index(target, options.draggable);
-
- // Check filter
- if (typeof filter === 'function') {
- if (filter.call(this, evt, target, this)) {
- _dispatchEvent(_this, originalTarget, 'filter', target, el, startIndex);
- preventOnFilter && evt.preventDefault();
- return; // cancel dnd
- }
- }
- else if (filter) {
- filter = filter.split(',').some(function (criteria) {
- criteria = _closest(originalTarget, criteria.trim(), el);
-
- if (criteria) {
- _dispatchEvent(_this, criteria, 'filter', target, el, startIndex);
- return true;
- }
- });
-
- if (filter) {
- preventOnFilter && evt.preventDefault();
- return; // cancel dnd
- }
- }
-
- if (options.handle && !_closest(originalTarget, options.handle, el)) {
- return;
- }
-
- // Prepare `dragstart`
- this._prepareDragStart(evt, touch, target, startIndex);
- },
-
- _prepareDragStart: function (/** Event */evt, /** Touch */touch, /** HTMLElement */target, /** Number */startIndex) {
- var _this = this,
- el = _this.el,
- options = _this.options,
- ownerDocument = el.ownerDocument,
- dragStartFn;
-
- if (target && !dragEl && (target.parentNode === el)) {
- tapEvt = evt;
-
- rootEl = el;
- dragEl = target;
- parentEl = dragEl.parentNode;
- nextEl = dragEl.nextSibling;
- lastDownEl = target;
- activeGroup = options.group;
- oldIndex = startIndex;
-
- this._lastX = (touch || evt).clientX;
- this._lastY = (touch || evt).clientY;
-
- // dragEl.style['will-change'] = 'transform';
-
- dragStartFn = function () {
- // Delayed drag has been triggered
- // we can re-enable the events: touchmove/mousemove
- _this._disableDelayedDrag();
-
- // Make the element draggable
- dragEl.draggable = _this.nativeDraggable;
-
- // Chosen item
- _toggleClass(dragEl, options.chosenClass, true);
-
- // Bind the events: dragstart/dragend
- _this._triggerDragStart(evt, touch);
-
- // Drag start event
- _dispatchEvent(_this, rootEl, 'choose', dragEl, rootEl, oldIndex);
- };
-
- // Disable "draggable"
- options.ignore.split(',').forEach(function (criteria) {
- _find(dragEl, criteria.trim(), _disableDraggable);
- });
-
- _on(ownerDocument, 'mouseup', _this._onDrop);
- _on(ownerDocument, 'touchend', _this._onDrop);
- _on(ownerDocument, 'touchcancel', _this._onDrop);
- _on(ownerDocument, 'pointercancel', _this._onDrop);
- _on(ownerDocument, 'selectstart', _this);
-
- if (options.delay) {
- // If the user moves the pointer or let go the click or touch
- // before the delay has been reached:
- // disable the delayed drag
- _on(ownerDocument, 'mouseup', _this._disableDelayedDrag);
- _on(ownerDocument, 'touchend', _this._disableDelayedDrag);
- _on(ownerDocument, 'touchcancel', _this._disableDelayedDrag);
- _on(ownerDocument, 'mousemove', _this._disableDelayedDrag);
- _on(ownerDocument, 'touchmove', _this._disableDelayedDrag);
- _on(ownerDocument, 'pointermove', _this._disableDelayedDrag);
-
- _this._dragStartTimer = setTimeout(dragStartFn, options.delay);
- } else {
- dragStartFn();
- }
-
-
- }
- },
-
- _disableDelayedDrag: function () {
- var ownerDocument = this.el.ownerDocument;
-
- clearTimeout(this._dragStartTimer);
- _off(ownerDocument, 'mouseup', this._disableDelayedDrag);
- _off(ownerDocument, 'touchend', this._disableDelayedDrag);
- _off(ownerDocument, 'touchcancel', this._disableDelayedDrag);
- _off(ownerDocument, 'mousemove', this._disableDelayedDrag);
- _off(ownerDocument, 'touchmove', this._disableDelayedDrag);
- _off(ownerDocument, 'pointermove', this._disableDelayedDrag);
- },
-
- _triggerDragStart: function (/** Event */evt, /** Touch */touch) {
- touch = touch || (evt.pointerType == 'touch' ? evt : null);
-
- if (touch) {
- // Touch device support
- tapEvt = {
- target: dragEl,
- clientX: touch.clientX,
- clientY: touch.clientY
- };
-
- this._onDragStart(tapEvt, 'touch');
- }
- else if (!this.nativeDraggable) {
- this._onDragStart(tapEvt, true);
- }
- else {
- _on(dragEl, 'dragend', this);
- _on(rootEl, 'dragstart', this._onDragStart);
- }
-
- try {
- if (document.selection) {
- // Timeout neccessary for IE9
- setTimeout(function () {
- document.selection.empty();
- });
- } else {
- window.getSelection().removeAllRanges();
- }
- } catch (err) {
- }
- },
-
- _dragStarted: function () {
- if (rootEl && dragEl) {
- var options = this.options;
-
- // Apply effect
- _toggleClass(dragEl, options.ghostClass, true);
- _toggleClass(dragEl, options.dragClass, false);
-
- Sortable.active = this;
-
- // Drag start event
- _dispatchEvent(this, rootEl, 'start', dragEl, rootEl, oldIndex);
- } else {
- this._nulling();
- }
- },
-
- _emulateDragOver: function () {
- if (touchEvt) {
- if (this._lastX === touchEvt.clientX && this._lastY === touchEvt.clientY) {
- return;
- }
-
- this._lastX = touchEvt.clientX;
- this._lastY = touchEvt.clientY;
-
- if (!supportCssPointerEvents) {
- _css(ghostEl, 'display', 'none');
- }
-
- var target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY),
- parent = target,
- i = touchDragOverListeners.length;
-
- if (parent) {
- do {
- if (parent[expando]) {
- while (i--) {
- touchDragOverListeners[i]({
- clientX: touchEvt.clientX,
- clientY: touchEvt.clientY,
- target: target,
- rootEl: parent
- });
- }
-
- break;
- }
-
- target = parent; // store last element
- }
- /* jshint boss:true */
- while (parent = parent.parentNode);
- }
-
- if (!supportCssPointerEvents) {
- _css(ghostEl, 'display', '');
- }
- }
- },
-
-
- _onTouchMove: function (/**TouchEvent*/evt) {
- if (tapEvt) {
- var options = this.options,
- fallbackTolerance = options.fallbackTolerance,
- fallbackOffset = options.fallbackOffset,
- touch = evt.touches ? evt.touches[0] : evt,
- dx = (touch.clientX - tapEvt.clientX) + fallbackOffset.x,
- dy = (touch.clientY - tapEvt.clientY) + fallbackOffset.y,
- translate3d = evt.touches ? 'translate3d(' + dx + 'px,' + dy + 'px,0)' : 'translate(' + dx + 'px,' + dy + 'px)';
-
- // only set the status to dragging, when we are actually dragging
- if (!Sortable.active) {
- if (fallbackTolerance &&
- min(abs(touch.clientX - this._lastX), abs(touch.clientY - this._lastY)) < fallbackTolerance
- ) {
- return;
- }
-
- this._dragStarted();
- }
-
- // as well as creating the ghost element on the document body
- this._appendGhost();
-
- moved = true;
- touchEvt = touch;
-
- _css(ghostEl, 'webkitTransform', translate3d);
- _css(ghostEl, 'mozTransform', translate3d);
- _css(ghostEl, 'msTransform', translate3d);
- _css(ghostEl, 'transform', translate3d);
-
- evt.preventDefault();
- }
- },
-
- _appendGhost: function () {
- if (!ghostEl) {
- var rect = dragEl.getBoundingClientRect(),
- css = _css(dragEl),
- options = this.options,
- ghostRect;
-
- ghostEl = dragEl.cloneNode(true);
-
- _toggleClass(ghostEl, options.ghostClass, false);
- _toggleClass(ghostEl, options.fallbackClass, true);
- _toggleClass(ghostEl, options.dragClass, true);
-
- _css(ghostEl, 'top', rect.top - parseInt(css.marginTop, 10));
- _css(ghostEl, 'left', rect.left - parseInt(css.marginLeft, 10));
- _css(ghostEl, 'width', rect.width);
- _css(ghostEl, 'height', rect.height);
- _css(ghostEl, 'opacity', '0.8');
- _css(ghostEl, 'position', 'fixed');
- _css(ghostEl, 'zIndex', '100000');
- _css(ghostEl, 'pointerEvents', 'none');
-
- options.fallbackOnBody && document.body.appendChild(ghostEl) || rootEl.appendChild(ghostEl);
-
- // Fixing dimensions.
- ghostRect = ghostEl.getBoundingClientRect();
- _css(ghostEl, 'width', rect.width * 2 - ghostRect.width);
- _css(ghostEl, 'height', rect.height * 2 - ghostRect.height);
- }
- },
-
- _onDragStart: function (/**Event*/evt, /**boolean*/useFallback) {
- var dataTransfer = evt.dataTransfer,
- options = this.options;
-
- this._offUpEvents();
-
- if (activeGroup.checkPull(this, this, dragEl, evt)) {
- cloneEl = _clone(dragEl);
-
- cloneEl.draggable = false;
- // cloneEl.style['will-change'] = '';
-
- _css(cloneEl, 'display', 'none');
- _toggleClass(cloneEl, this.options.chosenClass, false);
-
- rootEl.insertBefore(cloneEl, dragEl);
- _dispatchEvent(this, rootEl, 'clone', dragEl);
- }
-
- _toggleClass(dragEl, options.dragClass, true);
-
- if (useFallback) {
- if (useFallback === 'touch') {
- // Bind touch events
- _on(document, 'touchmove', this._onTouchMove);
- _on(document, 'touchend', this._onDrop);
- _on(document, 'touchcancel', this._onDrop);
- _on(document, 'pointermove', this._onTouchMove);
- _on(document, 'pointerup', this._onDrop);
- } else {
- // Old brwoser
- _on(document, 'mousemove', this._onTouchMove);
- _on(document, 'mouseup', this._onDrop);
- }
-
- this._loopId = setInterval(this._emulateDragOver, 50);
- }
- else {
- if (dataTransfer) {
- dataTransfer.effectAllowed = 'move';
- options.setData && options.setData.call(this, dataTransfer, dragEl);
- }
-
- _on(document, 'drop', this);
- setTimeout(this._dragStarted, 0);
- }
- },
-
- _onDragOver: function (/**Event*/evt) {
- var el = this.el,
- target,
- dragRect,
- targetRect,
- revert,
- options = this.options,
- group = options.group,
- activeSortable = Sortable.active,
- isOwner = (activeGroup === group),
- isMovingBetweenSortable = false,
- canSort = options.sort;
-
- if (evt.preventDefault !== void 0) {
- evt.preventDefault();
- !options.dragoverBubble && evt.stopPropagation();
- }
-
- if (dragEl.animated) {
- return;
- }
-
- moved = true;
-
- if (activeSortable && !options.disabled &&
- (isOwner
- ? canSort || (revert = !rootEl.contains(dragEl)) // Reverting item into the original list
- : (
- putSortable === this ||
- (
- (activeSortable.lastPullMode = activeGroup.checkPull(this, activeSortable, dragEl, evt)) &&
- group.checkPut(this, activeSortable, dragEl, evt)
- )
- )
- ) &&
- (evt.rootEl === void 0 || evt.rootEl === this.el) // touch fallback
- ) {
- // Smart auto-scrolling
- _autoScroll(evt, options, this.el);
-
- if (_silent) {
- return;
- }
-
- target = _closest(evt.target, options.draggable, el);
- dragRect = dragEl.getBoundingClientRect();
-
- if (putSortable !== this) {
- putSortable = this;
- isMovingBetweenSortable = true;
- }
-
- if (revert) {
- _cloneHide(activeSortable, true);
- parentEl = rootEl; // actualization
-
- if (cloneEl || nextEl) {
- rootEl.insertBefore(dragEl, cloneEl || nextEl);
- }
- else if (!canSort) {
- rootEl.appendChild(dragEl);
- }
-
- return;
- }
-
-
- if ((el.children.length === 0) || (el.children[0] === ghostEl) ||
- (el === evt.target) && (_ghostIsLast(el, evt))
- ) {
- //assign target only if condition is true
- if (el.children.length !== 0 && el.children[0] !== ghostEl && el === evt.target) {
- target = el.lastElementChild;
- }
-
- if (target) {
- if (target.animated) {
- return;
- }
-
- targetRect = target.getBoundingClientRect();
- }
-
- _cloneHide(activeSortable, isOwner);
-
- if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt) !== false) {
- if (!dragEl.contains(el)) {
- el.appendChild(dragEl);
- parentEl = el; // actualization
- }
-
- this._animate(dragRect, dragEl);
- target && this._animate(targetRect, target);
- }
- }
- else if (target && !target.animated && target !== dragEl && (target.parentNode[expando] !== void 0)) {
- if (lastEl !== target) {
- lastEl = target;
- lastCSS = _css(target);
- lastParentCSS = _css(target.parentNode);
- }
-
- targetRect = target.getBoundingClientRect();
-
- var width = targetRect.right - targetRect.left,
- height = targetRect.bottom - targetRect.top,
- floating = R_FLOAT.test(lastCSS.cssFloat + lastCSS.display)
- || (lastParentCSS.display == 'flex' && lastParentCSS['flex-direction'].indexOf('row') === 0),
- isWide = (target.offsetWidth > dragEl.offsetWidth),
- isLong = (target.offsetHeight > dragEl.offsetHeight),
- halfway = (floating ? (evt.clientX - targetRect.left) / width : (evt.clientY - targetRect.top) / height) > 0.5,
- nextSibling = target.nextElementSibling,
- after = false
- ;
-
- if (floating) {
- var elTop = dragEl.offsetTop,
- tgTop = target.offsetTop;
-
- if (elTop === tgTop) {
- after = (target.previousElementSibling === dragEl) && !isWide || halfway && isWide;
- }
- else if (target.previousElementSibling === dragEl || dragEl.previousElementSibling === target) {
- after = (evt.clientY - targetRect.top) / height > 0.5;
- } else {
- after = tgTop > elTop;
- }
- } else if (!isMovingBetweenSortable) {
- after = (nextSibling !== dragEl) && !isLong || halfway && isLong;
- }
-
- var moveVector = _onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, after);
-
- if (moveVector !== false) {
- if (moveVector === 1 || moveVector === -1) {
- after = (moveVector === 1);
- }
-
- _silent = true;
- setTimeout(_unsilent, 30);
-
- _cloneHide(activeSortable, isOwner);
-
- if (!dragEl.contains(el)) {
- if (after && !nextSibling) {
- el.appendChild(dragEl);
- } else {
- target.parentNode.insertBefore(dragEl, after ? nextSibling : target);
- }
- }
-
- parentEl = dragEl.parentNode; // actualization
-
- this._animate(dragRect, dragEl);
- this._animate(targetRect, target);
- }
- }
- }
- },
-
- _animate: function (prevRect, target) {
- var ms = this.options.animation;
-
- if (ms) {
- var currentRect = target.getBoundingClientRect();
-
- if (prevRect.nodeType === 1) {
- prevRect = prevRect.getBoundingClientRect();
- }
-
- _css(target, 'transition', 'none');
- _css(target, 'transform', 'translate3d('
- + (prevRect.left - currentRect.left) + 'px,'
- + (prevRect.top - currentRect.top) + 'px,0)'
- );
-
- target.offsetWidth; // repaint
-
- _css(target, 'transition', 'all ' + ms + 'ms');
- _css(target, 'transform', 'translate3d(0,0,0)');
-
- clearTimeout(target.animated);
- target.animated = setTimeout(function () {
- _css(target, 'transition', '');
- _css(target, 'transform', '');
- target.animated = false;
- }, ms);
- }
- },
-
- _offUpEvents: function () {
- var ownerDocument = this.el.ownerDocument;
-
- _off(document, 'touchmove', this._onTouchMove);
- _off(document, 'pointermove', this._onTouchMove);
- _off(ownerDocument, 'mouseup', this._onDrop);
- _off(ownerDocument, 'touchend', this._onDrop);
- _off(ownerDocument, 'pointerup', this._onDrop);
- _off(ownerDocument, 'touchcancel', this._onDrop);
- _off(ownerDocument, 'pointercancel', this._onDrop);
- _off(ownerDocument, 'selectstart', this);
- },
-
- _onDrop: function (/**Event*/evt) {
- var el = this.el,
- options = this.options;
-
- clearInterval(this._loopId);
- clearInterval(autoScroll.pid);
- clearTimeout(this._dragStartTimer);
-
- // Unbind events
- _off(document, 'mousemove', this._onTouchMove);
-
- if (this.nativeDraggable) {
- _off(document, 'drop', this);
- _off(el, 'dragstart', this._onDragStart);
- }
-
- this._offUpEvents();
-
- if (evt) {
- if (moved) {
- evt.preventDefault();
- !options.dropBubble && evt.stopPropagation();
- }
-
- ghostEl && ghostEl.parentNode && ghostEl.parentNode.removeChild(ghostEl);
-
- if (rootEl === parentEl || Sortable.active.lastPullMode !== 'clone') {
- // Remove clone
- cloneEl && cloneEl.parentNode && cloneEl.parentNode.removeChild(cloneEl);
- }
-
- if (dragEl) {
- if (this.nativeDraggable) {
- _off(dragEl, 'dragend', this);
- }
-
- _disableDraggable(dragEl);
- // dragEl.style['will-change'] = '';
-
- // Remove class's
- _toggleClass(dragEl, this.options.ghostClass, false);
- _toggleClass(dragEl, this.options.chosenClass, false);
-
- // Drag stop event
- _dispatchEvent(this, rootEl, 'unchoose', dragEl, rootEl, oldIndex);
-
- if (rootEl !== parentEl) {
- newIndex = _index(dragEl, options.draggable);
-
- if (newIndex >= 0) {
- // Add event
- _dispatchEvent(null, parentEl, 'add', dragEl, rootEl, oldIndex, newIndex);
-
- // Remove event
- _dispatchEvent(this, rootEl, 'remove', dragEl, rootEl, oldIndex, newIndex);
-
- // drag from one list and drop into another
- _dispatchEvent(null, parentEl, 'sort', dragEl, rootEl, oldIndex, newIndex);
- _dispatchEvent(this, rootEl, 'sort', dragEl, rootEl, oldIndex, newIndex);
- }
- }
- else {
- if (dragEl.nextSibling !== nextEl) {
- // Get the index of the dragged element within its parent
- newIndex = _index(dragEl, options.draggable);
-
- if (newIndex >= 0) {
- // drag & drop within the same list
- _dispatchEvent(this, rootEl, 'update', dragEl, rootEl, oldIndex, newIndex);
- _dispatchEvent(this, rootEl, 'sort', dragEl, rootEl, oldIndex, newIndex);
- }
- }
- }
-
- if (Sortable.active) {
- /* jshint eqnull:true */
- if (newIndex == null || newIndex === -1) {
- newIndex = oldIndex;
- }
-
- _dispatchEvent(this, rootEl, 'end', dragEl, rootEl, oldIndex, newIndex);
-
- // Save sorting
- this.save();
- }
- }
-
- }
-
- this._nulling();
- },
-
- _nulling: function() {
- rootEl =
- dragEl =
- parentEl =
- ghostEl =
- nextEl =
- cloneEl =
- lastDownEl =
-
- scrollEl =
- scrollParentEl =
-
- tapEvt =
- touchEvt =
-
- moved =
- newIndex =
-
- lastEl =
- lastCSS =
-
- putSortable =
- activeGroup =
- Sortable.active = null;
-
- savedInputChecked.forEach(function (el) {
- el.checked = true;
- });
- savedInputChecked.length = 0;
- },
-
- handleEvent: function (/**Event*/evt) {
- switch (evt.type) {
- case 'drop':
- case 'dragend':
- this._onDrop(evt);
- break;
-
- case 'dragover':
- case 'dragenter':
- if (dragEl) {
- this._onDragOver(evt);
- _globalDragOver(evt);
- }
- break;
-
- case 'selectstart':
- evt.preventDefault();
- break;
- }
- },
-
-
- /**
- * Serializes the item into an array of string.
- * @returns {String[]}
- */
- toArray: function () {
- var order = [],
- el,
- children = this.el.children,
- i = 0,
- n = children.length,
- options = this.options;
-
- for (; i < n; i++) {
- el = children[i];
- if (_closest(el, options.draggable, this.el)) {
- order.push(el.getAttribute(options.dataIdAttr) || _generateId(el));
- }
- }
-
- return order;
- },
-
-
- /**
- * Sorts the elements according to the array.
- * @param {String[]} order order of the items
- */
- sort: function (order) {
- var items = {}, rootEl = this.el;
-
- this.toArray().forEach(function (id, i) {
- var el = rootEl.children[i];
-
- if (_closest(el, this.options.draggable, rootEl)) {
- items[id] = el;
- }
- }, this);
-
- order.forEach(function (id) {
- if (items[id]) {
- rootEl.removeChild(items[id]);
- rootEl.appendChild(items[id]);
- }
- });
- },
-
-
- /**
- * Save the current sorting
- */
- save: function () {
- var store = this.options.store;
- store && store.set(this);
- },
-
-
- /**
- * For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
- * @param {HTMLElement} el
- * @param {String} [selector] default: `options.draggable`
- * @returns {HTMLElement|null}
- */
- closest: function (el, selector) {
- return _closest(el, selector || this.options.draggable, this.el);
- },
-
-
- /**
- * Set/get option
- * @param {string} name
- * @param {*} [value]
- * @returns {*}
- */
- option: function (name, value) {
- var options = this.options;
-
- if (value === void 0) {
- return options[name];
- } else {
- options[name] = value;
-
- if (name === 'group') {
- _prepareGroup(options);
- }
- }
- },
-
-
- /**
- * Destroy
- */
- destroy: function () {
- var el = this.el;
-
- el[expando] = null;
-
- _off(el, 'mousedown', this._onTapStart);
- _off(el, 'touchstart', this._onTapStart);
- _off(el, 'pointerdown', this._onTapStart);
-
- if (this.nativeDraggable) {
- _off(el, 'dragover', this);
- _off(el, 'dragenter', this);
- }
-
- // Remove draggable attributes
- Array.prototype.forEach.call(el.querySelectorAll('[draggable]'), function (el) {
- el.removeAttribute('draggable');
- });
-
- touchDragOverListeners.splice(touchDragOverListeners.indexOf(this._onDragOver), 1);
-
- this._onDrop();
-
- this.el = el = null;
- }
- };
-
-
- function _cloneHide(sortable, state) {
- if (sortable.lastPullMode !== 'clone') {
- state = true;
- }
-
- if (cloneEl && (cloneEl.state !== state)) {
- _css(cloneEl, 'display', state ? 'none' : '');
-
- if (!state) {
- if (cloneEl.state) {
- if (sortable.options.group.revertClone) {
- rootEl.insertBefore(cloneEl, nextEl);
- sortable._animate(dragEl, cloneEl);
- } else {
- rootEl.insertBefore(cloneEl, dragEl);
- }
- }
- }
-
- cloneEl.state = state;
- }
- }
+ function _getParentOrHost(el) {
+ var parent = el.host;
- function _closest(/**HTMLElement*/el, /**String*/selector, /**HTMLElement*/ctx) {
- if (el) {
- ctx = ctx || document;
+ return (parent && parent.nodeType) ? parent : el.parentNode;
+ }
- do {
- if ((selector === '>*' && el.parentNode === ctx) || _matches(el, selector)) {
- return el;
- }
- /* jshint boss:true */
- } while (el = _getParentOrHost(el));
- }
- return null;
- }
+ function _globalDragOver(/**Event*/evt) {
+ if (evt.dataTransfer) {
+ evt.dataTransfer.dropEffect = 'move';
+ }
+ evt.preventDefault();
+ }
- function _getParentOrHost(el) {
- var parent = el.host;
+ function _on(el, event, fn) {
+ el.addEventListener(event, fn, captureMode);
+ }
- return (parent && parent.nodeType) ? parent : el.parentNode;
- }
+ function _off(el, event, fn) {
+ el.removeEventListener(event, fn, captureMode);
+ }
- function _globalDragOver(/**Event*/evt) {
- if (evt.dataTransfer) {
- evt.dataTransfer.dropEffect = 'move';
- }
- evt.preventDefault();
- }
+ function _toggleClass(el, name, state) {
+ if (el) {
+ if (el.classList) {
+ el.classList[state ? 'add' : 'remove'](name);
+ }
+ else {
+ var className = (' ' + el.className + ' ').replace(R_SPACE, ' ').replace(' ' + name + ' ', ' ');
+ el.className = (className + (state ? ' ' + name : '')).replace(R_SPACE, ' ');
+ }
+ }
+ }
- function _on(el, event, fn) {
- el.addEventListener(event, fn, captureMode);
- }
+ function _css(el, prop, val) {
+ var style = el && el.style;
- function _off(el, event, fn) {
- el.removeEventListener(event, fn, captureMode);
- }
+ if (style) {
+ if (val === void 0) {
+ if (document.defaultView && document.defaultView.getComputedStyle) {
+ val = document.defaultView.getComputedStyle(el, '');
+ }
+ else if (el.currentStyle) {
+ val = el.currentStyle;
+ }
+ return prop === void 0 ? val : val[prop];
+ }
+ else {
+ if (!(prop in style)) {
+ prop = '-webkit-' + prop;
+ }
- function _toggleClass(el, name, state) {
- if (el) {
- if (el.classList) {
- el.classList[state ? 'add' : 'remove'](name);
- }
- else {
- var className = (' ' + el.className + ' ').replace(R_SPACE, ' ').replace(' ' + name + ' ', ' ');
- el.className = (className + (state ? ' ' + name : '')).replace(R_SPACE, ' ');
- }
- }
- }
+ style[prop] = val + (typeof val === 'string' ? '' : 'px');
+ }
+ }
+ }
- function _css(el, prop, val) {
- var style = el && el.style;
+ function _find(ctx, tagName, iterator) {
+ if (ctx) {
+ var list = ctx.getElementsByTagName(tagName), i = 0, n = list.length;
- if (style) {
- if (val === void 0) {
- if (document.defaultView && document.defaultView.getComputedStyle) {
- val = document.defaultView.getComputedStyle(el, '');
- }
- else if (el.currentStyle) {
- val = el.currentStyle;
- }
+ if (iterator) {
+ for (; i < n; i++) {
+ iterator(list[i], i);
+ }
+ }
- return prop === void 0 ? val : val[prop];
- }
- else {
- if (!(prop in style)) {
- prop = '-webkit-' + prop;
- }
+ return list;
+ }
- style[prop] = val + (typeof val === 'string' ? '' : 'px');
- }
- }
- }
+ return [];
+ }
- function _find(ctx, tagName, iterator) {
- if (ctx) {
- var list = ctx.getElementsByTagName(tagName), i = 0, n = list.length;
- if (iterator) {
- for (; i < n; i++) {
- iterator(list[i], i);
- }
- }
+ function _dispatchEvent(sortable, rootEl, name, targetEl, toEl, fromEl, startIndex, newIndex) {
+ sortable = (sortable || rootEl[expando]);
- return list;
- }
+ var evt = document.createEvent('Event'),
+ options = sortable.options,
+ onName = 'on' + name.charAt(0).toUpperCase() + name.substr(1);
- return [];
- }
+ evt.initEvent(name, true, true);
+ evt.to = toEl || rootEl;
+ evt.from = fromEl || rootEl;
+ evt.item = targetEl || rootEl;
+ evt.clone = cloneEl;
+ evt.oldIndex = startIndex;
+ evt.newIndex = newIndex;
- function _dispatchEvent(sortable, rootEl, name, targetEl, fromEl, startIndex, newIndex) {
- sortable = (sortable || rootEl[expando]);
+ rootEl.dispatchEvent(evt);
- var evt = document.createEvent('Event'),
- options = sortable.options,
- onName = 'on' + name.charAt(0).toUpperCase() + name.substr(1);
+ if (options[onName]) {
+ options[onName].call(sortable, evt);
+ }
+ }
- evt.initEvent(name, true, true);
- evt.to = rootEl;
- evt.from = fromEl || rootEl;
- evt.item = targetEl || rootEl;
- evt.clone = cloneEl;
+ function _onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect, originalEvt, willInsertAfter) {
+ var evt,
+ sortable = fromEl[expando],
+ onMoveFn = sortable.options.onMove,
+ retVal;
- evt.oldIndex = startIndex;
- evt.newIndex = newIndex;
+ evt = document.createEvent('Event');
+ evt.initEvent('move', true, true);
- rootEl.dispatchEvent(evt);
+ evt.to = toEl;
+ evt.from = fromEl;
+ evt.dragged = dragEl;
+ evt.draggedRect = dragRect;
+ evt.related = targetEl || toEl;
+ evt.relatedRect = targetRect || toEl.getBoundingClientRect();
+ evt.willInsertAfter = willInsertAfter;
+
+ fromEl.dispatchEvent(evt);
+
+ if (onMoveFn) {
+ retVal = onMoveFn.call(sortable, evt, originalEvt);
+ }
+
+ return retVal;
+ }
- if (options[onName]) {
- options[onName].call(sortable, evt);
- }
- }
+ function _disableDraggable(el) {
+ el.draggable = false;
+ }
- function _onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect, originalEvt, willInsertAfter) {
- var evt,
- sortable = fromEl[expando],
- onMoveFn = sortable.options.onMove,
- retVal;
-
- evt = document.createEvent('Event');
- evt.initEvent('move', true, true);
-
- evt.to = toEl;
- evt.from = fromEl;
- evt.dragged = dragEl;
- evt.draggedRect = dragRect;
- evt.related = targetEl || toEl;
- evt.relatedRect = targetRect || toEl.getBoundingClientRect();
- evt.willInsertAfter = willInsertAfter;
-
- fromEl.dispatchEvent(evt);
-
- if (onMoveFn) {
- retVal = onMoveFn.call(sortable, evt, originalEvt);
- }
-
- return retVal;
- }
-
-
- function _disableDraggable(el) {
- el.draggable = false;
- }
-
-
- function _unsilent() {
- _silent = false;
- }
-
-
- /** @returns {HTMLElement|false} */
- function _ghostIsLast(el, evt) {
- var lastEl = el.lastElementChild,
- rect = lastEl.getBoundingClientRect();
-
- // 5 — min delta
- // abs — нельзя добавлять, а то глюки при наведении сверху
- return (evt.clientY - (rect.top + rect.height) > 5) ||
- (evt.clientX - (rect.left + rect.width) > 5);
- }
-
-
- /**
- * Generate id
- * @param {HTMLElement} el
- * @returns {String}
- * @private
- */
- function _generateId(el) {
- var str = el.tagName + el.className + el.src + el.href + el.textContent,
- i = str.length,
- sum = 0;
-
- while (i--) {
- sum += str.charCodeAt(i);
- }
-
- return sum.toString(36);
- }
-
- /**
- * Returns the index of an element within its parent for a selected set of
- * elements
- * @param {HTMLElement} el
- * @param {selector} selector
- * @return {number}
- */
- function _index(el, selector) {
- var index = 0;
-
- if (!el || !el.parentNode) {
- return -1;
- }
-
- while (el && (el = el.previousElementSibling)) {
- if ((el.nodeName.toUpperCase() !== 'TEMPLATE') && (selector === '>*' || _matches(el, selector))) {
- index++;
- }
- }
-
- return index;
- }
-
- function _matches(/**HTMLElement*/el, /**String*/selector) {
- if (el) {
- selector = selector.split('.');
-
- var tag = selector.shift().toUpperCase(),
- re = new RegExp('\\s(' + selector.join('|') + ')(?=\\s)', 'g');
-
- return (
- (tag === '' || el.nodeName.toUpperCase() == tag) &&
- (!selector.length || ((' ' + el.className + ' ').match(re) || []).length == selector.length)
- );
- }
-
- return false;
- }
-
- function _throttle(callback, ms) {
- var args, _this;
-
- return function () {
- if (args === void 0) {
- args = arguments;
- _this = this;
-
- setTimeout(function () {
- if (args.length === 1) {
- callback.call(_this, args[0]);
- } else {
- callback.apply(_this, args);
- }
-
- args = void 0;
- }, ms);
- }
- };
- }
-
- function _extend(dst, src) {
- if (dst && src) {
- for (var key in src) {
- if (src.hasOwnProperty(key)) {
- dst[key] = src[key];
- }
- }
- }
-
- return dst;
- }
-
- function _clone(el) {
- return $
- ? $(el).clone(true)[0]
- : (Polymer && Polymer.dom
- ? Polymer.dom(el).cloneNode(true)
- : el.cloneNode(true)
- );
- }
-
- function _saveInputCheckedState(root) {
- var inputs = root.getElementsByTagName('input');
- var idx = inputs.length;
-
- while (idx--) {
- var el = inputs[idx];
- el.checked && savedInputChecked.push(el);
- }
- }
-
- // Fixed #973:
- _on(document, 'touchmove', function (evt) {
- if (Sortable.active) {
- evt.preventDefault();
- }
- });
-
- try {
- window.addEventListener('test', null, Object.defineProperty({}, 'passive', {
- get: function () {
- captureMode = {
- capture: false,
- passive: false
- };
- }
- }));
- } catch (err) {}
-
- // Export utils
- Sortable.utils = {
- on: _on,
- off: _off,
- css: _css,
- find: _find,
- is: function (el, selector) {
- return !!_closest(el, selector, el);
- },
- extend: _extend,
- throttle: _throttle,
- closest: _closest,
- toggleClass: _toggleClass,
- clone: _clone,
- index: _index
- };
-
-
- /**
- * Create sortable instance
- * @param {HTMLElement} el
- * @param {Object} [options]
- */
- Sortable.create = function (el, options) {
- return new Sortable(el, options);
- };
-
-
- // Export
- Sortable.version = '1.6.0';
- return Sortable;
+
+ function _unsilent() {
+ _silent = false;
+ }
+
+
+ /** @returns {HTMLElement|false} */
+ function _ghostIsLast(el, evt) {
+ var lastEl = el.lastElementChild,
+ rect = lastEl.getBoundingClientRect();
+
+ // 5 — min delta
+ // abs — нельзя добавлять, а то глюки при наведении сверху
+ return (evt.clientY - (rect.top + rect.height) > 5) ||
+ (evt.clientX - (rect.left + rect.width) > 5);
+ }
+
+
+ /**
+ * Generate id
+ * @param {HTMLElement} el
+ * @returns {String}
+ * @private
+ */
+ function _generateId(el) {
+ var str = el.tagName + el.className + el.src + el.href + el.textContent,
+ i = str.length,
+ sum = 0;
+
+ while (i--) {
+ sum += str.charCodeAt(i);
+ }
+
+ return sum.toString(36);
+ }
+
+ /**
+ * Returns the index of an element within its parent for a selected set of
+ * elements
+ * @param {HTMLElement} el
+ * @param {selector} selector
+ * @return {number}
+ */
+ function _index(el, selector) {
+ var index = 0;
+
+ if (!el || !el.parentNode) {
+ return -1;
+ }
+
+ while (el && (el = el.previousElementSibling)) {
+ if ((el.nodeName.toUpperCase() !== 'TEMPLATE') && (selector === '>*' || _matches(el, selector))) {
+ index++;
+ }
+ }
+
+ return index;
+ }
+
+ function _matches(/**HTMLElement*/el, /**String*/selector) {
+ if (el) {
+ selector = selector.split('.');
+
+ var tag = selector.shift().toUpperCase(),
+ re = new RegExp('\\s(' + selector.join('|') + ')(?=\\s)', 'g');
+
+ return (
+ (tag === '' || el.nodeName.toUpperCase() == tag) &&
+ (!selector.length || ((' ' + el.className + ' ').match(re) || []).length == selector.length)
+ );
+ }
+
+ return false;
+ }
+
+ function _throttle(callback, ms) {
+ var args, _this;
+
+ return function () {
+ if (args === void 0) {
+ args = arguments;
+ _this = this;
+
+ setTimeout(function () {
+ if (args.length === 1) {
+ callback.call(_this, args[0]);
+ } else {
+ callback.apply(_this, args);
+ }
+
+ args = void 0;
+ }, ms);
+ }
+ };
+ }
+
+ function _extend(dst, src) {
+ if (dst && src) {
+ for (var key in src) {
+ if (src.hasOwnProperty(key)) {
+ dst[key] = src[key];
+ }
+ }
+ }
+
+ return dst;
+ }
+
+ function _clone(el) {
+ if (Polymer && Polymer.dom) {
+ return Polymer.dom(el).cloneNode(true);
+ }
+ else if ($) {
+ return $(el).clone(true)[0];
+ }
+ else {
+ return el.cloneNode(true);
+ }
+ }
+
+ function _saveInputCheckedState(root) {
+ var inputs = root.getElementsByTagName('input');
+ var idx = inputs.length;
+
+ while (idx--) {
+ var el = inputs[idx];
+ el.checked && savedInputChecked.push(el);
+ }
+ }
+
+ function _nextTick(fn) {
+ return setTimeout(fn, 0);
+ }
+
+ function _cancelNextTick(id) {
+ return clearTimeout(id);
+ }
+
+ // Fixed #973:
+ _on(document, 'touchmove', function (evt) {
+ if (Sortable.active) {
+ evt.preventDefault();
+ }
+ });
+
+ // Export utils
+ Sortable.utils = {
+ on: _on,
+ off: _off,
+ css: _css,
+ find: _find,
+ is: function (el, selector) {
+ return !!_closest(el, selector, el);
+ },
+ extend: _extend,
+ throttle: _throttle,
+ closest: _closest,
+ toggleClass: _toggleClass,
+ clone: _clone,
+ index: _index,
+ nextTick: _nextTick,
+ cancelNextTick: _cancelNextTick
+ };
+
+
+ /**
+ * Create sortable instance
+ * @param {HTMLElement} el
+ * @param {Object} [options]
+ */
+ Sortable.create = function (el, options) {
+ return new Sortable(el, options);
+ };
+
+
+ // Export
+ Sortable.version = '1.7.0';
+ return Sortable;
});
diff --git a/src/components/Menu/Drawer/Drawer.spec.js b/src/components/Menu/Drawer/Drawer.spec.js
index 6426812..f5b49d1 100644
--- a/src/components/Menu/Drawer/Drawer.spec.js
+++ b/src/components/Menu/Drawer/Drawer.spec.js
@@ -1,16 +1,18 @@
import React from 'react';
-import { shallow } from 'enzyme';
+import { configure, shallow } from 'enzyme';
+import Adapter from 'enzyme-adapter-react-16';
import Drawer from './Drawer.jsx';
-it('should render without throwing an error', function() {
- const wrapper = shallow();
- const container = wrapper.find(
-
- );
+configure({ adapter: new Adapter() });
- expect(container.root.length).toBe(1);
-});
+describe('A suite', function() {
+ it('should render without throwing an error', function() {
+ const wrapper = shallow();
-it('should be selectable by class "drawer-container"', function() {
- expect(shallow().is('.drawer-container')).toBe(true);
+ expect(wrapper.find('.react-virtualized-pivot-module-menu')
+ .length).toBe(1);
+ });
+ it('should be selectable by class "drawer-container"', function() {
+ expect(shallow().is('.drawer-container')).toBe(true);
+ });
});
diff --git a/src/components/Pivot/Pivot.jsx b/src/components/Pivot/Pivot.jsx
index 72b4fa6..8f95a15 100644
--- a/src/components/Pivot/Pivot.jsx
+++ b/src/components/Pivot/Pivot.jsx
@@ -17,35 +17,76 @@ export default class Pivot extends PureComponent {
}) :
[];
const dataArray = this.props.data !== undefined ? this.props.data : [];
- const fields = this.props.data !== undefined ? this.props.data[0] : [];
+ let fields = this.props.data !== undefined ? this.props.data[0] : [];
+ const colFields = this.props.colFields || [];
+ const rowFields = this.props.rowFields || [];
+
+ if (fields.length) {
+ colFields.forEach((field) => {
+ if (fields.indexOf(field) > -1) {
+ fields = [].concat(fields.slice(0, fields.indexOf(field)),
+ fields.slice(fields.indexOf(field) + 1));
+ }
+ });
+ rowFields.forEach((field) => {
+ if (fields.indexOf(field) > -1) {
+ fields = [].concat(fields.slice(0, fields.indexOf(field)),
+ fields.slice(fields.indexOf(field) + 1));
+ }
+ });
+ }
+
const pivot = this.props.data !== undefined ?
- new QuickPivot(this.props.data, [], [],
- this.props.selectedAggregationDimension || '', 'sum', '') :
- {};
+ new QuickPivot(this.props.data, this.props.rowFields || [],
+ this.props.colFields || [], this.props.selectedAggregationDimension ||
+ '', 'sum', '') : {};
+
+ Object.keys(this.props.filters).forEach((filter) => {
+ pivot.filter((elem, index, array) => {
+ return this.props.filters[filter].findIndex((field) => {
+ return field === elem[filter];
+ }) === -1;
+ });
+ });
+
+ let headerCounter = 0;
+
+ if (pivot.data) {
+ while (true) {
+ if (pivot.data.table[headerCounter].type === 'colHeader') {
+ headerCounter += 1;
+ } else {
+ break;
+ }
+ }
+ }
this.state = {
aggregationDimensions,
dataArray,
fields,
pivot,
- colFields: [],
- rowFields: [],
+ colFields,
+ rowFields,
selectedAggregationType: 'sum',
selectedAggregationDimension: this.props.selectedAggregationDimension ||
'',
currentFilter: '',
currentValues: [],
- filters: {},
+ filters: this.props.filters,
columnWidth: 100,
- columnCount: 0,
+ columnCount:
+ (pivot !== undefined && pivot.data.table.length &&
+ pivot.data.table[0].value.length) ?
+ pivot.data.table[0].value.length : 0,
overscanColumnCount: 5,
overscanRowCount: 5,
headerHeight: 40,
rowHeight: 30,
- rowCount: 0,
- data: [],
+ rowCount: pivot !== undefined ? pivot.data.table.length : 0,
+ data: pivot !== undefined ? pivot.data.table : [],
header: {},
- headerCounter: 0,
+ headerCounter,
isDrawerOpen: false,
};
@@ -67,43 +108,162 @@ export default class Pivot extends PureComponent {
}
componentWillReceiveProps(nextProps) {
- if (this.props.colorPack !== nextProps.colorPack) {
- return;
- }
- const aggregationDimensions = nextProps.data !== undefined ?
- nextProps.data[0].map((item, index) => {
- return {value: item, label: item};
- }) :
- [];
- const dataArray = nextProps.data !== undefined ? nextProps.data : [];
- const fields = nextProps.data !== undefined ? nextProps.data[0] : [];
- const pivot = nextProps.data !== undefined ?
- new QuickPivot(nextProps.data, [], [],
- nextProps.selectedAggregationDimension || '', 'sum', '') : {};
+ console.log(nextProps)
+ if (nextProps.onChange !== undefined) {
+ console.log('in the onchange')
+ const newState = nextProps.onChange(this.state);
+ const aggregationDimensions = nextProps.data !== undefined ?
+ nextProps.data[0].map((item, index) => {
+ return {value: item, label: item};
+ }) :
+ [];
+ const dataArray = nextProps.data !== undefined ? nextProps.data : [];
+ let fields = nextProps.data !== undefined ? nextProps.data[0] : [];
+
+ if (fields.length) {
+ newState.colFields.forEach((field) => {
+ if (fields.indexOf(field) > -1) {
+ fields = [].concat(fields.slice(0, fields.indexOf(field)),
+ fields.slice(fields.indexOf(field) + 1));
+ }
+ });
+ newState.rowFields.forEach((field) => {
+ if (fields.indexOf(field) > -1) {
+ fields = [].concat(fields.slice(0, fields.indexOf(field)),
+ fields.slice(fields.indexOf(field) + 1));
+ }
+ });
+ }
- // Reset entire state execpt selectedAggregationType
- this.setState({
- aggregationDimensions,
- dataArray,
- fields,
- pivot,
- colFields: [],
- rowFields: [],
- selectedAggregationDimension: nextProps.selectedAggregationDimension ||
- '',
- currentFilter: '',
- currentValues: [],
- filters: {},
- columnWidth: 100,
- columnCount: 0,
- overscanColumnCount: 0,
- overscanRowCount: 5,
- rowHeight: 30,
- rowCount: 0,
- data: [],
- header: {},
- headerCounter: 0,
- });
+ const pivot = nextProps.data !== undefined ?
+ new QuickPivot(nextProps.data, newState.rowFields || [],
+ newState.colFields || [], newState.selectedAggregationDimension ||
+ '', 'sum', '') : {};
+
+ Object.keys(newState.filters).forEach((filter) => {
+ pivot.filter((elem, index, array) => {
+ return newState.filters[filter].findIndex((field) => {
+ return field === elem[filter];
+ }) === -1;
+ });
+ });
+
+ let headerCounter = 0;
+
+ if (pivot.data) {
+ while (true) {
+ if (pivot.data.table[headerCounter].type === 'colHeader') {
+ headerCounter += 1;
+ } else {
+ break;
+ }
+ }
+ }
+
+ this.setState({
+ aggregationDimensions,
+ dataArray: dataArray,
+ fields,
+ pivot,
+ colFields: newState.colFields,
+ rowFields: newState.rowFields,
+ selectedAggregationDimension: newState.selectedAggregationDimension ||
+ '',
+ currentFilter: '',
+ currentValues: [],
+ filters: newState.filters,
+ columnWidth: 100,
+ columnCount:
+ (pivot !== undefined && pivot.data.table.length &&
+ pivot.data.table[0].value.length) ?
+ pivot.data.table[0].value.length : 0,
+ overscanColumnCount: newState.overscanColumnCount,
+ overscanRowCount: newState.overscanRowCount,
+ headerHeight: newState.headerHeight,
+ rowHeight: newState.rowHeight,
+ rowCount: pivot !== undefined ? pivot.data.table.length : 0,
+ data: pivot !== undefined ? pivot.data.table : [],
+ header: {},
+ headerCounter: headerCounter,
+ isDrawerOpen: newState.isDrawerOpen,
+ });
+
+ } else {
+ const aggregationDimensions = nextProps.data !== undefined ?
+ nextProps.data[0].map((item, index) => {
+ return {value: item, label: item};
+ }) :
+ [];
+ const dataArray = nextProps.data !== undefined ? nextProps.data : [];
+ let fields = nextProps.data !== undefined ? nextProps.data[0] : [];
+
+ if (fields.length) {
+ nextProps.colFields.forEach((field) => {
+ if (fields.indexOf(field) > -1) {
+ fields = [].concat(fields.slice(0, fields.indexOf(field)),
+ fields.slice(fields.indexOf(field) + 1));
+ }
+ });
+ nextProps.rowFields.forEach((field) => {
+ if (fields.indexOf(field) > -1) {
+ fields = [].concat(fields.slice(0, fields.indexOf(field)),
+ fields.slice(fields.indexOf(field) + 1));
+ }
+ });
+ }
+
+ const pivot = nextProps.data !== undefined ?
+ new QuickPivot(nextProps.data, nextProps.rowFields || [],
+ nextProps.colFields || [], nextProps.selectedAggregationDimension ||
+ '', 'sum', '') : {};
+
+ Object.keys(nextProps.filters).forEach((filter) => {
+ pivot.filter((elem, index, array) => {
+ return nextProps.filters[filter].findIndex((field) => {
+ return field === elem[filter];
+ }) === -1;
+ });
+ });
+
+ let headerCounter = 0;
+
+ if (pivot.data) {
+ while (true) {
+ if (pivot.data.table[headerCounter].type === 'colHeader') {
+ headerCounter += 1;
+ } else {
+ break;
+ }
+ }
+ }
+
+ // Reset entire state execpt selectedAggregationType
+ this.setState({
+ aggregationDimensions,
+ dataArray,
+ fields,
+ pivot,
+ colFields: nextProps.colFields || [],
+ rowFields: nextProps.rowFields || [],
+ selectedAggregationDimension: nextProps.selectedAggregationDimension ||
+ '',
+ currentFilter: '',
+ currentValues: [],
+ filters: nextProps.filters,
+ columnWidth: 100,
+ columnCount:
+ (pivot !== undefined && pivot.data.table.length &&
+ pivot.data.table[0].value.length) ?
+ pivot.data.table[0].value.length : 0,
+ overscanColumnCount: 0,
+ overscanRowCount: 5,
+ rowHeight: 30,
+ rowCount: pivot !== undefined ? pivot.data.table.length : 0,
+ data: pivot !== undefined ? pivot.data.table : [],
+ header: {},
+ headerCounter,
+ });
+ }
}
onSelectAggregationType(selectedAggregationType) {
@@ -409,7 +569,6 @@ export default class Pivot extends PureComponent {
columnWidth,
currentFilter,
currentValues,
- data,
fields,
filters,
headerCounter,
@@ -417,7 +576,6 @@ export default class Pivot extends PureComponent {
overscanColumnCount,
overscanRowCount,
pivot,
- rowCount,
rowFields,
rowHeight,
selectedAggregationDimension,
@@ -425,6 +583,11 @@ export default class Pivot extends PureComponent {
isDrawerOpen,
} = this.state;
+ let {
+ data,
+ rowCount,
+ } = this.state;
+
const {
bodyCellValueTransformation,
colorPack,
@@ -432,6 +595,7 @@ export default class Pivot extends PureComponent {
onGridHeaderCellClick,
onLeftGridCellClick,
onLeftHeaderCellClick,
+ rowTotals,
} = this.props;
const aggregationTypes = [
@@ -442,6 +606,11 @@ export default class Pivot extends PureComponent {
{ value: 'average', label: 'average' },
];
+ if (data !== undefined && data.length && !rowTotals) {
+ rowCount = rowCount - 1;
+ data = data.slice(0, rowCount);
+ }
+
return (