Просмотр исходного кода

CellDragListener, better cell constraining/centering logic

Adam Shaw 11 лет назад
Родитель
Сommit
befaceae88
3 измененных файлов с 66 добавлено и 16 удалено
  1. 52 12
      src/common/CellDragListener.js
  2. 11 4
      src/common/CoordMap.js
  3. 3 0
      src/common/Grid.events.js

+ 52 - 12
src/common/CellDragListener.js

@@ -1,6 +1,9 @@
 
 /* Tracks mouse movements over a CoordMap and raises events about which cell the mouse is over.
 ------------------------------------------------------------------------------------------------------------------------
+options:
+- subjectEl
+- subjectCenter
 */
 
 var CellDragListener = DragListener.extend({
@@ -8,6 +11,7 @@ var CellDragListener = DragListener.extend({
 	coordMap: null, // converts coordinates to date cells
 	origCell: null, // the cell the mouse was over when listening started
 	cell: null, // the cell the mouse is over
+	coordAdjust: null, // delta that will be added to the mouse coordinates when computing collisions
 
 
 	constructor: function(coordMap, options) {
@@ -17,18 +21,48 @@ var CellDragListener = DragListener.extend({
 	},
 
 
-	// Called when drag listening starts (but a real drag has not necessarily began)
-	listenStart: function(ev) { // ev might be undefined if dragging was started manually
-		var cell;
+	// Called when drag listening starts (but a real drag has not necessarily began).
+	// ev might be undefined if dragging was started manually.
+	listenStart: function(ev) {
+		var subjectEl = this.options.subjectEl;
+		var subjectRect;
+		var origPoint;
+		var point;
 
 		DragListener.prototype.listenStart.apply(this, arguments); // call the super-method
 
 		this.computeCoords();
 
-		// get info on the initial cell and its coordinates
-		this.origCell = ev ?
-			this.getCell(ev) :
-			null;
+		if (ev) {
+			origPoint = { left: ev.pageX, top: ev.pageY };
+			point = origPoint;
+
+			// constrain the point to bounds of the element being dragged
+			if (subjectEl) {
+				subjectRect = getOuterRect(subjectEl); // used for centering as well
+				point = constrainPoint(point, subjectRect);
+			}
+
+			this.origCell = this.getCell(point.left, point.top);
+
+			// treat the center of the subject as the collision point?
+			if (subjectEl && this.options.subjectCenter) {
+
+				// only consider the area the subject overlaps the cell. best for large subjects
+				if (this.origCell) {
+					subjectRect = intersectRects(this.origCell, subjectRect) ||
+						subjectRect; // in case there is no intersection
+				}
+
+				point = getRectCenter(subjectRect);
+			}
+
+			this.coordAdjust = diffPoints(point, origPoint); // point - origPoint
+		}
+		else {
+			this.origCell = null;
+			this.coordAdjust = null;
+		}
 	},
 
 
@@ -45,10 +79,10 @@ var CellDragListener = DragListener.extend({
 
 		DragListener.prototype.dragStart.apply(this, arguments); // call the super-method
 
+		cell = this.getCell(ev.pageX, ev.pageY); // might be different from this.origCell if the min-distance is large
+
 		// report the initial cell the mouse is over
 		// especially important if no min-distance and drag starts immediately
-		cell = this.getCell(ev); // this might be different from this.origCell if the min-distance is large
-
 		if (cell) {
 			this.cellOver(cell);
 		}
@@ -61,7 +95,7 @@ var CellDragListener = DragListener.extend({
 
 		DragListener.prototype.drag.apply(this, arguments); // call the super-method
 
-		cell = this.getCell(ev);
+		cell = this.getCell(ev.pageX, ev.pageY);
 
 		if (!isCellsEqual(cell, this.cell)) { // a different cell than before?
 			if (this.cell) {
@@ -124,8 +158,14 @@ var CellDragListener = DragListener.extend({
 
 
 	// Gets the cell underneath the coordinates for the given mouse event
-	getCell: function(ev) {
-		return this.coordMap.getCell(ev.pageX, ev.pageY);
+	getCell: function(left, top) {
+
+		if (this.coordAdjust) {
+			left += this.coordAdjust.left;
+			top += this.coordAdjust.top;
+		}
+
+		return this.coordMap.getCell(left, top);
 	}
 
 });

+ 11 - 4
src/common/CoordMap.js

@@ -49,7 +49,9 @@ var GridCoordMap = Class.extend({
 	// Given a coordinate of the document, gets the associated cell. If no cell is underneath, returns null
 	getCell: function(x, y) {
 		var rowCoords = this.rowCoords;
+		var rowCnt = rowCoords.length;
 		var colCoords = this.colCoords;
+		var colCnt = colCoords.length;
 		var hitRow = null;
 		var hitCol = null;
 		var i, coords;
@@ -57,7 +59,7 @@ var GridCoordMap = Class.extend({
 
 		if (this.inBounds(x, y)) {
 
-			for (i = 0; i < rowCoords.length; i++) {
+			for (i = 0; i < rowCnt; i++) {
 				coords = rowCoords[i];
 				if (y >= coords.top && y < coords.bottom) {
 					hitRow = i;
@@ -65,7 +67,7 @@ var GridCoordMap = Class.extend({
 				}
 			}
 
-			for (i = 0; i < colCoords.length; i++) {
+			for (i = 0; i < colCnt; i++) {
 				coords = colCoords[i];
 				if (x >= coords.left && x < coords.right) {
 					hitCol = i;
@@ -74,8 +76,13 @@ var GridCoordMap = Class.extend({
 			}
 
 			if (hitRow !== null && hitCol !== null) {
-				cell = this.grid.getCell(hitRow, hitCol);
-				cell.grid = this.grid; // for DragListener's isCellsEqual. dragging between grids
+
+				cell = this.grid.getCell(hitRow, hitCol); // expected to return a fresh object we can modify
+				cell.grid = this.grid; // for CellDragListener's isCellsEqual. dragging between grids
+
+				// make the coordinates available on the cell object
+				$.extend(cell, rowCoords[hitRow], colCoords[hitCol]);
+
 				return cell;
 			}
 		}

+ 3 - 0
src/common/Grid.events.js

@@ -270,6 +270,8 @@ Grid.mixin({
 		var dragListener = new CellDragListener(view.coordMap, {
 			distance: 5,
 			scroll: view.opt('dragScroll'),
+			subjectEl: el,
+			subjectCenter: true,
 			listenStart: function(ev) {
 				mouseFollower.hide(); // don't show until we know this is a real drag
 				mouseFollower.start(ev);
@@ -514,6 +516,7 @@ Grid.mixin({
 		dragListener = new CellDragListener(this.coordMap, {
 			distance: 5,
 			scroll: view.opt('dragScroll'),
+			subjectEl: el,
 			dragStart: function(ev) {
 				_this.triggerSegMouseout(seg, ev); // ensure a mouseout on the manipulated event has been reported
 				_this.isResizingSeg = true;