Created
May 12, 2019 23:20
-
-
Save luisenriquecorona/b10e162fea9e335fcde41ff98cd26a76 to your computer and use it in GitHub Desktop.
In order to work correctly in all common browsers, Example must perform some browser testing. The example anticipates the DOM Level 3 Events specifi- cation and includes code to use the wheel event when browsers implement it.6 It also includes some future-proofing to stop using the DOMMouseScroll event when Firefox starts firing wheel or mousewh…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Enclose the content element in a frame or viewport of the specified width | |
// and height (minimum 50x50). The optional contentX and contentY arguments | |
// specify the initial offset of the content relative to the frame. (If | |
// specified, they must be <= 0.) The frame has mousewheel event handlers that | |
// allow the user to pan the element, and to shrink or enlarge the frame. | |
function enclose(content, framewidth, frameheight, contentX, contentY) { | |
// These arguments aren't just the initial values: they maintain the | |
// current state and are used and modified by the mousewheel handler. | |
framewidth = Math.max(framewidth, 50); | |
frameheight = Math.max(frameheight, 50); | |
contentX = Math.min(contentX, 0) || 0; | |
contentY = Math.min(contentY, 0) || 0; | |
// Create the frame element and set a CSS classname and styles | |
var frame = document.createElement("div"); | |
frame.className = "enclosure"; // So we can define styles in a stylesheet | |
frame.style.width = framewidth + "px"; // Set the frame size. | |
frame.style.height = frameheight + "px"; | |
frame.style.overflow = "hidden"; // No scrollbars, no overflow | |
frame.style.boxSizing = "border-box"; // Border-box simplifies the | |
frame.style.webkitBoxSizing = "border-box"; // calculations for resizing | |
frame.style.MozBoxSizing = "border-box"; // the frame. | |
// Put the frame in the document and move the content elt into the frame. | |
content.parentNode.insertBefore(frame, content); | |
frame.appendChild(content); | |
// Position the element relative to the frame | |
content.style.position = "relative"; | |
content.style.left = contentX + "px"; | |
content.style.top = contentY + "px"; | |
// We'll need to work around some browser-specific quirks below | |
var isMacWebkit = (navigator.userAgent.indexOf("Macintosh") !== -1 && | |
navigator.userAgent.indexOf("WebKit") !== -1); | |
var isFirefox = (navigator.userAgent.indexOf("Gecko") !== -1); | |
// Register mousewheel event handlers. | |
frame.onwheel = wheelHandler; // Future browsers | |
frame.onmousewheel = wheelHandler; // Most current browsers | |
if (isFirefox) // Firefox only | |
frame.addEventListener("DOMMouseScroll", wheelHandler, false); | |
function wheelHandler(event) { | |
var e = event || window.event; // Standard or IE event object | |
// Extract the amount of rotation from the event object, looking | |
// for properties of a wheel event object, a mousewheel event object | |
// (in both its 2D and 1D forms), and the Firefox DOMMouseScroll event. | |
// Scale the deltas so that one "click" toward the screen is 30 pixels. | |
// If future browsers fire both "wheel" and "mousewheel" for the same | |
// event, we'll end up double-counting it here. Hopefully, however, | |
// cancelling the wheel event will prevent generation of mousewheel. | |
var deltaX = e.deltaX*-30 || // wheel event | |
e.wheelDeltaX/4 || // mousewheel | |
0; // property not defined | |
var deltaY = e.deltaY*-30 || // wheel event | |
e.wheelDeltaY/4 || // mousewheel event in Webkit | |
(e.wheelDeltaY===undefined && // if there is no 2D property then | |
e.wheelDelta/4) || // use the 1D wheel property | |
e.detail*-10 || // Firefox DOMMouseScroll event | |
0; // property not defined | |
// Most browsers generate one event with delta 120 per mousewheel click. | |
// On Macs, however, the mousewheels seem to be velocity-sensitive and | |
// the delta values are often larger multiples of 120, at | |
// least with the Apple Mouse. Use browser-testing to defeat this. | |
if (isMacWebkit) { | |
deltaX /= 30; | |
deltaY /= 30; | |
} | |
// If we ever get a mousewheel or wheel event in (a future version of) | |
// Firefox, then we don't need DOMMouseScroll anymore. | |
if (isFirefox && e.type !== "DOMMouseScroll") | |
frame.removeEventListener("DOMMouseScroll", wheelHandler, false); | |
// Get the current dimensions of the content element | |
var contentbox = content.getBoundingClientRect(); | |
var contentwidth = contentbox.right - contentbox.left; | |
var contentheight = contentbox.bottom - contentbox.top; | |
if (e.altKey) { // If Alt key is held down, resize the frame | |
if (deltaX) { | |
framewidth -= deltaX; // New width, but not bigger than the | |
framewidth = Math.min(framwidth, contentwidth); // content | |
framewidth = Math.max(framewidth,50); // and no less than 50. | |
frame.style.width = framewidth + "px"; // Set it on frame | |
} | |
if (deltaY) { | |
frameheight -= deltaY; // Do the same for the frame height | |
frameheight = Math.min(frameheight, contentheight); | |
frameheight = Math.max(frameheight-deltaY, 50); | |
frame.style.height = frameheight + "px"; | |
} | |
} | |
else { // Without the Alt modifier, pan the content within the frame | |
if (deltaX) { | |
// Don't scroll more than this | |
var minoffset = Math.min(framewidth-contentwidth, 0); | |
// Add deltaX to contentX, but don't go lower than minoffset | |
contentX = Math.max(contentX + deltaX, minoffset); | |
contentX = Math.min(contentX, 0); // or higher than 0 | |
content.style.left = contentX + "px"; // Set new offset | |
} | |
if (deltaY) { | |
var minoffset = Math.min(frameheight - contentheight, 0); | |
// Add deltaY to contentY, but don't go lower than minoffset | |
contentY = Math.max(contentY + deltaY, minoffset); | |
contentY = Math.min(contentY, 0); // Or higher than 0 | |
content.style.top = contentY + "px"; // Set the new offset. | |
} | |
} | |
// Don't let this event bubble. Prevent any default action. | |
// This stops the browser from using the mousewheel event to scroll | |
// the document. Hopefully calling preventDefault() on a wheel event | |
// will also prevent the generation of a mousewheel event for the | |
// same rotation. | |
if (e.preventDefault) e.preventDefault(); | |
if (e.stopPropagation) e.stopPropagation(); | |
e.cancelBubble = true; // IE events | |
e.returnValue = false; // IE events | |
return false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment