%PDF- %PDF-
Direktori : /home/bitrix/www/bitrix/components/bitrix/main.ui.grid/templates/.default/js/ |
Current File : //home/bitrix/www/bitrix/components/bitrix/main.ui.grid/templates/.default/js/rows-sortable.js |
;(function() { 'use strict'; BX.namespace('BX.Grid'); BX.Grid.RowDragEvent = function(eventName) { this.allowMoveRow = true; this.allowInsertBeforeTarget = true; this.dragItem = null; this.targetItem = null; this.eventName = !!eventName ? eventName : ''; this.errorMessage = ''; }; BX.Grid.RowDragEvent.prototype = { allowMove: function() { this.allowMoveRow = true; this.errorMessage = ''; }, allowInsertBefore: function() { this.allowInsertBeforeTarget = true; }, disallowMove: function(errorMessage) { this.allowMoveRow = false; this.errorMessage = errorMessage || ''; }, disallowInsertBefore: function() { this.allowInsertBeforeTarget = false; }, getDragItem: function() { return this.dragItem; }, getTargetItem: function() { return this.targetItem; }, getEventName: function() { return this.eventName; }, setDragItem: function(item) { return this.dragItem = item; }, setTargetItem: function(item) { return this.targetItem = item; }, setEventName: function(name) { return this.eventName = name; }, isAllowedMove: function() { return this.allowMoveRow; }, isAllowedInsertBefore: function() { return this.allowInsertBeforeTarget; }, getErrorMessage: function() { return this.errorMessage; } }; BX.Grid.RowsSortable = function(parent) { this.parent = null; this.list = null; this.setDefaultProps(); this.init(parent); }; BX.Grid.RowsSortable.prototype = { init: function(parent) { this.parent = parent; this.list = this.getList(); this.prepareListItems(); jsDD.Enable(); if (!this.inited) { this.inited = true; this.onscrollDebounceHandler = BX.debounce(this._onWindowScroll, 300, this); BX.addCustomEvent('Grid::thereEditedRows', BX.proxy(this.disable, this)); BX.addCustomEvent('Grid::noEditedRows', BX.proxy(this.enable, this)); document.addEventListener('scroll', this.onscrollDebounceHandler, BX.Grid.Utils.listenerParams({passive: true})); } }, destroy: function() { BX.removeCustomEvent('Grid::thereEditedRows', BX.proxy(this.disable, this)); BX.removeCustomEvent('Grid::noEditedRows', BX.proxy(this.enable, this)); document.removeEventListener('scroll', this.onscrollDebounceHandler, BX.Grid.Utils.listenerParams({passive: true})); this.unregisterObjects(); }, _onWindowScroll: function() { this.windowScrollTop = BX.scrollTop(window); this.rowsRectList = null; }, disable: function() { this.unregisterObjects(); }, enable: function() { this.reinit(); }, reinit: function() { this.unregisterObjects(); this.setDefaultProps(); this.init(this.parent); }, getList: function() { return this.parent.getRows().getSourceBodyChild(); }, unregisterObjects: function() { this.list.forEach(this.unregister, this); }, prepareListItems: function() { this.list.forEach(this.register, this); }, register: function(row) { var Rows = this.parent.getRows(); if (Rows.get(row).isDraggable()) { row.onbxdragstart = BX.delegate(this._onDragStart, this); row.onbxdrag = BX.delegate(this._onDrag, this); row.onbxdragstop = BX.delegate(this._onDragEnd, this); jsDD.registerObject(row); } }, unregister: function(row) { jsDD.unregisterObject(row); }, getIndex: function(item) { return BX.Grid.Utils.getIndex(this.list, item); }, calcOffset: function() { var offset = this.dragRect.height; if (this.additionalDragItems.length) { this.additionalDragItems.forEach(function(row) { offset += row.clientHeight; }); } return offset; }, getTheadCells: function(sourceCells) { return [].map.call(sourceCells, function(cell, index) { return { block: '', tag: 'th', attrs: { style: 'width: '+BX.width(sourceCells[index])+'px;' } } }); }, createFake: function() { var content = []; this.cloneDragItem = BX.clone(this.dragItem); this.cloneDragAdditionalDragItems = []; this.cloneDragAdditionalDragItemRows = []; var theadCellsDecl = this.getTheadCells(this.dragItem.cells); content.push(this.cloneDragItem); this.additionalDragItems.forEach(function(row) { var cloneRow = BX.clone(row); content.push(cloneRow); this.cloneDragAdditionalDragItems.push(cloneRow); this.cloneDragAdditionalDragItemRows.push(new BX.Grid.Row(this.parent, cloneRow)); }, this); var tableWidth = BX.width(this.parent.getTable()); this.fake = BX.decl({ block: 'main-grid-fake-container', attrs: { style: 'position: absolute; top: '+this.getDragStartRect().top+'px; width: ' + tableWidth + 'px' }, content: { block: 'main-grid-table', mix: 'main-grid-table-fake', tag: 'table', attrs: { style: 'width: ' + tableWidth + 'px' }, content: [ { block: 'main-grid-header', tag: 'thead', content: { block: 'main-grid-row-head', tag: 'tr', content: theadCellsDecl } }, { block: '', tag: 'tbody', content: content } ] } }); BX.insertAfter(this.fake, this.parent.getTable()); this.cloneDragItem = new BX.Grid.Row(this.parent, this.cloneDragItem); return this.fake; }, getDragStartRect: function() { return BX.pos(this.dragItem, this.parent.getTable()); }, _onDragStart: function() { this.dragItem = jsDD.current_node; this.targetItem = this.dragItem; this.additionalDragItems = this.getAdditionalDragItems(this.dragItem); this.dragIndex = this.getIndex(this.dragItem); this.dragRect = this.getRowRect(this.dragItem, this.dragIndex); this.offset = this.calcOffset(); this.dragStartOffset = (jsDD.start_y - this.dragRect.top); this.dragEvent = new BX.Grid.RowDragEvent(); this.dragEvent.setEventName('BX.Main.grid:rowDragStart'); this.dragEvent.setDragItem(this.dragItem); this.dragEvent.setTargetItem(this.targetItem); this.dragEvent.allowInsertBefore(); var dragRow = this.parent.getRows().get(this.dragItem); this.startDragDepth = dragRow.getDepth(); this.startDragParentId = dragRow.getParentId(); this.createFake(); BX.addClass(this.parent.getContainer(), this.parent.settings.get('classOnDrag')); BX.addClass(this.dragItem, this.parent.settings.get('classDragActive')); BX.onCustomEvent(window, 'BX.Main.grid:rowDragStart', [this.dragEvent, this.parent]); }, getAdditionalDragItems: function(dragItem) { var Rows = this.parent.getRows(); return Rows.getRowsByParentId(Rows.get(dragItem).getId(), true).map(function(row) { return row.getNode(); }); }, /** * @param {?HTMLElement} row * @param {int} offset * @param {?int} [transition] css transition-duration in ms */ moveRow: function(row, offset, transition) { if (!!row) { var transitionDuration = BX.type.isNumber(transition) ? transition : 300; row.style.transition = transitionDuration + 'ms'; row.style.transform = 'translate3d(0px, '+offset+'px, 0px)'; } }, getDragOffset: function() { return jsDD.y - this.dragRect.top - this.dragStartOffset; }, getWindowScrollTop: function() { if (this.windowScrollTop === null) { this.windowScrollTop = BX.scrollTop(window); } return this.windowScrollTop; }, getSortOffset: function() { return jsDD.y; }, getRowRect: function(row, index) { if (!this.rowsRectList) { this.rowsRectList = {}; this.list.forEach(function(current, i) { this.rowsRectList[i] = current.getBoundingClientRect(); }, this); } return this.rowsRectList[index]; }, getRowCenter: function(row, index) { var rect = this.getRowRect(row, index); return rect.top + this.getWindowScrollTop() + (rect.height / 2); }, isDragToBottom: function(row, index) { var rowCenter = this.getRowCenter(row, index); var sortOffset = this.getSortOffset(); return index > this.dragIndex && rowCenter < sortOffset; }, isMovedToBottom: function(row) { return row.style.transform === 'translate3d(0px, '+(-this.offset)+'px, 0px)'; }, isDragToTop: function(row, index) { var rowCenter = this.getRowCenter(row, index); var sortOffset = this.getSortOffset(); return index < this.dragIndex && rowCenter > sortOffset; }, isMovedToTop: function(row) { return row.style.transform === 'translate3d(0px, '+this.offset+'px, 0px)'; }, isDragToBack: function(row, index) { var rowCenter = this.getRowCenter(row, index); var dragIndex = this.dragIndex; var y = jsDD.y; return (index > dragIndex && y < rowCenter) || (index < dragIndex && y > rowCenter); }, isMoved: function(row) { return (row.style.transform !== 'translate3d(0px, 0px, 0px)' && row.style.transform !== ''); }, _onDrag: function() { var dragTransitionDuration = 0; var defaultOffset = 0; this.moveRow(this.dragItem, this.getDragOffset(), dragTransitionDuration); this.moveRow(this.fake, this.getDragOffset(), dragTransitionDuration); BX.Grid.Utils.styleForEach(this.additionalDragItems, { 'transition': dragTransitionDuration + 'ms', 'transform': 'translate3d(0px, '+(this.getDragOffset())+'px, 0px)' }); this.list.forEach(function(current, index) { if (!!current && current !== this.dragItem && this.additionalDragItems.indexOf(current) === -1) { if (this.isDragToTop(current, index) && !this.isMovedToTop(current)) { this.targetItem = current; this.moveRow(current, this.offset); this.dragEvent.setEventName('BX.Main.grid:rowDragMove'); this.dragEvent.setTargetItem(this.targetItem); BX.onCustomEvent(window, 'BX.Main.grid:rowDragMove', [this.dragEvent, this.parent]); this.checkError(this.dragEvent); this.updateProperties(this.dragItem, this.targetItem); this.isDragetToTop = true; } if (this.isDragToBottom(current, index) && !this.isMovedToBottom(current)) { this.targetItem = this.findNextVisible(this.list, index); this.moveRow(current, -this.offset); this.dragEvent.setEventName('BX.Main.grid:rowDragMove'); this.dragEvent.setTargetItem(this.targetItem); BX.onCustomEvent(window, 'BX.Main.grid:rowDragMove', [this.dragEvent, this.parent]); this.checkError(this.dragEvent); this.updateProperties(this.dragItem, this.targetItem); this.isDragetToTop = false; } if (this.isDragToBack(current, index) && this.isMoved(current)) { this.moveRow(current, defaultOffset); this.targetItem = current; if (this.isDragetToTop) { this.targetItem = this.findNextVisible(this.list, index); } this.dragEvent.setEventName('BX.Main.grid:rowDragMove'); this.dragEvent.setTargetItem(this.targetItem); BX.onCustomEvent(window, 'BX.Main.grid:rowDragMove', [this.dragEvent, this.parent]); this.checkError(this.dragEvent); this.updateProperties(this.dragItem, this.targetItem); } } }, this); }, createError: function(target, message) { var error = BX.decl({ block: 'main-grid-error', content: !!message ? message : '' }); !!target && target.appendChild(error); setTimeout(function() { BX.addClass(error, 'main-grid-error-show'); }, 0); return error; }, checkError: function(event) { if (!event.isAllowedMove() && !this.error) { this.error = this.createError(this.fake, event.getErrorMessage()); } if (event.isAllowedMove() && this.error) { BX.remove(this.error); this.error = null; } }, findNextVisible: function(list, index) { var result = null; var Rows = this.parent.getRows(); list.forEach(function(item, currentIndex) { if (!result && currentIndex > index) { var row = Rows.get(item); if (row.isShown()) { result = item; } } }); return result; }, /** * Updates row properties * @param {?HTMLTableRowElement} dragItem * @param {?HTMLTableRowElement} targetItem */ updateProperties: function(dragItem, targetItem) { var Rows = this.parent.getRows(); var dragRow = Rows.get(dragItem); var depth = 0; var parentId = 0; if (!!targetItem) { var targetRow = Rows.get(targetItem); depth = targetRow.getDepth(); parentId = targetRow.getParentId(); } dragRow.setDepth(depth); dragRow.setParentId(parentId); this.cloneDragItem.setDepth(depth); this.cloneDragAdditionalDragItemRows.forEach(function(row, index) { row.setDepth(BX.data(this.additionalDragItems[index], 'depth')); }, this); }, resetDragProperties: function() { var dragRow = this.parent.getRows().get(this.dragItem); dragRow.setDepth(this.startDragDepth); dragRow.setParentId(this.startDragParentId); }, _onDragOver: function() {}, _onDragLeave: function() {}, _onDragEnd: function() { BX.onCustomEvent(window, 'BX.Main.grid:rowDragEnd', [this.dragEvent, this.parent]); BX.removeClass(this.parent.getContainer(), this.parent.settings.get('classOnDrag')); BX.removeClass(this.dragItem, this.parent.settings.get('classDragActive')); BX.Grid.Utils.styleForEach(this.list, {'transition': '', 'transform': ''}); if (this.dragEvent.isAllowedMove()) { this.sortRows(this.dragItem, this.targetItem); this.sortAdditionalDragItems(this.dragItem, this.additionalDragItems); this.list = this.getList(); this.parent.getRows().reset(); var dragItem = this.parent.getRows().get(this.dragItem); var ids = this.parent.getRows().getBodyChild().map(function(row) { return row.getId(); }); this.saveRowsSort(ids); BX.onCustomEvent(window, 'Grid::rowMoved', [ids, dragItem, this.parent]); } else { this.resetDragProperties(); } BX.remove(this.fake); this.setDefaultProps(); }, sortAdditionalDragItems: function(dragItem, additional) { additional.reduce(function(prev, current) { !!current && BX.insertAfter(current, prev); return current; }, dragItem); }, sortRows: function(current, target) { if (!!target) { target.parentNode.insertBefore(current, target); } else { current.parentNode.appendChild(current); } }, saveRowsSort: function(rows) { var data = { ids: rows, action: this.parent.getUserOptions().getAction('GRID_SAVE_ROWS_SORT') }; this.parent.getData().request(null, 'POST', data); }, setDefaultProps: function() { this.dragItem = null; this.targetItem = null; this.dragRect = null; this.dragIndex = null; this.offset = null; this.realX = null; this.realY = null; this.dragStartOffset = null; this.windowScrollTop = null; this.rowsRectList = null; this.error = false; } }; })();