function browser() { var browser = "Unknown browser"; if(!!window.chrome && !(!!window.opera)) browser = 'chrome'; // Chrome 1+ if(typeof InstallTrigger !== 'undefined') browser = 'firefox'; // Firefox 1.0+ if(!!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0) browser = 'opera'; // Opera 8.0+ (UA detection to detect Blink/v8-powered Opera) if(/*@cc_on!@*/false || !!document.documentMode) browser = 'ie'; // At least IE6 if(Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0) browser = 'safari'; // At least Safari 3+: "[object HTMLElementConstructor]" return browser; } function is_touch_device() { return ('ontouchstart' in document.documentElement); } var onePager = jQuery('.mk-edge-one-pager').length; if(!onePager && (browser() === 'chrome' || browser() === 'ie_11')) { // SmoothScroll for websites v1.2.1 // Licensed under the terms of the MIT license. // People involved // - Balazs Galambosi (maintainer) // - Michael Herf (Pulse Algorithm) (function(){ // Scroll Variables (tweakable) var defaultOptions = { // Scrolling Core frameRate : 150, // [Hz] animationTime : 400, // [px] stepSize : 120, // [px] // Pulse (less tweakable) // ratio of "tail" to "acceleration" pulseAlgorithm : true, pulseScale : 8, pulseNormalize : 1, // Acceleration accelerationDelta : 20, // 20 accelerationMax : 1, // 1 // Keyboard Settings keyboardSupport : true, // option arrowScroll : 50, // [px] // Other touchpadSupport : true, fixedBackground : true, excluded : "" }; var options = defaultOptions; // Other Variables var isExcluded = false; var isFrame = false; var direction = { x: 0, y: 0 }; var initDone = false; var root = document.documentElement; var activeElement; var observer; var deltaBuffer = [ 120, 120, 120 ]; var key = { left: 37, up: 38, right: 39, down: 40, spacebar: 32, pageup: 33, pagedown: 34, end: 35, home: 36 }; /*********************************************** * SETTINGS ***********************************************/ var options = defaultOptions; /*********************************************** * INITIALIZE ***********************************************/ /** * Tests if smooth scrolling is allowed. Shuts down everything if not. */ function initTest() { var disableKeyboard = false; // disable keyboard support if anything above requested it if (disableKeyboard) { removeEvent("keydown", keydown); } if (options.keyboardSupport && !disableKeyboard) { addEvent("keydown", keydown); } } /** * Sets up scrolls array, determines if frames are involved. */ function init() { if (!document.body) return; if(is_touch_device()) return; var body = document.body; var html = document.documentElement; var windowHeight = window.innerHeight; var scrollHeight = body.scrollHeight; // check compat mode for root element root = (document.compatMode.indexOf('CSS') >= 0) ? html : body; activeElement = body; initTest(); initDone = true; // Checks if this script is running in a frame if (top != self) { isFrame = true; } /** * This fixes a bug where the areas left and right to * the content does not trigger the onmousewheel event * on some pages. e.g.: html, body { height: 100% } */ else if (scrollHeight > windowHeight && (body.offsetHeight <= windowHeight || html.offsetHeight <= windowHeight)) { html.style.height = 'auto'; setTimeout(refresh, 10); // clearfix if (root.offsetHeight <= windowHeight) { var underlay = document.createElement("div"); underlay.style.clear = "both"; body.appendChild(underlay); } } // disable fixed background if (!options.fixedBackground && !isExcluded) { body.style.backgroundAttachment = "scroll"; html.style.backgroundAttachment = "scroll"; } } /************************************************ * SCROLLING ************************************************/ var que = []; var pending = false; var lastScroll = +new Date; /** * Pushes scroll actions to the scrolling queue. */ function scrollArray(elem, left, top, delay) { delay || (delay = 1000); directionCheck(left, top); if (options.accelerationMax != 1) { var now = +new Date; var elapsed = now - lastScroll; if (elapsed < options.accelerationDelta) { var factor = (1 + (30 / elapsed)) / 2; if (factor > 1) { factor = Math.min(factor, options.accelerationMax); left *= factor; top *= factor; } } lastScroll = +new Date; } // push a scroll command que.push({ x: left, y: top, lastX: (left < 0) ? 0.99 : -0.99, lastY: (top < 0) ? 0.99 : -0.99, start: +new Date }); // don't act if there's a pending queue if (pending) { return; } var scrollWindow = (elem === document.body); var step = function (time) { var now = +new Date; var scrollX = 0; var scrollY = 0; for (var i = 0; i < que.length; i++) { var item = que[i]; var elapsed = now - item.start; var finished = (elapsed >= options.animationTime); // scroll position: [0, 1] var position = (finished) ? 1 : elapsed / options.animationTime; // easing [optional] if (options.pulseAlgorithm) { position = pulse(position); } // only need the difference var x = (item.x * position - item.lastX) >> 0; var y = (item.y * position - item.lastY) >> 0; // add this to the total scrolling scrollX += x; scrollY += y; // update last values item.lastX += x; item.lastY += y; // delete and step back if it's over if (finished) { que.splice(i, 1); i--; } } // scroll left and top if (scrollWindow) { window.scrollBy(scrollX, scrollY); } else { if (scrollX) elem.scrollLeft += scrollX; if (scrollY) elem.scrollTop += scrollY; } // clean up if there's nothing left to do if (!left && !top) { que = []; } if (que.length) { requestFrame(step, elem, (delay / options.frameRate + 1)); } else { pending = false; } }; // start a new queue of actions requestFrame(step, elem, 0); pending = true; } /*********************************************** * EVENTS ***********************************************/ /** * Mouse wheel handler. * @param {Object} event */ function wheel(event) { if (!initDone) { init(); } var target = event.target; var overflowing = overflowingAncestor(target); // use default if there's no overflowing // element or default action is prevented if (!overflowing || event.defaultPrevented || isNodeName(activeElement, "embed") || (isNodeName(target, "embed") && /\.pdf/i.test(target.src))) { return true; } var deltaX = event.wheelDeltaX || 0; var deltaY = event.wheelDeltaY || 0; // use wheelDelta if deltaX/Y is not available if (!deltaX && !deltaY) { deltaY = event.wheelDelta || 0; } // check if it's a touchpad scroll that should be ignored if (!options.touchpadSupport && isTouchpad(deltaY)) { return true; } // scale by step size // delta is 120 most of the time // synaptics seems to send 1 sometimes if (Math.abs(deltaX) > 1.2) { deltaX *= options.stepSize / 120; } if (Math.abs(deltaY) > 1.2) { deltaY *= options.stepSize / 120; } scrollArray(overflowing, -deltaX, -deltaY); event.preventDefault(); } /** * Keydown event handler. * @param {Object} event */ function keydown(event) { var target = event.target; var modifier = event.ctrlKey || event.altKey || event.metaKey || (event.shiftKey && event.keyCode !== key.spacebar); // do nothing if user is editing text // or using a modifier key (except shift) // or in a dropdown if ( /input|textarea|select|embed/i.test(target.nodeName) || target.isContentEditable || event.defaultPrevented || modifier ) { return true; } // spacebar should trigger button press if (isNodeName(target, "button") && event.keyCode === key.spacebar) { return true; } var shift, x = 0, y = 0; var elem = overflowingAncestor(activeElement); var clientHeight = elem.clientHeight; if (elem == document.body) { clientHeight = window.innerHeight; } switch (event.keyCode) { case key.up: y = -options.arrowScroll; break; case key.down: y = options.arrowScroll; break; case key.spacebar: // (+ shift) shift = event.shiftKey ? 1 : -1; y = -shift * clientHeight * 0.9; break; case key.pageup: y = -clientHeight * 0.9; break; case key.pagedown: y = clientHeight * 0.9; break; case key.home: y = -elem.scrollTop; break; case key.end: var damt = elem.scrollHeight - elem.scrollTop - clientHeight; y = (damt > 0) ? damt+10 : 0; break; case key.left: x = -options.arrowScroll; break; case key.right: x = options.arrowScroll; break; default: return true; // a key we don't care about } scrollArray(elem, x, y); event.preventDefault(); } /** * Mousedown event only for updating activeElement */ function mousedown(event) { activeElement = event.target; } /*********************************************** * OVERFLOW ***********************************************/ var cache = {}; // cleared out every once in while setInterval(function () { cache = {}; }, 10 * 1000); var uniqueID = (function () { var i = 0; return function (el) { return el.uniqueID || (el.uniqueID = i++); }; })(); function setCache(elems, overflowing) { for (var i = elems.length; i--;) cache[uniqueID(elems[i])] = overflowing; return overflowing; } function overflowingAncestor(el) { var elems = []; var rootScrollHeight = root.scrollHeight; do { var cached = cache[uniqueID(el)]; if (cached) { return setCache(elems, cached); } elems.push(el); if (rootScrollHeight === el.scrollHeight) { if (!isFrame || root.clientHeight + 10 < rootScrollHeight) { return setCache(elems, document.body); // scrolling root in WebKit } } else if (el.clientHeight + 10 < el.scrollHeight) { overflow = getComputedStyle(el, "").getPropertyValue("overflow-y"); if (overflow === "scroll" || overflow === "auto") { return setCache(elems, el); } } } while (el = el.parentNode); } /*********************************************** * HELPERS ***********************************************/ function addEvent(type, fn, bubble) { window.addEventListener(type, fn, (bubble||false)); } function removeEvent(type, fn, bubble) { window.removeEventListener(type, fn, (bubble||false)); } function isNodeName(el, tag) { return (el.nodeName||"").toLowerCase() === tag.toLowerCase(); } function directionCheck(x, y) { x = (x > 0) ? 1 : -1; y = (y > 0) ? 1 : -1; if (direction.x !== x || direction.y !== y) { direction.x = x; direction.y = y; que = []; lastScroll = 0; } } var deltaBufferTimer; function isTouchpad(deltaY) { if (!deltaY) return; deltaY = Math.abs(deltaY) deltaBuffer.push(deltaY); deltaBuffer.shift(); clearTimeout(deltaBufferTimer); var allEquals = (deltaBuffer[0] == deltaBuffer[1] && deltaBuffer[1] == deltaBuffer[2]); var allDivisable = (isDivisible(deltaBuffer[0], 120) && isDivisible(deltaBuffer[1], 120) && isDivisible(deltaBuffer[2], 120)); return !(allEquals || allDivisable); } function isDivisible(n, divisor) { return (Math.floor(n / divisor) == n / divisor); } var requestFrame = (function () { return window.requestAnimationFrame || window.webkitRequestAnimationFrame || function (callback, element, delay) { window.setTimeout(callback, delay || (1000/60)); }; })(); /*********************************************** * PULSE ***********************************************/ /** * Viscous fluid with a pulse for part and decay for the rest. * - Applies a fixed force over an interval (a damped acceleration), and * - Lets the exponential bleed away the velocity over a longer interval * - Michael Herf, http://stereopsis.com/stopping/ */ function pulse_(x) { var val, start, expx; // test x = x * options.pulseScale; if (x < 1) { // acceleartion val = x - (1 - Math.exp(-x)); } else { // tail // the previous animation ended here: start = Math.exp(-1); // simple viscous drag x -= 1; expx = 1 - Math.exp(-x); val = start + (expx * (1 - start)); } return val * options.pulseNormalize; } function pulse(x) { if (x >= 1) return 1; if (x <= 0) return 0; if (options.pulseNormalize == 1) { options.pulseNormalize /= pulse_(1); } return pulse_(x); } var isChrome = /chrome/i.test(window.navigator.userAgent); var isMouseWheelSupported = 'onmousewheel' in document; if (isMouseWheelSupported) { addEvent("mousedown", mousedown); addEvent("mousewheel", wheel); addEvent("load", init); }; })(); } if(browser() === 'ie') { /** * Created by IntelliJ IDEA. * * User: phil * Date: 15/11/12 * Time: 11:04 AM * */ (function($) { var self = this, container, running = false, currentY = 0, targetY = 0, oldY = 0, maxScrollTop = 0, minScrollTop, direction, onRenderCallback = null, fricton = 0.7, // higher value for slower deceleration vy = 0, stepAmt = 5, minMovement = 0.1, ts = 0.1; var updateScrollTarget = function(amt) { targetY += amt; vy += (targetY - oldY) * stepAmt; oldY = targetY; } var render = function() { if (vy < -(minMovement) || vy > minMovement) { currentY = (currentY + vy); if (currentY > maxScrollTop) { currentY = vy = 0; } else if (currentY < minScrollTop) { vy = 0; currentY = minScrollTop; } container.scrollTop(-currentY); vy *= fricton; if (onRenderCallback) { onRenderCallback(); } } } var animateLoop = function() { if (!running) return; requestAnimFrame(animateLoop); render(); //log("45","animateLoop","animateLoop", "",stop); } var onWheel = function(e) { e.preventDefault(); var evt = e.originalEvent; var delta = evt.detail ? evt.detail * -1 : evt.wheelDelta / 40; var dir = delta < 0 ? -1 : 1; if (dir != direction) { vy = 0; direction = dir; } //reset currentY in case non-wheel scroll has occurred (scrollbar drag, etc.) currentY = -container.scrollTop(); updateScrollTarget(delta); } /* * http://paulirish.com/2011/requestanimationframe-for-smart-animating/ */ window.requestAnimFrame = (function() { return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) { window.setTimeout(callback, 1000 / 60); }; })(); /* * http://jsbin.com/iqafek/2/edit */ var normalizeWheelDelta = function() { // Keep a distribution of observed values, and scale by the // 33rd percentile. var distribution = [], done = null, scale = 30; return function(n) { // Zeroes don't count. if (n == 0) return n; // After 500 samples, we stop sampling and keep current factor. if (done != null) return n * done; var abs = Math.abs(n); // Insert value (sorted in ascending order). outer: do { // Just used for break goto for (var i = 0; i < distribution.length; ++i) { if (abs <= distribution[i]) { distribution.splice(i, 0, abs); break outer; } } distribution.push(abs); } while (false); // Factor is scale divided by 33rd percentile. var factor = scale / distribution[Math.floor(distribution.length / 3)]; if (distribution.length == 500) done = factor; return n * factor; }; }(); $.fn.smoothWheel = function() { // var args = [].splice.call(arguments, 0); var options = jQuery.extend({}, arguments[0]); return this.each(function(index, elm) { if (!('ontouchstart' in window)) { container = $(this); container.bind("mousewheel", onWheel); container.bind("DOMMouseScroll", onWheel); //set target/old/current Y to match current scroll position to prevent jump to top of container targetY = oldY = container.scrollTop(); currentY = -targetY; minScrollTop = container.get(0).clientHeight - container.get(0).scrollHeight; if (options.onRender) { onRenderCallback = options.onRender; } if (options.remove) { log("122", "smoothWheel", "remove", ""); running = false; container.unbind("mousewheel", onWheel); container.unbind("DOMMouseScroll", onWheel); } else if (!running) { running = true; animateLoop(); } } }); }; })(jQuery); (function($, window) { $(window).load(function(){ $(window).smoothWheel() }); })(jQuery, window); }