document.getAnonymousElementByAttribute(this, "anonid", "cstack"); document.getAnonymousElementByAttribute(this, "anonid", "ccanvas"); return document.getAnonymousElementByAttribute(this, "anonid", "display-list"); null = 0) zoomDelta *= -1; this._zoomLevel = this._clampZoomLevel(this._zoomLevel + zoomDelta); this._browserToCanvas(); ]]> /** * Retrieve the content element for a given point (relative to the top * left corner of the browser window). */ var cdoc = this.browser.contentDocument; // Return the document width/height for XUL documents (which is // essentially the same as the viewport width/height). if (cdoc instanceof XULDocument) return [cdoc.width, cdoc.height]; // These might not exist yet depending on page load state var body = cdoc.body || {}; var html = cdoc.documentElement || {}; var w = Math.max(body.scrollWidth, html.scrollWidth); var h = Math.max(body.scrollHeight, html.scrollHeight); if (isNaN(w) || isNaN(h)) return [this._canvas.width, this._canvas.height]; return [w, h]; /** * Given a set of page coordinates, constrain them such that they * fit within the rect defined by [0,0] and [x,y], where x and y are * the maximum values that can be used for the canvas' .top and .left * such that it is still within the scrollable area of the page, taking * into account the current zoomLevel. */ 0) { // dt should never be less than 0 this.dragData.velocityX = dx / dt; this.dragData.velocityY = dy / dt; // Save the original x.y we're starting from to make sure // we don't go backwards this.dragData.originalX = this.dragData.dragX; this.dragData.originalY = this.dragData.dragY; // s = S0 + 0.5 * v0^2 * 1/CoK); s = position, s0 = initial pos // v0 = initial velocity, CoK = Coefficient of Kinetic friction // All in page coords let idealDestScreenX = this.dragData.dragX + Math.abs(this.dragData.velocityX) * this.dragData.velocityX * 200; let idealDestScreenY = this.dragData.dragY + Math.abs(this.dragData.velocityY) * this.dragData.velocityY * 200 let [destPageX, destPageY] = this._constrainPanCoords(-this._screenToPage(idealDestScreenX), -this._screenToPage(idealDestScreenY)); // Convert to screen coords this.dragData.destinationX = -this._pageToScreen(destPageX); this.dragData.destinationY = -this._pageToScreen(destPageY); // If we have a kinetic timer, kill it. This shouldn't happen if (this.dragData.kineticId) window.clearInterval(this.dragData.kineticId); // Start timer for kinetic movements let interval = dt / (this.PAN_EVENTS_TO_TRACK - 1); this.dragData.kineticId = window.setInterval(this._doKinetic, interval, this, interval); } else { // dt <= 0, this is bad this._endPan(); } } else { // p1 or p2 is null, either we didn't pan enough, or something went wrong this._endPan() } // Clear out the old events since they aren't needed anymore for (var i = 0; i < this.PAN_EVENTS_TO_TRACK; i++) { this._panEventTracker[i] = null; } ]]> nextX && nextX > self.dragData.destinationX) || (self.dragData.originalX < nextX && nextX < self.dragData.destinationX)) self.dragData.dragX = nextX; else self.dragData.dragX = self.dragData.destinationX; if((self.dragData.originalY > nextY && nextY > self.dragData.destinationY) || (self.dragData.originalY < nextY && nextY < self.dragData.destinationY)) self.dragData.dragY = nextY; else self.dragData.dragY = self.dragData.destinationY; self._updateCanvasPosition(); // calculate how much we've actually moved and end if less than 4px let actualDx = startX - self.dragData.dragX; let actualDy = startY - self.dragData.dragY; if ((actualDx / (self.dragData.destinationX - self.dragData.originalX) < 0 && actualDy / (self.dragData.destinationY - self.dragData.originalY) < 0) || (Math.abs(actualDx) < 4 && Math.abs(actualDy) < 4)) { self._endKinetic(); } ]]> 10 || Math.abs(this.deckbrowser.dragData.sY - aEvent.screenY) > 10)) { clearTimeout(this.deckbrowser._dragStartTimeout); this.deckbrowser._dragStartTimer(); } else { return false; } } var dx = this.deckbrowser.dragData.sX - aEvent.screenX; var dy = this.deckbrowser.dragData.sY - aEvent.screenY; // Filter out noise in big panning operations which are // almost certainly intended to be on-axis horizontal or // vertical pans. if (Math.abs(dx) > 40 || Math.abs(dy) > 40) { if (Math.abs(dx/dy) < 0.3) // dx is a lot less than dy, probably a vertical drag dx = 0; else if (Math.abs(dy/dx) < 0.3) // probably a horizontal drag dy = 0; } let now = Date.now(); this.deckbrowser._panEventTrackerIndex = (this.deckbrowser._panEventTrackerIndex + 1) % this.deckbrowser.PAN_EVENTS_TO_TRACK; var pt = { x: aEvent.screenX, y: aEvent.screenY, t: now }; this.deckbrowser._panEventTracker[this.deckbrowser._panEventTrackerIndex] = pt; this.deckbrowser._moveCanvas(dx, dy); aEvent.preventDefault(); return true; }, DOMMouseScroll: function seh_DOMMouseScroll(aEvent) { this.deckbrowser.zoom(aEvent.detail); }, dblclick: function seh_dblclick(aEvent) { var target = aEvent.originalTarget; var dragData = this.deckbrowser.dragData; if (this.deckbrowser._zoomed) { // reset zoom, pan state this.deckbrowser._zoomLevel = this._oldZoomLevel; [dragData.pageX, dragData.pageY] = [dragData.oldPageX, dragData.oldPageY]; this.deckbrowser._browserToCanvas(); this.deckbrowser._zoomed = false; } else { var element = this.deckbrowser.elementFromPoint(aEvent.clientX, aEvent.clientY); if (!element) { Components.utils.reportError("elementFromPoint returned null\n"); return; } // Find the nearest non-inline ancestor while (element.parentNode) { var display = window.getComputedStyle(element, "").getPropertyValue("display"); var zoomable = /table/.test(display) || /block/.test(display); if (zoomable) break; element = element.parentNode; } // Remember pageX/pageY [dragData.oldPageX, dragData.oldPageY] = [dragData.pageX, dragData.pageY]; this._oldZoomLevel = this.deckbrowser._zoomLevel; this.deckbrowser.zoomToElement(element); this.deckbrowser._zoomed = true; } } }); ]]>