Skip to content

Commit 08d56c6

Browse files
committed
Convert GrabToPan to a standard class
This code is the last piece[1] of the viewer that's not using standard `class`es, and by converting this code we get rid of some now unneeded boilerplate code (slightly reducing the size of the *built* `web/viewer.js` file). Note that while this code was originally imported from a separate repository, it was last sync-ed with upstream *five years* ago which is why this re-factoring should be OK as far as I'm concerned (and we've done some other clean-up since then as well). --- [1] Technically the `web/debugger.js` file is left as well, however that code is first of all not bundled in the *built* `web/viewer.js` file and secondly it's not even loaded by default either.
1 parent ed6af0f commit 08d56c6

File tree

1 file changed

+58
-70
lines changed

1 file changed

+58
-70
lines changed

web/grab_to_pan.js

+58-70
Original file line numberDiff line numberDiff line change
@@ -14,97 +14,91 @@
1414
* limitations under the License.
1515
*/
1616

17-
/**
18-
* Construct a GrabToPan instance for a given HTML element.
19-
* @param options.element {Element}
20-
* @param options.ignoreTarget {function} optional. See `ignoreTarget(node)`
21-
* @param options.onActiveChanged {function(boolean)} optional. Called
22-
* when grab-to-pan is (de)activated. The first argument is a boolean that
23-
* shows whether grab-to-pan is activated.
24-
*/
25-
function GrabToPan(options) {
26-
this.element = options.element;
27-
this.document = options.element.ownerDocument;
28-
if (typeof options.ignoreTarget === "function") {
29-
this.ignoreTarget = options.ignoreTarget;
30-
}
31-
this.onActiveChanged = options.onActiveChanged;
32-
33-
// Bind the contexts to ensure that `this` always points to
34-
// the GrabToPan instance.
35-
this.activate = this.activate.bind(this);
36-
this.deactivate = this.deactivate.bind(this);
37-
this.toggle = this.toggle.bind(this);
38-
this._onmousedown = this._onmousedown.bind(this);
39-
this._onmousemove = this._onmousemove.bind(this);
40-
this._endPan = this._endPan.bind(this);
41-
42-
// This overlay will be inserted in the document when the mouse moves during
43-
// a grab operation, to ensure that the cursor has the desired appearance.
44-
const overlay = (this.overlay = document.createElement("div"));
45-
overlay.className = "grab-to-pan-grabbing";
46-
}
47-
GrabToPan.prototype = {
17+
// Class name of element which can be grabbed.
18+
const CSS_CLASS_GRAB = "grab-to-pan-grab";
19+
20+
class GrabToPan {
4821
/**
49-
* Class name of element which can be grabbed
22+
* Construct a GrabToPan instance for a given HTML element.
23+
* @param {Element} options.element
24+
* @param {function} [options.ignoreTarget] - See `ignoreTarget(node)`.
25+
* @param {function(boolean)} [options.onActiveChanged] - Called when
26+
* grab-to-pan is (de)activated. The first argument is a boolean that
27+
* shows whether grab-to-pan is activated.
5028
*/
51-
CSS_CLASS_GRAB: "grab-to-pan-grab",
29+
constructor(options) {
30+
this.element = options.element;
31+
this.document = options.element.ownerDocument;
32+
if (typeof options.ignoreTarget === "function") {
33+
this.ignoreTarget = options.ignoreTarget;
34+
}
35+
this.onActiveChanged = options.onActiveChanged;
36+
37+
// Bind the contexts to ensure that `this` always points to
38+
// the GrabToPan instance.
39+
this.activate = this.activate.bind(this);
40+
this.deactivate = this.deactivate.bind(this);
41+
this.toggle = this.toggle.bind(this);
42+
this._onMouseDown = this.#onMouseDown.bind(this);
43+
this._onMouseMove = this.#onMouseMove.bind(this);
44+
this._endPan = this.#endPan.bind(this);
45+
46+
// This overlay will be inserted in the document when the mouse moves during
47+
// a grab operation, to ensure that the cursor has the desired appearance.
48+
const overlay = (this.overlay = document.createElement("div"));
49+
overlay.className = "grab-to-pan-grabbing";
50+
}
5251

5352
/**
5453
* Bind a mousedown event to the element to enable grab-detection.
5554
*/
56-
activate: function GrabToPan_activate() {
55+
activate() {
5756
if (!this.active) {
5857
this.active = true;
59-
this.element.addEventListener("mousedown", this._onmousedown, true);
60-
this.element.classList.add(this.CSS_CLASS_GRAB);
61-
if (this.onActiveChanged) {
62-
this.onActiveChanged(true);
63-
}
58+
this.element.addEventListener("mousedown", this._onMouseDown, true);
59+
this.element.classList.add(CSS_CLASS_GRAB);
60+
61+
this.onActiveChanged?.(true);
6462
}
65-
},
63+
}
6664

6765
/**
6866
* Removes all events. Any pending pan session is immediately stopped.
6967
*/
70-
deactivate: function GrabToPan_deactivate() {
68+
deactivate() {
7169
if (this.active) {
7270
this.active = false;
73-
this.element.removeEventListener("mousedown", this._onmousedown, true);
71+
this.element.removeEventListener("mousedown", this._onMouseDown, true);
7472
this._endPan();
75-
this.element.classList.remove(this.CSS_CLASS_GRAB);
76-
if (this.onActiveChanged) {
77-
this.onActiveChanged(false);
78-
}
73+
this.element.classList.remove(CSS_CLASS_GRAB);
74+
75+
this.onActiveChanged?.(false);
7976
}
80-
},
77+
}
8178

82-
toggle: function GrabToPan_toggle() {
79+
toggle() {
8380
if (this.active) {
8481
this.deactivate();
8582
} else {
8683
this.activate();
8784
}
88-
},
85+
}
8986

9087
/**
9188
* Whether to not pan if the target element is clicked.
9289
* Override this method to change the default behaviour.
9390
*
94-
* @param node {Element} The target of the event
91+
* @param {Element} node - The target of the event.
9592
* @returns {boolean} Whether to not react to the click event.
9693
*/
97-
ignoreTarget: function GrabToPan_ignoreTarget(node) {
94+
ignoreTarget(node) {
9895
// Check whether the clicked element is, a child of, an input element/link.
9996
return node.matches(
10097
"a[href], a[href] *, input, textarea, button, button *, select, option"
10198
);
102-
},
99+
}
103100

104-
/**
105-
* @private
106-
*/
107-
_onmousedown: function GrabToPan__onmousedown(event) {
101+
#onMouseDown(event) {
108102
if (event.button !== 0 || this.ignoreTarget(event.target)) {
109103
return;
110104
}
@@ -122,7 +116,7 @@ GrabToPan.prototype = {
122116
this.scrollTopStart = this.element.scrollTop;
123117
this.clientXStart = event.clientX;
124118
this.clientYStart = event.clientY;
125-
this.document.addEventListener("mousemove", this._onmousemove, true);
119+
this.document.addEventListener("mousemove", this._onMouseMove, true);
126120
this.document.addEventListener("mouseup", this._endPan, true);
127121
// When a scroll event occurs before a mousemove, assume that the user
128122
// dragged a scrollbar (necessary for Opera Presto, Safari and IE)
@@ -135,12 +129,9 @@ GrabToPan.prototype = {
135129
if (focusedElement && !focusedElement.contains(event.target)) {
136130
focusedElement.blur();
137131
}
138-
},
132+
}
139133

140-
/**
141-
* @private
142-
*/
143-
_onmousemove: function GrabToPan__onmousemove(event) {
134+
#onMouseMove(event) {
144135
this.element.removeEventListener("scroll", this._endPan, true);
145136
if (!(event.buttons & 1)) {
146137
// The left mouse button is released.
@@ -164,18 +155,15 @@ GrabToPan.prototype = {
164155
if (!this.overlay.parentNode) {
165156
document.body.appendChild(this.overlay);
166157
}
167-
},
158+
}
168159

169-
/**
170-
* @private
171-
*/
172-
_endPan: function GrabToPan__endPan() {
160+
#endPan() {
173161
this.element.removeEventListener("scroll", this._endPan, true);
174-
this.document.removeEventListener("mousemove", this._onmousemove, true);
162+
this.document.removeEventListener("mousemove", this._onMouseMove, true);
175163
this.document.removeEventListener("mouseup", this._endPan, true);
176164
// Note: ChildNode.remove doesn't throw if the parentNode is undefined.
177165
this.overlay.remove();
178-
},
179-
};
166+
}
167+
}
180168

181169
export { GrabToPan };

0 commit comments

Comments
 (0)