Smoothscroll

Smooth scrolling everywhere using javascript

01.11.2016 itibariyledir. En son verisyonu görün.

Bu betiği kurabilmeniz için Tampermonkey, Greasemonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği yüklemek için Tampermonkey gibi bir uzantı yüklemeniz gerekir.

Bu betiği kurabilmeniz için Tampermonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Userscripts gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği indirebilmeniz için ayrıca Tampermonkey gibi bir eklenti kurmanız gerekmektedir.

Bu komut dosyasını yüklemek için bir kullanıcı komut dosyası yöneticisi uzantısı yüklemeniz gerekecek.

(Zaten bir kullanıcı komut dosyası yöneticim var, kurmama izin verin!)

Bu stili yüklemek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için Stylus gibi bir uzantı kurmanız gerekir.

Bu stili yükleyebilmek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı kurmanız gerekir.

Bu stili yükleyebilmek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

(Zateb bir user-style yöneticim var, yükleyeyim!)

// ==UserScript==
// @name Smoothscroll
// @include     http*
// @author       Creec Winceptor
// @description  Smooth scrolling everywhere using javascript
// @namespace https://greasyfork.org/users/3167
// @run-at document-load
// @grant    none
// @grant       GM_getValue
// @grant       GM_setValue
// @grant       GM_registerMenuCommand
// @version 2.2
// ==/UserScript==

if (window.top != window.self)  //don't run on frames or iframes
    return;

//DEFAULT SETTINGS HERE 
//DO NOT CHANGE ANYTHING HERE ANYMORE, USE SCRIPT COMMANDS -> CONFIGURE SMOOTHSCROLL


//Smoothness factor value (how strong the smoothing effect is)
//values: 1-(infinite)
var smoothness = 50;

//Scroll sensitivity
//values: anything? (default 1.00)
var sensitivity = 1;

//Acceleration sensitivity
//values: anything? (default 1.50)
var acceleration = 1;

//Refreshrate setting
//values: 30-144 (default = 60/72/120/144 = same as your monitor hz)
var refreshrate = 60;


//Alternative scrolling multiplier
//values: true/false (try to set this to true if scrolling is too slow/doesn't work)
var alternative_sensitivity_multiplier = false;


//CODE STARTS HERE

var DEBUG = false;

var WEBKIT = false;

console.log("Loading smoothscroll...");

var baserefreshrate = 60; //DO NOT CHANGE THIS EVER
if (smoothness>100)
{
	smoothness = 100;
}

if (refreshrate <= 30 || refreshrate>144)
{
	refreshrate = 144;
}

function InitSmoothscroll()
{
  
  LoadConfig();

  InitConfigmenu();

var startposition = false;
var targetposition = 0;
var position = 0;

//var scrollfocus = //ss$('body');
var scrollfocus = document.body;
var mousemoved = true;
  
function hasScrollBarVisible(element)
{
  //return (document.documentElement.scrollHeight !== document.documentElement.clientHeight);
 
  // Get the computed style of the body element
  var cStyle = element.currentStyle||window.getComputedStyle(element, "");
 
  // Check the overflow and overflowY properties for "auto" and "visible" values
  var scrollbar1 = cStyle.overflow == "scroll" || cStyle.overflowY == "scroll";

	var scrollbar2 = cStyle.overflow == "auto" || cStyle.overflowY == "auto";
	
	var scrollbar = scrollbar1 || scrollbar2;
 
  return scrollbar;
}


function hasscrollbars(scrollfocus)
{
	var hasvisiblescrollbars = hasScrollBarVisible(scrollfocus);
	return hasvisiblescrollbars;
	
	/*
	var parentelement = //ss$(scrollfocus).parent();
	if ( //ss$(parentelement))
	{
		if (//ss$(parentelement).is("textarea") || //ss$(scrollfocus).is("textarea") || //ss$(parentelement).is("article") || //ss$(parentelement).is("article"))
		{
			return true;
		}
		else
		{
			if (//ss$(parentelement).hasClass( "yt-scrollbar" ) || //ss$(scrollfocus).hasClass( "yt-scrollbar" ))
			{
				return true;
			}
			return hasvisiblescrollbars;
		}
	}
	else
	{
		return hasvisiblescrollbars;
	}
	return false;
	*/
}

var scroll_timeout = null;

function UpdatePosition(element)
{
	//gameLoop();
	var interpolation = 3;
  
	var animationduration = Math.round(1000/(refreshrate*interpolation));
  
  	var relativeratio = Math.round(( 1/(1+smoothness)/interpolation*refreshrate/baserefreshrate )*1000)/1000;
	
	var positiondelta = scrollpositiondelta(element);
	
	
                  
	var smoothdelta = Math.sqrt(positiondelta*positiondelta*relativeratio);
  	var rounddelta = Math.ceil(smoothdelta);
  	
	//var smoothdelta = positiondelta*relativeratio;
  
	if (positiondelta<0)
	{
		smoothdelta = smoothdelta*(-1);
      	rounddelta = rounddelta*(-1);
	}

	if (Math.abs( rounddelta ) < 1 )
	{	
	
      if (Math.abs( positiondelta ) > 1 )
      {
      	
      	scroll_timeout = setTimeout(function() {
			element.scrollTop = element.scrollTop + rounddelta;
			scrollpositiondelta(element, positiondelta - rounddelta);
			UpdatePosition(element);
		  }, Math.abs(animationduration/smoothdelta) );
      
      }
      else
      {
          scroll_timeout = setTimeout(function() {
              element.scrollTop = element.scrollTop + rounddelta;
              scrollpositiondelta(element, 0);
            }, animationduration);

      }
		


	}
	else
	{
		  scroll_timeout = setTimeout(function() {
			element.scrollTop = element.scrollTop + rounddelta;
			scrollpositiondelta(element, positiondelta - rounddelta);
			UpdatePosition(element);
		  }, animationduration);
	}
}


 function MouseScroll (e) {

   	var mul = 1;
	if (!WEBKIT || alternative_sensitivity_multiplier)
		mul = 40;
   	var x = e.deltaX*mul;
   	var y = e.deltaY*mul;
   
   	if (mousemoved)
    {
      scrollfocus = UpdateFocus(x,y);
      mousemoved = false;
    }
   
	 var positiondelta = 0;
	 var lastscrolltop = 0;

	 var rolled = y;
	 	
	 	if (!canscroll(scrollfocus, rolled))
		{
			if (scrollfocus != document.documentElement)	
			{
				scrollfocus = UpdateFocus(x,y);
              return false;
			}
			else
			{
              	
              	//console.log("true");
				return false;
			}
		}
	 	else
		{
			e.preventDefault();
		}
   	 positiondelta = scrollpositiondelta(scrollfocus);
   
	 var direction = rolled/Math.abs(rolled);
	 
	 var positiondeltadelta = Math.round(rolled*sensitivity + Math.sqrt(Math.abs(positiondelta-rolled*sensitivity))*acceleration*rolled*0.09/sensitivity);
	 
	 positiondelta = positiondelta*1 + positiondeltadelta*1;
	 
  	 scrollpositiondelta(scrollfocus, positiondelta)

	 clearTimeout(scroll_timeout);
	 
	 UpdatePosition(scrollfocus);
	 
	 return true;
 }

 function canscroll(element, dir)
{
  	if (dir>0)
    {
      dir = 1;
    }
  	if (dir<0)
    {
      dir = -1;
    }
  	var checkradius = 3; //pixels to try scrolling
  
  	var canscroll0 = false;

	var scrollable = element;

	var lastscrolltop = scrollable.scrollTop;

	scrollable.scrollTop = lastscrolltop+dir*checkradius;

	if (scrollable.scrollTop!=lastscrolltop)
	{
		canscroll0 = true;
	}

	scrollable.scrollTop = lastscrolltop;

	return canscroll0;
}
  
  
function scrollpositiondelta(element, newdelta)
{
  	//var target = //ss$(element);
	var target = element;
  	var delta = 0;
  	if (newdelta!=undefined)
    {
      //console.log(dir);
      var dir = 0;
      if (newdelta>0)
      {
        dir = 1;
      }
      if (newdelta<0)
      {
        dir = -1;
      }
	  target.setAttribute("positiondelta", newdelta );

      delta = newdelta;
    }
	else
    {
		var olddelta = target.getAttribute("positiondelta");
      if (olddelta!=undefined)
      {
      	delta = olddelta;
      }
    }
  	return delta*1;
}

function UpdateFocus(x,y) {
	if (scrollfocus)
      {
        //scrollpositiondelta(scrollfocus, 0);
        //ss$(scrollfocus).stop();
      }
	var dir = y;
	 	var nodelist = document.querySelectorAll( ":hover" );
	 	if (WEBKIT)
        {
        	//scrollfocus = //ss$('body');
			scrollfocus = document.body;
        }
  		else
        {
            //scrollfocus = //ss$('html');
			scrollfocus = document.documentElement;
        }
  		
	 	for (var i = nodelist.length-1; i >= 0 ; i--) { 
			  var newfocus = nodelist[i];
				if (canscroll(newfocus, dir) && hasscrollbars(newfocus))
				{
					scrollfocus = newfocus;
					return newfocus;
				}
 		}

	 return scrollfocus;
 }
	
  /*ss$('html').bind({
    
	mousemove: function(e) {
      mousemoved = true;
    },
    
    mousedown: function(e) {
      if (DEBUG)
      {
        console.log(scrollfocus);
      }
      if (scrollfocus)
      {
        scrollpositiondelta(scrollfocus, 0);
        ////ss$(scrollfocus).stop();
      }
      scrollfocus = UpdateFocus(0,0);
      //console.log("click");
    }
  });
	*/
	
  
document.documentElement.addEventListener("wheel", function(e){
    MouseScroll(e);
	mousemoved = true;
  //console.log("scrolling");
});
  

  //WEBKIT = 'webkitRequestAnimationFrame' in window;
  WEBKIT = document.compatMode == 'CSS1Compat' || document.compatMode == "BackCompat";
  
  //console.log("window: " + window);
  console.log("Smoothscroll loaded! Webkit: " + WEBKIT);
  
  $smoothscroll$ = true;
}

function LoadConfig()
{
  smoothness = GM_getValue( 'smoothness', smoothness );
  sensitivity = GM_getValue( 'sensitivity', sensitivity );
  acceleration = GM_getValue( 'acceleration', acceleration );
  refreshrate = GM_getValue( 'refreshrate', refreshrate );
  //alternative_sesitivity_multiplier = GM_getValue( 'alternative_sesitivity_multiplier', alternative_sesitivity_multiplier );
  //console.log("Config for smoothscroll loaded!")
}

function SaveConfig()
{
  GM_setValue( 'smoothness', document.getElementById('ss-smoothness').value)
  GM_setValue( 'sensitivity', document.getElementById('ss-sensitivity').value)
  GM_setValue( 'acceleration', document.getElementById('ss-acceleration').value)
  GM_setValue( 'refreshrate', document.getElementById('ss-refreshrate').value)
  //console.log(document.getElementById('ss-alternative_sesitivity_multiplier').checked)
  //console.log("Config for smoothscroll saved!")
}

function CloseConfig()
{
 	var configbar = document.getElementById("ss-configbar");
  configbar.style.display = 'none';  
}

function InitConfigmenu()
{
  	//console.log("Initiating smoothscroll config...");
    var configbar = document.createElement('div');
    configbar.setAttribute("id","ss-configbar");
 	
  	configbar.innerHTML = '<div style="display:block; width: 100%; height: auto; border: 0px solid #aaaaaa; background-color: grey;">Config page for smoothscroll (refresh page for changes to apply!) Made by: Creec Winceptor</div><div id="ss-config" style="margin:3px; display:block; width: auto; height: auto; border: 0px solid #554433;"><table style="width:auto;"><tr><td>Smoothness</td><td><input type="number" id="ss-smoothness" min="0" max="100" value="' + smoothness + '"></td><td> Smoothness factor value (how strong the smoothing effect is)</td></tr><tr><td>Sensitivity</td><td><input type="number" id="ss-sensitivity" min="0" max="100" value="' + sensitivity + '"></td><td> Scroll sensitivity (duh)</td></tr><tr><td>Acceleration</td><td><input type="number" id="ss-acceleration" min="0" max="100" value="' + acceleration + '"></td><td> Acceleration of continuous scroll action (saves your finger)</td></tr><tr><td>Refreshrate</td><td><input type="number" id="ss-refreshrate" min="1" max="100" value="' + refreshrate + '"></td><td>Refreshrate of scrollanimation (60Hz default)</td></tr></table></div><div style="width: 100%; height: auto; text-align: center; background-color: grey;"><input id="ss-save" type="button" value="Save config" style="width: 44%; height: auto; border: 0px solid #aaaaaa; margin: 3px"/><input id="ss-close" type="button" value="Close config" style="width: 44%; height: auto; border: 0px solid #aaaaaa; margin: 3px"/><div>';
  	
  	
    var configparent = document.getElementsByTagName("body")[0];
  	configbar.style.width = '100%';  
  	configbar.style.display = 'none';  
  	configbar.style.position = 'absolute';
	configbar.style.zIndex = '9999';
  	configbar.style.backgroundColor = 'white';
  
  	configparent.insertBefore(configbar, configparent.childNodes[0]);
  	
  	document.getElementById("ss-close").onclick = function() {CloseConfig()};
  
  	document.getElementById("ss-save").onclick = function() {SaveConfig()};
}

function ConfigSmoothscroll()
{
  if (typeof $smoothscroll$ == 'undefined'){
    alert("Smoothscroll is not running properly on this page!");
    return;
  }

  var configbar = document.getElementById("ss-configbar");
  configbar.style.display = 'block';  
  //ss$("html, body").animate({ scrollTop: 0 }, "slow");
  //console.log("opening config...");
}

if (typeof $smoothscroll$ == 'undefined'){
	//console.log("Initiating smoothscroll...");
	InitSmoothscroll();	
	GM_registerMenuCommand("Configurate smoothscroll", ConfigSmoothscroll);
}
else
{
  console.log("Smoothscroll already loaded!");
}