Вход Регистрация
Файл: usr/tpl/JMY_yellow/assest/js/SmoothScroll.js
Строк: 431
<?php
// 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;
 
    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)) {
 
        
// DOMChange (throttle): fix height
        
var pending = false;
        var 
refresh = function () {
            if (!
pending && html.scrollHeight != document.height) {
                
pending = true; // add a new pending action
                
setTimeout(function () {
                    
html.style.height = document.height + 'px';
                    
pending = false;
                }, 
500); // act rarely to stay fast
            
}
        };
        
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 
allDivisable = (isDivisible(deltaBuffer[0], 120) &&
                        
isDivisible(deltaBuffer[1], 120) &&
                        
isDivisible(deltaBuffer[2], 120));
    return !
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 
wheelEvent = null;
if (
"onwheel" in document.createElement("div"))
    
wheelEvent = "wheel";
else if (
"onmousewheel" in document.createElement("div"))
    
wheelEvent = "mousewheel";
 
if (
wheelEvent && isChrome) {
    
addEvent(wheelEvent, wheel);
    
addEvent("mousedown", mousedown);
    
addEvent("load", init);
}
 
})();
?>
Онлайн: 1
Реклама