/*================================================== * An "ether" is a object that maps date/time to pixel coordinates. *================================================== */ /*================================================== * Linear Ether *================================================== */ Timeline.LinearEther = function(params) { this._params = params; this._interval = params.interval; this._pixelsPerInterval = params.pixelsPerInterval; }; Timeline.LinearEther.prototype.initialize = function(band, timeline) { this._band = band; this._timeline = timeline; this._unit = timeline.getUnit(); if ("startsOn" in this._params) { this._start = this._unit.parseFromObject(this._params.startsOn); } else if ("endsOn" in this._params) { this._start = this._unit.parseFromObject(this._params.endsOn); this.shiftPixels(-this._timeline.getPixelLength()); } else if ("centersOn" in this._params) { this._start = this._unit.parseFromObject(this._params.centersOn); this.shiftPixels(-this._timeline.getPixelLength() / 2); } else { this._start = this._unit.makeDefaultValue(); this.shiftPixels(-this._timeline.getPixelLength() / 2); } }; Timeline.LinearEther.prototype.setDate = function(date) { this._start = this._unit.cloneValue(date); }; Timeline.LinearEther.prototype.shiftPixels = function(pixels) { var numeric = this._interval * pixels / this._pixelsPerInterval; this._start = this._unit.change(this._start, numeric); }; Timeline.LinearEther.prototype.dateToPixelOffset = function(date) { var numeric = this._unit.compare(date, this._start); return this._pixelsPerInterval * numeric / this._interval; }; Timeline.LinearEther.prototype.pixelOffsetToDate = function(pixels) { var numeric = pixels * this._interval / this._pixelsPerInterval; return this._unit.change(this._start, numeric); }; Timeline.LinearEther.prototype.zoom = function(zoomIn) { var netIntervalChange = 0; var currentZoomIndex = this._band._zoomIndex; var newZoomIndex = currentZoomIndex; if (zoomIn && (currentZoomIndex > 0)) { newZoomIndex = currentZoomIndex - 1; } if (!zoomIn && (currentZoomIndex < (this._band._zoomSteps.length - 1))) { newZoomIndex = currentZoomIndex + 1; } this._band._zoomIndex = newZoomIndex; this._interval = SimileAjax.DateTime.gregorianUnitLengths[this._band._zoomSteps[newZoomIndex].unit]; this._pixelsPerInterval = this._band._zoomSteps[newZoomIndex].pixelsPerInterval; netIntervalChange = this._band._zoomSteps[newZoomIndex].unit - this._band._zoomSteps[currentZoomIndex].unit; return netIntervalChange; }; /*================================================== * Hot Zone Ether *================================================== */ Timeline.HotZoneEther = function(params) { this._params = params; this._interval = params.interval; this._pixelsPerInterval = params.pixelsPerInterval; this._theme = params.theme; }; Timeline.HotZoneEther.prototype.initialize = function(band, timeline) { this._band = band; this._timeline = timeline; this._unit = timeline.getUnit(); this._zones = [{ startTime: Number.NEGATIVE_INFINITY, endTime: Number.POSITIVE_INFINITY, magnify: 1 }]; var params = this._params; for (var i = 0; i < params.zones.length; i++) { var zone = params.zones[i]; var zoneStart = this._unit.parseFromObject(zone.start); var zoneEnd = this._unit.parseFromObject(zone.end); for (var j = 0; j < this._zones.length && this._unit.compare(zoneEnd, zoneStart) > 0; j++) { var zone2 = this._zones[j]; if (this._unit.compare(zoneStart, zone2.endTime) < 0) { if (this._unit.compare(zoneStart, zone2.startTime) > 0) { this._zones.splice(j, 0, { startTime: zone2.startTime, endTime: zoneStart, magnify: zone2.magnify }); j++; zone2.startTime = zoneStart; } if (this._unit.compare(zoneEnd, zone2.endTime) < 0) { this._zones.splice(j, 0, { startTime: zoneStart, endTime: zoneEnd, magnify: zone.magnify * zone2.magnify }); j++; zone2.startTime = zoneEnd; zoneStart = zoneEnd; } else { zone2.magnify *= zone.magnify; zoneStart = zone2.endTime; } } // else, try the next existing zone } } if ("startsOn" in this._params) { this._start = this._unit.parseFromObject(this._params.startsOn); } else if ("endsOn" in this._params) { this._start = this._unit.parseFromObject(this._params.endsOn); this.shiftPixels(-this._timeline.getPixelLength()); } else if ("centersOn" in this._params) { this._start = this._unit.parseFromObject(this._params.centersOn); this.shiftPixels(-this._timeline.getPixelLength() / 2); } else { this._start = this._unit.makeDefaultValue(); this.shiftPixels(-this._timeline.getPixelLength() / 2); } }; Timeline.HotZoneEther.prototype.setDate = function(date) { this._start = this._unit.cloneValue(date); }; Timeline.HotZoneEther.prototype.shiftPixels = function(pixels) { this._start = this.pixelOffsetToDate(pixels); }; Timeline.HotZoneEther.prototype.dateToPixelOffset = function(date) { return this._dateDiffToPixelOffset(this._start, date); }; Timeline.HotZoneEther.prototype.pixelOffsetToDate = function(pixels) { return this._pixelOffsetToDate(pixels, this._start); }; Timeline.HotZoneEther.prototype.zoom = function(zoomIn) { var netIntervalChange = 0; var currentZoomIndex = this._band._zoomIndex; var newZoomIndex = currentZoomIndex; if (zoomIn && (currentZoomIndex > 0)) { newZoomIndex = currentZoomIndex - 1; } if (!zoomIn && (currentZoomIndex < (this._band._zoomSteps.length - 1))) { newZoomIndex = currentZoomIndex + 1; } this._band._zoomIndex = newZoomIndex; this._interval = SimileAjax.DateTime.gregorianUnitLengths[this._band._zoomSteps[newZoomIndex].unit]; this._pixelsPerInterval = this._band._zoomSteps[newZoomIndex].pixelsPerInterval; netIntervalChange = this._band._zoomSteps[newZoomIndex].unit - this._band._zoomSteps[currentZoomIndex].unit; return netIntervalChange; }; Timeline.HotZoneEther.prototype._dateDiffToPixelOffset = function(fromDate, toDate) { var scale = this._getScale(); var fromTime = fromDate; var toTime = toDate; var pixels = 0; if (this._unit.compare(fromTime, toTime) < 0) { var z = 0; while (z < this._zones.length) { if (this._unit.compare(fromTime, this._zones[z].endTime) < 0) { break; } z++; } while (this._unit.compare(fromTime, toTime) < 0) { var zone = this._zones[z]; var toTime2 = this._unit.earlier(toTime, zone.endTime); pixels += (this._unit.compare(toTime2, fromTime) / (scale / zone.magnify)); fromTime = toTime2; z++; } } else { var z = this._zones.length - 1; while (z >= 0) { if (this._unit.compare(fromTime, this._zones[z].startTime) > 0) { break; } z--; } while (this._unit.compare(fromTime, toTime) > 0) { var zone = this._zones[z]; var toTime2 = this._unit.later(toTime, zone.startTime); pixels += (this._unit.compare(toTime2, fromTime) / (scale / zone.magnify)); fromTime = toTime2; z--; } } return pixels; }; Timeline.HotZoneEther.prototype._pixelOffsetToDate = function(pixels, fromDate) { var scale = this._getScale(); var time = fromDate; if (pixels > 0) { var z = 0; while (z < this._zones.length) { if (this._unit.compare(time, this._zones[z].endTime) < 0) { break; } z++; } while (pixels > 0) { var zone = this._zones[z]; var scale2 = scale / zone.magnify; if (zone.endTime == Number.POSITIVE_INFINITY) { time = this._unit.change(time, pixels * scale2); pixels = 0; } else { var pixels2 = this._unit.compare(zone.endTime, time) / scale2; if (pixels2 > pixels) { time = this._unit.change(time, pixels * scale2); pixels = 0; } else { time = zone.endTime; pixels -= pixels2; } } z++; } } else { var z = this._zones.length - 1; while (z >= 0) { if (this._unit.compare(time, this._zones[z].startTime) > 0) { break; } z--; } pixels = -pixels; while (pixels > 0) { var zone = this._zones[z]; var scale2 = scale / zone.magnify; if (zone.startTime == Number.NEGATIVE_INFINITY) { time = this._unit.change(time, -pixels * scale2); pixels = 0; } else { var pixels2 = this._unit.compare(time, zone.startTime) / scale2; if (pixels2 > pixels) { time = this._unit.change(time, -pixels * scale2); pixels = 0; } else { time = zone.startTime; pixels -= pixels2; } } z--; } } return time; }; Timeline.HotZoneEther.prototype._getScale = function() { return this._interval / this._pixelsPerInterval; };