Skip to content

Commit

Permalink
updated to version 2.0.0 using vanilla-js only
Browse files Browse the repository at this point in the history
  • Loading branch information
yairEO committed Jul 1, 2018
1 parent 83fd08e commit 4273235
Show file tree
Hide file tree
Showing 9 changed files with 282 additions and 276 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,4 @@ Icon
Network Trash Folder
Temporary Items
.apdisk
/jQuery.fakeScroll.js
Expand Down
34 changes: 17 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,40 @@ fakeScroll

### [DEMO PAGE](http://yaireo.github.io/fakescroll)

Uber lightweight & robust custom scrollbar replacement jQuery plugin.
The internet deserves a performant custom scrollbar script that is flexible, easy to use and only weights ~5.4k.
Very lightweight & robust custom-looking scrollbar script.


## Example markup for typical use-case
## Example markup:

<div class="fakeScroll">
<div class="foo">
...
...
...
</div>

## The above will become this (once plugin is applied):
## Initializing:

<div class="fakeScroll">
<div class="scrollWrap">
<div class="scrollContent">
document.querySelector('.foo').fakeScroll();

## The above will transform into this:

<div class="foo">
<div class="fakeScroll__wrap">
<div class="fakeScroll__content">
...
...
...
</div>
</div>
<div class="fakeScrollBar"></div>
<div class="fakeScroll__bar"></div>
</div>

## Initializing

$('.fakeScroll').fakeScroll();

## Settings

Name | Type | Default | Info
------------------- | ---------- | ----------- | --------------------------------------------------------------------------
theme | String | undefined | Class name which is added to the ".fakeScrollBar" element
offset | String | 0 0 | scroll offset, from start and end
sensitivity | Number | 1 | scroll sensitivity multiplier
minBarSizer | Number | 50 | Minimum size for the fake scroll bar, in pixels
Name | Type | Default | Info
------------------- | ---------- | ----------- | --------------------------------------------------------------------------
classname | String | "" | Class name which is added to the ".fakeScrollBar" element
offset | String | 0 0 0 0 | scroll offset
track | Boolean/String | false | enable track events. use "smooth" for smooth "jumping"
19 changes: 0 additions & 19 deletions bower.json

This file was deleted.

50 changes: 0 additions & 50 deletions fakeScroll-slideout.css

This file was deleted.

52 changes: 35 additions & 17 deletions fakeScroll.css
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
.scrollWrap{
.fakeScroll__wrap{
overflow : hidden;
height : 100%;
position : relative;
z-index : 1;
}
.scrollContent{

.fakeScroll__content{
height : 100%;
width : 100%;
padding : 0 32px 0 0;
Expand All @@ -15,25 +16,42 @@
box-sizing : border-box;
}

.fakeScrollBar{
position : absolute;
background : rgba(255,255,255,.5);
width : 9px;
border-radius : 4px;
right : -15px;
top : 0;
z-index : 0;
cursor : -moz-grab;
cursor : -webkit-grab;
.fakeScroll__track{
position : absolute;
right : -15px;
top : 0;
bottom : 0;
width : 9px;
cursor : default;
}

.fakeScroll:hover .fakeScrollBar.fakescroll-grabbed{
cursor : -moz-grabbing;
cursor : -webkit-grabbing;
background : #FFF;
.fakeScroll__bar{
position : relative;
background : rgba(255,255,255, .4);
width : 100%;
border-radius : 4px;
right : 0;
top : 0;
z-index : 0;
transition : background 0.1s;
cursor : -moz-grab;
cursor : -webkit-grab;
}

body.fakescroll-grabbed{
.fakeScroll__bar:hover{
background : rgba(255,255,255, .55);
}

.fakeScroll__bar.fakeScroll--grabbed{
cursor : -moz-grabbing;
cursor : -webkit-grabbing;
background : white;
}

body.fakeScroll--grabbed{
cursor : -moz-grabbing;
cursor : -webkit-grabbing;
-moz-user-select : none;
-webkit-user-select : none;
user-select : none;
}
174 changes: 174 additions & 0 deletions fakescroll.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
;(function(){
raf = window.requestAnimationFrame || function(cb) { return window.setTimeout(cb, 1000 / 60) };

function FakeScroll(targetElm, settings){
if( !targetElm ) return;

this.settings = Object.assign({}, this.defaults, settings || {});
this.settings.offset = this.settings.offset.split(' '); // convert offset String to Array
this.callback = settings.callback ? settings.callback : null;

this.state = {};
this.listeners = {};

this.DOM = this.build(targetElm);
this.events.binding.call(this, this.DOM);

// run "moveBar" once
setTimeout(this.moveBar.bind(this));

}

FakeScroll.prototype = {
defaults : {
classname : "",
track : false,
offset : "0 0 0 0"
},

/**
* Build the DOM needed
*/
build( targetElm ){
var DOM = {};
scopeHTML = `<div class="fakeScroll__wrap">
<div class="fakeScroll__content"></div>
</div>
<div class='fakeScroll__track'>
<div class="fakeScroll__bar ${this.settings.classname}"></div>
</div>`,
fragment = document.createDocumentFragment();

// move all the children of the target element into a fragment
while( targetElm.childNodes.length ){
fragment.appendChild(targetElm.childNodes[0]);
}

targetElm.insertAdjacentHTML('afterbegin', scopeHTML);

DOM.scrollWrap = targetElm.firstElementChild;
DOM.scrollContent = DOM.scrollWrap.firstElementChild;
DOM.scrollContent.appendChild(fragment);

DOM.track = DOM.scrollWrap.nextElementSibling;
DOM.bar = DOM.track.firstElementChild;

return DOM;
},

events : {
on(elm, eName, cbName){
// to be able tp unbind the events, callback refferece must be saved somewhere
eName.split(' ').forEach(e => {
if( !(cbName in this.events.callbacks) ) console.warn(cbName, " doesn't exist in Callbacks: ", this.events.callbacks);

this.listeners[e] = this.events.callbacks[cbName].bind(this);
elm.addEventListener(e, this.listeners[e])
});

return this.events;
},

off(elm, eName, cbName){
eName.split(' ').forEach(e => elm.removeEventListener(e, this.listeners[e]))
return this.events;
},

binding(DOM){
this.events.on.call(this, DOM.scrollContent, 'scroll mouseenter', 'onScrollResize')
.on.call(this, window, 'resize', 'onScrollResize')
.on.call(this, DOM.bar, 'mousedown', 'onBarMouseDown')

if( this.settings.track )
this.events.on.call(this, DOM.track, 'click', 'onTrackClick')
},

/**
* events only binded when Bar element gets a "mousedown" event
* @param {[type]} onOff [description]
* @return {[type]} [description]
*/
drag(onOff){
this.events[onOff].call(this, document, 'mousemove', 'onDrag')
[onOff].call(this, document, 'mouseup', 'onStopDrag')
},

callbacks : {
onScrollResize(e){
this.moveBar.call(this)
},

onDrag(e){
var delta = e.pageY - this.state.lastPageY;
this.state.lastPageY = e.pageY;

raf(() => {
this.DOM.scrollContent.scrollTop += delta / this.scrollRatio;
});
},

onStopDrag(e){
[this.DOM.bar, document.body].map(el => el.classList.remove('fakeScroll--grabbed'))
this.events.drag.call(this, 'off');
setTimeout(()=>{ this.state.drag = false })
},

onBarMouseDown(e){
this.state.drag = true;
this.state.lastPageY = e.pageY;
[this.DOM.bar, document.body].map(el => el.classList.add('fakeScroll--grabbed'))
this.events.drag.call(this, 'on');
},

onTrackClick(e){
if( this.state.drag ) return;

var bounds = e.target.getBoundingClientRect(),
styles = window.getComputedStyle(e.target, null),
boundsPad = [parseInt(styles.paddingTop, 10), 0, parseInt(styles.paddingBottom, 10), 0],
perc = (e.clientY - bounds.top) / (bounds.height - boundsPad[0] - boundsPad[2]),
scrollHeight = this.DOM.scrollContent.scrollHeight,
ownHeight = this.DOM.scrollWrap.clientHeight,
newScrollTop = perc * (scrollHeight - ownHeight);

if( this.settings.track == 'smooth' ){
this.DOM.scrollContent.style.scrollBehavior = 'smooth';
setTimeout(()=>{ this.DOM.scrollContent.style.scrollBehavior = 'unset' }, 500)
}

this.DOM.scrollContent.scrollTop = newScrollTop;
}
}
},

destroy(){
this.events.off.call(this, window, 'resize', 'onScrollResize');
},

moveBar(){
// if( !this.DOM.scrollContent ) return false;

var _scrollContent = this.DOM.scrollContent,
scrollHeight = _scrollContent.scrollHeight,
ownHeight = this.DOM.scrollWrap.clientHeight;

this.scrollRatio = ownHeight / scrollHeight;

// update fake scrollbar location on the Y axis using requestAnimationFrame
raf(()=> {
var height = (ownHeight / scrollHeight) * 100,
top = (_scrollContent.scrollTop / scrollHeight ) * 100;

this.DOM.bar.style.cssText = `height : calc(${height}% - ${this.settings.offset[0]}px);
top : calc(${top}% + ${this.settings.offset[0]}px);
display : ${scrollHeight <= ownHeight ? 'none' : ''}`;
});
}
}

Element.prototype.fakeScroll = function( settings ){
this._fakeScroll = this._fakeScroll || new FakeScroll(this, settings || {});

return this._fakeScroll;
}
})();
Loading

0 comments on commit 4273235

Please sign in to comment.