CoordMap.js
3.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/* A "coordinate map" converts pixel coordinates into an associated cell, which has an associated date
------------------------------------------------------------------------------------------------------------------------
Common interface:
CoordMap.prototype = {
build: function() {},
getCell: function(x, y) {}
};
*/
/* Coordinate map for a grid component
----------------------------------------------------------------------------------------------------------------------*/
var GridCoordMap = Class.extend({
grid: null, // reference to the Grid
rowCoords: null, // array of {top,bottom} objects
colCoords: null, // array of {left,right} objects
containerEl: null, // container element that all coordinates are constrained to. optionally assigned
bounds: null,
constructor: function(grid) {
this.grid = grid;
},
// Queries the grid for the coordinates of all the cells
build: function() {
this.rowCoords = this.grid.computeRowCoords();
this.colCoords = this.grid.computeColCoords();
this.computeBounds();
},
// Clears the coordinates data to free up memory
clear: function() {
this.rowCoords = null;
this.colCoords = null;
},
// 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;
var cell;
if (this.inBounds(x, y)) {
for (i = 0; i < rowCnt; i++) {
coords = rowCoords[i];
if (y >= coords.top && y < coords.bottom) {
hitRow = i;
break;
}
}
for (i = 0; i < colCnt; i++) {
coords = colCoords[i];
if (x >= coords.left && x < coords.right) {
hitCol = i;
break;
}
}
if (hitRow !== null && hitCol !== null) {
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;
}
}
return null;
},
// If there is a containerEl, compute the bounds into min/max values
computeBounds: function() {
this.bounds = this.containerEl ?
getClientRect(this.containerEl) : // area within scrollbars
null;
},
// Determines if the given coordinates are in bounds. If no `containerEl`, always true
inBounds: function(x, y) {
var bounds = this.bounds;
if (bounds) {
return x >= bounds.left && x < bounds.right && y >= bounds.top && y < bounds.bottom;
}
return true;
}
});
/* Coordinate map that is a combination of multiple other coordinate maps
----------------------------------------------------------------------------------------------------------------------*/
var ComboCoordMap = Class.extend({
coordMaps: null, // an array of CoordMaps
constructor: function(coordMaps) {
this.coordMaps = coordMaps;
},
// Builds all coordMaps
build: function() {
var coordMaps = this.coordMaps;
var i;
for (i = 0; i < coordMaps.length; i++) {
coordMaps[i].build();
}
},
// Queries all coordMaps for the cell underneath the given coordinates, returning the first result
getCell: function(x, y) {
var coordMaps = this.coordMaps;
var cell = null;
var i;
for (i = 0; i < coordMaps.length && !cell; i++) {
cell = coordMaps[i].getCell(x, y);
}
return cell;
},
// Clears all coordMaps
clear: function() {
var coordMaps = this.coordMaps;
var i;
for (i = 0; i < coordMaps.length; i++) {
coordMaps[i].clear();
}
}
});