Skip to content

Commit

Permalink
Fixed #251, New ScrollPanel component
Browse files Browse the repository at this point in the history
  • Loading branch information
Çağatay Çivici committed Dec 12, 2017
1 parent eff3b79 commit b9ec8f5
Show file tree
Hide file tree
Showing 5 changed files with 479 additions and 1 deletion.
3 changes: 3 additions & 0 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { MessagesDemo } from './showcase/messages/MessagesDemo';
import { MultiSelectDemo } from './showcase/multiselect/MultiSelectDemo';
import { OverlayPanelDemo } from './showcase/overlaypanel/OverlayPanelDemo';
import { PanelDemo } from './showcase/panel/PanelDemo';
import { ScrollPanelDemo } from './showcase/scrollpanel/ScrollPanelDemo';
import { ProgressBarDemo } from './showcase/progressbar/ProgressBarDemo';
import { RadioButtonDemo } from './showcase/radiobutton/RadioButtonDemo';
import { TabViewDemo } from './showcase/tabview/TabViewDemo';
Expand Down Expand Up @@ -209,6 +210,7 @@ class AppMenu extends Component {
<Link to="/fieldset">&#9679; Fieldset</Link>
<Link to="/grid">&#9679; Grid</Link>
<Link to="/panel">&#9679; Panel</Link>
<Link to="/scrollpanel">&#9679; ScrollPanel</Link>
<Link to="/tabview">&#9679; TabView</Link>
<Link to="/toolbar">&#9679; Toolbar</Link>
</div>
Expand Down Expand Up @@ -520,6 +522,7 @@ class App extends Component {
<Route path="/sidebar" component={SidebarDemo} />
<Route path="/gmap" component={GMapDemo} />
<Route path="/progressspinner" component={ProgressSpinnerDemo} />
<Route path="/scrollpanel" component={ScrollPanelDemo} />

<div className="content-section layout-footer clearfix">
<span>Released under the MIT License, Copyright © 2017 PrimeTek</span>
Expand Down
46 changes: 46 additions & 0 deletions src/components/scrollpanel/ScrollPanel.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
.ui-scrollpanel-wrapper {
overflow: hidden;
width: 100%;
height: 100%;
position: relative;
z-index: 1;
float: left;
}

.ui-scrollpanel-content {
height: 100%;
width: calc(100% + 18px);
padding: 0 0 0 0;
position: relative;
overflow: auto;
box-sizing: border-box;
}

.ui-scrollpanel-bar {
position: relative;
background: #c1c1c1;
width: 9px;
border-radius: 3px;
top: 0;
z-index: 2;
cursor: pointer;
opacity: 0;
transition: opacity 0.25s linear;
}

.ui-scrollpanel-hidden {
display: none;
}

.ui-scrollpanel:hover .ui-scrollpanel-bar,
.ui-scrollpanel:active .ui-scrollpanel-bar {
opacity: 1;
}

.ui-scrollpanel-grabbed {
-o-user-select: none;
-ms-user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
user-select: none;
}
104 changes: 104 additions & 0 deletions src/components/scrollpanel/ScrollPanel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import DomHandler from '../utils/DomHandler';
import classNames from 'classnames';

export class ScrollPanel extends Component {

static defaultProps = {
style: null,
className: null
}

static propTypes = {
style: PropTypes.object,
className: PropTypes.string
};

constructor(props) {
super(props);

this.moveBar = this.moveBar.bind(this);
this.onBarMouseDown = this.onBarMouseDown.bind(this);
this.onDocumentMouseMove = this.onDocumentMouseMove.bind(this);
this.onDocumentMouseUp = this.onDocumentMouseUp.bind(this);
}

componentDidMount() {
this.moveBar();
this.moveBar = this.moveBar.bind(this);

window.addEventListener('resize', this.moveBar);
this.initialized = true;
}

componentWillUnmount() {
if(this.initialized) {
window.removeEventListener('resize', this.moveBar);
}
}

moveBar() {
let totalHeight = this.content.scrollHeight;
let ownHeight = this.content.clientHeight;
let right = (this.container.clientWidth - this.bar.clientWidth) * -1;
this.scrollRatio = ownHeight / totalHeight;

this.requestAnimationFrame(() => {
if (this.scrollRatio >= 1) {
DomHandler.addClass(this.bar, 'ui-scrollpanel-hidden');
}
else {
DomHandler.removeClass(this.bar, 'ui-scrollpanel-hidden');
this.bar.style.cssText = 'height:' + Math.max(this.scrollRatio * 100, 10) + '%; top:' + (this.content.scrollTop / totalHeight) * 100 + '%;right:' + right + 'px;';
}
});
}

onBarMouseDown(e) {
this.lastPageY = e.pageY;
DomHandler.addClass(this.bar, 'ui-scrollpanel-grabbed');
DomHandler.addClass(document.body, 'ui-scrollpanel-grabbed');

document.addEventListener('mousemove', this.onDocumentMouseMove);
document.addEventListener('mouseup', this.onDocumentMouseUp);
e.preventDefault();
}

onDocumentMouseMove(e) {
let delta = e.pageY - this.lastPageY;
this.lastPageY = e.pageY;

this.requestAnimationFrame(() => {
this.content.scrollTop += delta / this.scrollRatio;
});
}

onDocumentMouseUp(e) {
DomHandler.removeClass(this.bar, 'ui-scrollpanel-grabbed');
DomHandler.removeClass(document.body, 'ui-scrollpanel-grabbed');

document.removeEventListener('mousemove', this.onDocumentMouseMove);
document.removeEventListener('mouseup', this.onDocumentMouseUp);
}

requestAnimationFrame(f) {
let frame = window.requestAnimationFrame ||  this.timeoutFrame;
frame(f);
}

render() {
let className = classNames('ui-scrollpanel ui-widget ui-widget-content ui-corner-all', this.props.className);

return (
<div ref={(el) => { this.container = el; }} id={this.props.id} className={className} style={this.props.style}>
<div className="ui-scrollpanel-wrapper">
<div ref={(el) => { this.content = el; }} className="ui-scrollpanel-content" onScroll={this.moveBar} onMouseEnter={this.moveBar}>
{this.props.children}
</div>
</div>
<div ref={(el) => { this.bar = el; }} className="ui-scrollpanel-bar" onMouseDown={this.onBarMouseDown}></div>
</div>
);
}
}
33 changes: 32 additions & 1 deletion src/sass/App.scss
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ body {
border-radius: 2px;
color: #fff;
font-weight: 700;
margin-bottom: 1em;
margin: .5em 0;
display: inline-block;
transition: background-color .3s;

Expand Down Expand Up @@ -895,6 +895,37 @@ a{
border: 1px solid #fafafa;
}

.scrollpanel-demo {
.custombar1 .ui-scrollpanel-wrapper {
border-right: 9px solid #f4f4f4;
}

.custombar1 .ui-scrollpanel-bar {
background-color: #1976d2;
opacity: 1;
transition: background-color .3s;
}

.custombar1 .ui-scrollpanel-bar:hover {
background-color: #135ba1;
}

.custombar2 .ui-scrollpanel-wrapper {
border-right: 9px solid #000000;
}

.custombar2 .ui-scrollpanel-bar {
background-color: #68C77D;
border-radius: 0;
opacity: 1;
transition: background-color .3s;
}

.custombar2:hover .ui-scrollpanel-bar {
background-color: #46A55A;
}
}

/* Animation */
@-webkit-keyframes fadeInDown {
from {
Expand Down
Loading

0 comments on commit b9ec8f5

Please sign in to comment.