/* 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 ----------------------------------------------------------------------------------------------------------------------*/ function GridCoordMap(grid) { this.grid = grid; } GridCoordMap.prototype = { grid: null, // reference to the Grid rows: null, // the top-to-bottom y coordinates. including the bottom of the last item cols: null, // the left-to-right x coordinates. including the right of the last item containerEl: null, // container element that all coordinates are constrained to. optionally assigned minX: null, maxX: null, // exclusive minY: null, maxY: null, // exclusive // Queries the grid for the coordinates of all the cells build: function() { this.grid.buildCoords( this.rows = [], this.cols = [] ); this.computeBounds(); }, // Given a coordinate of the document, gets the associated cell. If no cell is underneath, returns null getCell: function(x, y) { var cell = null; var rows = this.rows; var cols = this.cols; var r = -1; var c = -1; var i; if (this.inBounds(x, y)) { for (i = 0; i < rows.length; i++) { if (y >= rows[i][0] && y < rows[i][1]) { r = i; break; } } for (i = 0; i < cols.length; i++) { if (x >= cols[i][0] && x < cols[i][1]) { c = i; break; } } if (r >= 0 && c >= 0) { cell = { row: r, col: c }; cell.grid = this.grid; cell.date = this.grid.getCellDate(cell); } } return cell; }, // If there is a containerEl, compute the bounds into min/max values computeBounds: function() { var containerOffset; if (this.containerEl) { containerOffset = this.containerEl.offset(); this.minX = containerOffset.left; this.maxX = containerOffset.left + this.containerEl.outerWidth(); this.minY = containerOffset.top; this.maxY = containerOffset.top + this.containerEl.outerHeight(); } }, // Determines if the given coordinates are in bounds. If no `containerEl`, always true inBounds: function(x, y) { if (this.containerEl) { return x >= this.minX && x < this.maxX && y >= this.minY && y < this.maxY; } return true; } }; /* Coordinate map that is a combination of multiple other coordinate maps ----------------------------------------------------------------------------------------------------------------------*/ function ComboCoordMap(coordMaps) { this.coordMaps = coordMaps; } ComboCoordMap.prototype = { coordMaps: null, // an array of 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; } };