isMacWebKit.js

// 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; } }
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 mousewheel. Note that Example is also a practical example of the element geometry and CSS positioning techniques explained.

Be the first to comment

You can use [html][/html], [css][/css], [php][/php] and more to embed the code. Urls are automatically hyperlinked. Line breaks and paragraphs are automatically generated.