| /** |
| * @licstart The following is the entire license notice for the |
| * Javascript code in this page |
| * |
| * Copyright 2020 Mozilla Foundation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| * @licend The above is the entire license notice for the |
| * Javascript code in this page |
| */ |
| "use strict"; |
| |
| Object.defineProperty(exports, "__esModule", { |
| value: true |
| }); |
| exports.GrabToPan = GrabToPan; |
| |
| function GrabToPan(options) { |
| this.element = options.element; |
| this.document = options.element.ownerDocument; |
| |
| if (typeof options.ignoreTarget === "function") { |
| this.ignoreTarget = options.ignoreTarget; |
| } |
| |
| this.onActiveChanged = options.onActiveChanged; |
| this.activate = this.activate.bind(this); |
| this.deactivate = this.deactivate.bind(this); |
| this.toggle = this.toggle.bind(this); |
| this._onmousedown = this._onmousedown.bind(this); |
| this._onmousemove = this._onmousemove.bind(this); |
| this._endPan = this._endPan.bind(this); |
| const overlay = this.overlay = document.createElement("div"); |
| overlay.className = "grab-to-pan-grabbing"; |
| } |
| |
| GrabToPan.prototype = { |
| CSS_CLASS_GRAB: "grab-to-pan-grab", |
| activate: function GrabToPan_activate() { |
| if (!this.active) { |
| this.active = true; |
| this.element.addEventListener("mousedown", this._onmousedown, true); |
| this.element.classList.add(this.CSS_CLASS_GRAB); |
| |
| if (this.onActiveChanged) { |
| this.onActiveChanged(true); |
| } |
| } |
| }, |
| deactivate: function GrabToPan_deactivate() { |
| if (this.active) { |
| this.active = false; |
| this.element.removeEventListener("mousedown", this._onmousedown, true); |
| |
| this._endPan(); |
| |
| this.element.classList.remove(this.CSS_CLASS_GRAB); |
| |
| if (this.onActiveChanged) { |
| this.onActiveChanged(false); |
| } |
| } |
| }, |
| toggle: function GrabToPan_toggle() { |
| if (this.active) { |
| this.deactivate(); |
| } else { |
| this.activate(); |
| } |
| }, |
| ignoreTarget: function GrabToPan_ignoreTarget(node) { |
| return node[matchesSelector]("a[href], a[href] *, input, textarea, button, button *, select, option"); |
| }, |
| _onmousedown: function GrabToPan__onmousedown(event) { |
| if (event.button !== 0 || this.ignoreTarget(event.target)) { |
| return; |
| } |
| |
| if (event.originalTarget) { |
| try { |
| event.originalTarget.tagName; |
| } catch (e) { |
| return; |
| } |
| } |
| |
| this.scrollLeftStart = this.element.scrollLeft; |
| this.scrollTopStart = this.element.scrollTop; |
| this.clientXStart = event.clientX; |
| this.clientYStart = event.clientY; |
| this.document.addEventListener("mousemove", this._onmousemove, true); |
| this.document.addEventListener("mouseup", this._endPan, true); |
| this.element.addEventListener("scroll", this._endPan, true); |
| event.preventDefault(); |
| event.stopPropagation(); |
| const focusedElement = document.activeElement; |
| |
| if (focusedElement && !focusedElement.contains(event.target)) { |
| focusedElement.blur(); |
| } |
| }, |
| _onmousemove: function GrabToPan__onmousemove(event) { |
| this.element.removeEventListener("scroll", this._endPan, true); |
| |
| if (isLeftMouseReleased(event)) { |
| this._endPan(); |
| |
| return; |
| } |
| |
| const xDiff = event.clientX - this.clientXStart; |
| const yDiff = event.clientY - this.clientYStart; |
| const scrollTop = this.scrollTopStart - yDiff; |
| const scrollLeft = this.scrollLeftStart - xDiff; |
| |
| if (this.element.scrollTo) { |
| this.element.scrollTo({ |
| top: scrollTop, |
| left: scrollLeft, |
| behavior: "instant" |
| }); |
| } else { |
| this.element.scrollTop = scrollTop; |
| this.element.scrollLeft = scrollLeft; |
| } |
| |
| if (!this.overlay.parentNode) { |
| document.body.appendChild(this.overlay); |
| } |
| }, |
| _endPan: function GrabToPan__endPan() { |
| this.element.removeEventListener("scroll", this._endPan, true); |
| this.document.removeEventListener("mousemove", this._onmousemove, true); |
| this.document.removeEventListener("mouseup", this._endPan, true); |
| this.overlay.remove(); |
| } |
| }; |
| let matchesSelector; |
| ["webkitM", "mozM", "msM", "oM", "m"].some(function (prefix) { |
| let name = prefix + "atches"; |
| |
| if (name in document.documentElement) { |
| matchesSelector = name; |
| } |
| |
| name += "Selector"; |
| |
| if (name in document.documentElement) { |
| matchesSelector = name; |
| } |
| |
| return matchesSelector; |
| }); |
| const isNotIEorIsIE10plus = !document.documentMode || document.documentMode > 9; |
| const chrome = window.chrome; |
| const isChrome15OrOpera15plus = chrome && (chrome.webstore || chrome.app); |
| const isSafari6plus = /Apple/.test(navigator.vendor) && /Version\/([6-9]\d*|[1-5]\d+)/.test(navigator.userAgent); |
| |
| function isLeftMouseReleased(event) { |
| if ("buttons" in event && isNotIEorIsIE10plus) { |
| return !(event.buttons & 1); |
| } |
| |
| if (isChrome15OrOpera15plus || isSafari6plus) { |
| return event.which === 0; |
| } |
| |
| return false; |
| } |