var ngEventProvider = function (grid, $scope, domUtilityService, $timeout) { var self = this; // The init method gets called during the ng-grid directive execution. self.colToMove = undefined; self.groupToMove = undefined; self.assignEvents = function() { // Here we set the onmousedown event handler to the header container. if (grid.config.jqueryUIDraggable && !grid.config.enablePinning) { grid.$groupPanel.droppable({ addClasses: false, drop: function(event) { self.onGroupDrop(event); } }); } else { grid.$groupPanel.on('mousedown', self.onGroupMouseDown).on('dragover', self.dragOver).on('drop', self.onGroupDrop); grid.$headerScroller.on('mousedown', self.onHeaderMouseDown).on('dragover', self.dragOver); if (grid.config.enableColumnReordering && !grid.config.enablePinning) { grid.$headerScroller.on('drop', self.onHeaderDrop); } if (grid.config.enableRowReordering) { grid.$viewport.on('mousedown', self.onRowMouseDown).on('dragover', self.dragOver).on('drop', self.onRowDrop); } } $scope.$watch('renderedColumns', function() { $timeout(self.setDraggables); }); }; self.dragStart = function(evt){ //FireFox requires there to be dataTransfer if you want to drag and drop. evt.dataTransfer.setData('text', ''); //cannot be empty string }; self.dragOver = function(evt) { evt.preventDefault(); }; //For JQueryUI self.setDraggables = function() { if (!grid.config.jqueryUIDraggable) { //Fix for FireFox. Instead of using jQuery on('dragstart', function) on find, we have to use addEventListeners for each column. var columns = grid.$root.find('.ngHeaderSortColumn'); //have to iterate if using addEventListener angular.forEach(columns, function(col){ col.setAttribute('draggable', 'true'); //jQuery 'on' function doesn't have dataTransfer as part of event in handler unless added to event props, which is not recommended //See more here: http://api.jquery.com/category/events/event-object/ if (col.addEventListener) { //IE8 doesn't have drag drop or event listeners col.addEventListener('dragstart', self.dragStart); } }); if (navigator.userAgent.indexOf("MSIE") != -1){ //call native IE dragDrop() to start dragging grid.$root.find('.ngHeaderSortColumn').bind('selectstart', function () { this.dragDrop(); return false; }); } } else { grid.$root.find('.ngHeaderSortColumn').draggable({ helper: 'clone', appendTo: 'body', stack: 'div', addClasses: false, start: function(event) { self.onHeaderMouseDown(event); } }).droppable({ drop: function(event) { self.onHeaderDrop(event); } }); } }; self.onGroupMouseDown = function(event) { var groupItem = $(event.target); // Get the scope from the header container if (groupItem[0].className != 'ngRemoveGroup') { var groupItemScope = angular.element(groupItem).scope(); if (groupItemScope) { // set draggable events if (!grid.config.jqueryUIDraggable) { groupItem.attr('draggable', 'true'); if(this.addEventListener){//IE8 doesn't have drag drop or event listeners this.addEventListener('dragstart', self.dragStart); } if (navigator.userAgent.indexOf("MSIE") != -1){ //call native IE dragDrop() to start dragging groupItem.bind('selectstart', function () { this.dragDrop(); return false; }); } } // Save the column for later. self.groupToMove = { header: groupItem, groupName: groupItemScope.group, index: groupItemScope.$index }; } } else { self.groupToMove = undefined; } }; self.onGroupDrop = function(event) { event.stopPropagation(); // clear out the colToMove object var groupContainer; var groupScope; if (self.groupToMove) { // Get the closest header to where we dropped groupContainer = $(event.target).closest('.ngGroupElement'); // Get the scope from the header. if (groupContainer.context.className == 'ngGroupPanel') { $scope.configGroups.splice(self.groupToMove.index, 1); $scope.configGroups.push(self.groupToMove.groupName); } else { groupScope = angular.element(groupContainer).scope(); if (groupScope) { // If we have the same column, do nothing. if (self.groupToMove.index != groupScope.$index) { // Splice the columns $scope.configGroups.splice(self.groupToMove.index, 1); $scope.configGroups.splice(groupScope.$index, 0, self.groupToMove.groupName); } } } self.groupToMove = undefined; grid.fixGroupIndexes(); } else if (self.colToMove) { if ($scope.configGroups.indexOf(self.colToMove.col) == -1) { groupContainer = $(event.target).closest('.ngGroupElement'); // Get the scope from the header. if (groupContainer.context.className == 'ngGroupPanel' || groupContainer.context.className == 'ngGroupPanelDescription ng-binding') { $scope.groupBy(self.colToMove.col); } else { groupScope = angular.element(groupContainer).scope(); if (groupScope) { // Splice the columns $scope.removeGroup(groupScope.$index); } } } self.colToMove = undefined; } if (!$scope.$$phase) { $scope.$apply(); } }; //Header functions self.onHeaderMouseDown = function(event) { // Get the closest header container from where we clicked. var headerContainer = $(event.target).closest('.ngHeaderSortColumn'); // Get the scope from the header container var headerScope = angular.element(headerContainer).scope(); if (headerScope) { // Save the column for later. self.colToMove = { header: headerContainer, col: headerScope.col }; } }; self.onHeaderDrop = function(event) { if (!self.colToMove || self.colToMove.col.pinned) { return; } // Get the closest header to where we dropped var headerContainer = $(event.target).closest('.ngHeaderSortColumn'); // Get the scope from the header. var headerScope = angular.element(headerContainer).scope(); if (headerScope) { // If we have the same column, do nothing. if (self.colToMove.col == headerScope.col) { return; } // Splice the columns $scope.columns.splice(self.colToMove.col.index, 1); $scope.columns.splice(headerScope.col.index, 0, self.colToMove.col); grid.fixColumnIndexes(); // Finally, rebuild the CSS styles. domUtilityService.BuildStyles($scope, grid, true); // clear out the colToMove object self.colToMove = undefined; } }; // Row functions self.onRowMouseDown = function(event) { // Get the closest row element from where we clicked. var targetRow = $(event.target).closest('.ngRow'); // Get the scope from the row element var rowScope = angular.element(targetRow).scope(); if (rowScope) { // set draggable events targetRow.attr('draggable', 'true'); // Save the row for later. domUtilityService.eventStorage.rowToMove = { targetRow: targetRow, scope: rowScope }; } }; self.onRowDrop = function(event) { // Get the closest row to where we dropped var targetRow = $(event.target).closest('.ngRow'); // Get the scope from the row element. var rowScope = angular.element(targetRow).scope(); if (rowScope) { // If we have the same Row, do nothing. var prevRow = domUtilityService.eventStorage.rowToMove; if (prevRow.scope.row == rowScope.row) { return; } grid.changeRowOrder(prevRow.scope.row, rowScope.row); grid.searchProvider.evalFilter(); // clear out the rowToMove object domUtilityService.eventStorage.rowToMove = undefined; // if there isn't an apply already in progress lets start one domUtilityService.digest(rowScope.$root); } }; self.assignGridEventHandlers = function() { //Chrome and firefox both need a tab index so the grid can recieve focus. //need to give the grid a tabindex if it doesn't already have one so //we'll just give it a tab index of the corresponding gridcache index //that way we'll get the same result every time it is run. //configurable within the options. if (grid.config.tabIndex === -1) { grid.$viewport.attr('tabIndex', domUtilityService.numberOfGrids); domUtilityService.numberOfGrids++; } else { grid.$viewport.attr('tabIndex', grid.config.tabIndex); }// resize on window resize $(window).resize(function() { domUtilityService.RebuildGrid($scope,grid); }); // resize on parent resize as well. $(grid.$root.parent()).on('resize', function() { domUtilityService.RebuildGrid($scope, grid); }); }; // In this example we want to assign grid events. self.assignGridEventHandlers(); self.assignEvents(); };