SarambaBamba / TopAndDownButtonsEverywhere

// ==UserScript==
// @name TopAndDownButtonsEverywhere
// @description Top and Down buttons everywhere (no Jquery) 
// @version 1.7
// @author Max Max
// @license MIT
// @include *
// @icon http://pics.smotri.com/cskins/blue/smiles/bt.gif
// @run-at document-end
// @grant none
// @noframes
// ==/UserScript==

// global variables
var position,
    // timer
    t1, t2,
    // speed by
    speed_by_click = 500, // edit this value
    speed_by_over = 70, // edit this value
    // z-index
    zIindex = 16777271;
    // figure out if this is moz || IE because they use documentElement
    var elem;
    if(navigator.userAgent.indexOf('Firefox') != -1 || navigator.userAgent.indexOf('MSIE') != -1)
      elem = document.documentElement;
    else
      elem = document.body;


//animation gradually increases in speed, peaks, and then gradually slows down. (by Someone Else)
Math.easeInOutQuad = function(a, b, c, d) {
    a /= d / 2;
    if (a < 1)
      return c / 2 * a * a + b;
    a--;
    return -c / 2 * (a * (a - 2) - 1) + b;
};

//sinusoidal easing in - accelerating from zero velocity (by Someone Else)
Math.easeInSine = function (t, b, c, d) {
	return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
};

// run it
var t0 = performance.now();
create_btn_element();
var t1 = performance.now();
console.log("Call took " + (t1 - t0) + " milliseconds.");
//}

function addStyle(css) {
    var head = document.head || document.getElementsByTagName('head')[0];
    if (head) {
        var style = document.createElement("style");
        style.type = "text/css";
        style.appendChild(document.createTextNode(css));
        head.appendChild(style);
    }
}

//scrollTo because this is cross browser supported.
function move_up() {
    position = document.documentElement.scrollTop || document.body.scrollTop;
    window.scrollTo(0, position - 12); // edit this value (14)
    t1 = setTimeout(move_up, speed_by_over);
}

function move_dn() {
    position = document.documentElement.scrollTop || document.body.scrollTop;
    window.scrollTo(0, position + 12); // edit this value (14)
    t2 = setTimeout(move_dn, speed_by_over);
}

function getDocumentHeight() {
  if(document.body.scrollHeight > document.body.offsetHeight)
    return document.body.scrollHeight;
  return document.body.offsetHeight;
}

function get_scroll() {
    var body = document.body;
    var root = document.documentElement;
    if (/CSS/.test(document.compatMode))
      return (root.clientHeight < root.scrollHeight);
    return (body.clientHeight < body.scrollHeight);
}

// calk
function scrollTo(element, to, duration) {
    var start = element.scrollTop, change = to - start, currentTime = 0, increment = 20;
    var newDuration;
        if(typeof(duration) === 'undefined')
          newDuration = 500;
        else
          newDuration = duration;

    var animateScroll = function() {
        currentTime += increment;
        var val = Math.easeInOutQuad(currentTime, start, change, newDuration);
        element.scrollTop = val;
        if (currentTime < newDuration) {
            setTimeout(animateScroll, increment);
        }
    };
    animateScroll();
}

// add css
function shareCSS() {
    var s = '', img_up, img_rest, img_dn;

    // img vs button
    img_up = 'data:img/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAUCAYAAACAl21KAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAB+SURBVDhPY1i1atV/amAGahgCMoNhaIGlS5cKAp19BoRBbLJcj2QILDJINwzoAmMgfoclIkBixkS5DI8hMJcRNgxoSBoOl6CnNZBhaVhdBjWE1MSJahjQkA4KEmYH2GUrV66cSYEhYB+AzKBtFiHkQqKiH6Ro1CDCQTWgYQQAs81DU0G/83sAAAAASUVORK5CYII=';
    img_rest = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAUCAYAAACAl21KAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAB3RJTUUH4QEUFBEp+ZM7LwAAABRJREFUOMtjYBgFo2AUjIJRMFQAAAW0AAF4TY98AAAAAElFTkSuQmCC';
    img_dn = 'data:img/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAUCAYAAACAl21KAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACPSURBVDhPY2DAAlatWvUfH8amB6vYqEGEg2pgw4iQ7cTKM6xcuXImsYpxqQOZAQ4woIIOCgzrQAl1oEFpZBiWhitFgwx7R4SBIDXYDYGZDFRgTMAwkCHGhBMRJMxwGUa8ITCbli5dKgg08AySN8+AxIhyCboiJMPIN4Qsm6miiYioxltawvSDYogohYTUAQC80UNTOht/YwAAAABJRU5ErkJggg==';

    // button id
    //whitout pointer-events: visible it may not work on some sites that use interactive elements or ads on the right side of the screen (tumblr, hoaxme, etc)
    s += '#play_btn_up { position:fixed; right:0; bottom:55%; z-index:' + zIindex + '; height:36px; width:36px; cursor:pointer; background:url(' + img_up + ') no-repeat scroll 50% 50% rgba(0, 0, 0, 0.7); border-radius:5px 0 0 5px; margin-top:-24px; pointer-events: visible;}';
    s += '#rest_btn { position:fixed; right:0; top:53%;z-index:' + zIindex + '; height:30px; width:36px; cursor:pointer; background:url(' + img_rest + ') no-repeat scroll 50% 50% rgba(0, 0, 0, 0.7); border-radius:5px 0 0 5px; margin-top:-24px; pointer-events: visible;}';
    s += '#play_btn_dn { position:fixed; right:0; top:62%; z-index:' + zIindex + '; height:36px; width:36px; cursor:pointer; background:url(' + img_dn + ') no-repeat scroll 50% 50% rgba(0, 0, 0, 0.7); border-radius:5px 0 0 5px; margin-top:-24px; pointer-events: visible;}';

    // button class
    s += '.play_btn { -webkit-transition-duration:0.5s linear; -o-transition-duration:0.5s linear; -moz-transition-duration:0.5s linear; transition-duration:0.5s linear; opacity:0.65; }';
    s += '.play_btn:hover { opacity:1; }';

    // append
    addStyle('' + s);
}

// main
function create_btn_element() {
    // get scroll
    var up, dn, scrolled, h = get_scroll();

    // exit
    if (!h)
        return;

    // add css
    shareCSS();

    if (elem) {
        // create DOM element
        up = document.createElement('span');
        up.setAttribute('id', 'play_btn_up');
        up.className = "play_btn";
        document.body.appendChild(up);
        up.addEventListener('mouseover', move_up, false);
        up.addEventListener('mouseout', function() {
          clearTimeout(t1);
        }, false);
        up.addEventListener('click', function() {
          //top
          scrollTo(elem, 0, speed_by_click);
        }, false);

        rest = document.createElement('span');
        rest.setAttribute('id', 'rest_btn');
        rest.className = "play_btn";
        document.body.appendChild(rest);

        dn = document.createElement('span');
        dn.setAttribute('id', 'play_btn_dn');
        dn.className = "play_btn";
        document.body.appendChild(dn);
        dn.addEventListener('mouseover', move_dn, false);
        dn.addEventListener('mouseout', function() {
          clearTimeout(t2);
        }, false);
        dn.addEventListener('click', function() {
          //bottom
          scrollTo(elem, getDocumentHeight(), speed_by_click);
        }, false);
    }
}