Skip to content

Commit

Permalink
fixed scrollbar interaction
Browse files Browse the repository at this point in the history
  • Loading branch information
crisward committed Dec 28, 2016
1 parent 06753e2 commit 8709399
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 10 deletions.
15 changes: 13 additions & 2 deletions lib/grid2.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

riot.tag2('grid2', '<div class="gridwrap" riot-style="height:{opts.height}px"> <div class="gridbody" ref="mainbody" riot-style="left:{fixedLeft.width}px;top:{rowHeight}px;bottom:0px"> <div class="fixedLeft" riot-style="transform:translate3d({fixedLeft.left}px,{fixedLeft.top}px,0px);backface-visibility: hidden;width:{fixedLeft.width}px;bottom:1px;z-index:2;"> <gridcelltag class="cell {cell.classes()}" tag="{cell.tag}" data="{parent.opts.data}" no-reorder val="{cell.text}" cell="{cell}" each="{cell in visCells.main}" onclick="{parent.handleClick}" riot-style="position: absolute;left:{cell.left}px;top:{cell.top}px;width:{cell.width}px;height:{parent.rowHeight}px;">{cell.text}</gridcelltag> </div> </div> <div class="gridbody" ref="header" riot-style="height:{rowHeight}px;margin-right:15px"> <div class="header" riot-style="top:0px;left:0px;width:{scrollWidth}px;height:{rowHeight}px"> <div class="headercell {classes}" each="{headers.main}" no-reorder riot-style="transform:translate3d({left}px,0px,0px); backface-visibility: hidden;width:{width}px;height:{rowHeight}px;">{text}</div> </div> </div> <div class="gridbody" ref="fixedleft" riot-style="width:{fixedLeft.width}px;height:{opts.height-2}px"> <div class="fixedLeft" riot-style="transform:translate3d(0px,{fixedLeft.top}px,0px);backface-visibility: hidden;width:{fixedLeft.width}px;bottom:1px;z-index:2;"> <div class="header" riot-style="top:{0 - fixedLeft.top}px;left:0px;width:{fixedLeft.width}px;height:{rowHeight}px"> <div class="headercell {classes}" each="{headers.fixed}" no-reorder riot-style="top:0px;left:{left}px;width:{width}px;height:{rowHeight}px;">{text}</div> </div> <gridcelltag class="cell {cell.classes()}" tag="{cell.tag}" no-reorder data="{parent.opts.data}" val="{cell.text}" cell="{cell}" each="{cell in visCells.fixed}" onclick="{parent.handleClick}" riot-style="position: absolute;left:{cell.left}px;top:{cell.top}px;width:{cell.width}px;height:{parent.rowHeight}px;">{cell.text}</gridcelltag> </div> </div> <div class="gridbody" ref="overlay" riot-style="overflow:auto;left:{fixedLeft.width}px;top:{rowHeight}px;bottom:0px;-webkit-overflow-scrolling: touch;pointer-events:none;"> <div class="scrollArea" riot-style="background:rgba(0,0,0,0.005);width:{scrollWidth-fixedLeft.width}px;height:{scrollHeight-rowHeight}px;"></div> </div> </div>', 'grid2 { display: block; -webkit-font-smoothing: antialiased; text-rendering: optimizeSpeed; } grid2 .scrollArea { transform: translateZ(0); } grid2 .gridwrap { position: relative; display: block; border: 1px solid #ccc; font-family: sans-serif; font-size: 14px; } grid2 .gridbody { position: absolute; overflow: hidden; top: 0; left: 0; right: 0; bottom: 0; transform: translateZ(0); backface-visibility: hidden; } grid2 .fixedLeft { position: absolute; top: 0; bottom: 0; } grid2 .cell, grid2 .headercell { position: absolute; box-sizing: border-box; padding: 10px 5px; whitespace: no-wrap; overflow: hidden; background: #fff; border: 1px solid #eee; border-width: 0 1px 1px 0; cursor: pointer; } grid2 .cell.active { background: #eee; } grid2 .header { position: absolute; z-index: 1; overflow: hidden; transform: translateZ(0); }', '', function(opts) {
riot.tag2('grid2', '<div class="gridwrap" riot-style="height:{opts.height}px"> <div class="gridbody" ref="overlay" onscroll="{scrollbar}" riot-style="overflow:auto;left:{fixedLeft.width}px;top:{rowHeight}px;bottom:0px;-webkit-overflow-scrolling: touch;"> <div if="{!measured}" style="height:100000px"></div> <div class="scrollArea" if="{measured}" riot-style="background:rgba(0,0,0,0.005);width:{scrollWidth-fixedLeft.width}px;height:{scrollHeight-rowHeight}px;"></div> </div> <div class="gridbody" ref="mainbody" riot-style="left:{fixedLeft.width}px;top:{rowHeight}px;bottom:{scrollbarwidth}px;right:{scrollbarwidth}px"> <div class="fixedLeft" riot-style="transform:translate3d({fixedLeft.left}px,{fixedLeft.top}px,0px);backface-visibility: hidden;width:{fixedLeft.width}px;bottom:1px;z-index:2;"> <gridcelltag class="cell {cell.classes()}" tag="{cell.tag}" data="{parent.opts.data}" no-reorder val="{cell.text}" cell="{cell}" each="{cell in visCells.main}" onclick="{parent.handleClick}" riot-style="position: absolute;left:{cell.left}px;top:{cell.top}px;width:{cell.width}px;height:{parent.rowHeight}px;">{cell.text}</gridcelltag> </div> </div> <div class="gridbody" ref="header" riot-style="height:{rowHeight}px;margin-right:15px"> <div class="header" riot-style="top:0px;left:0px;width:{scrollWidth}px;height:{rowHeight}px"> <div class="headercell {classes}" each="{headers.main}" no-reorder riot-style="transform:translate3d({left}px,0px,0px); backface-visibility: hidden;width:{width}px;height:{rowHeight}px;">{text}</div> </div> </div> <div class="gridbody" ref="fixedleft" riot-style="width:{fixedLeft.width}px;height:{opts.height-2}px"> <div class="fixedLeft" riot-style="transform:translate3d(0px,{fixedLeft.top}px,0px);backface-visibility: hidden;width:{fixedLeft.width}px;bottom:1px;z-index:2;"> <div class="header" riot-style="top:{0 - fixedLeft.top}px;left:0px;width:{fixedLeft.width}px;height:{rowHeight}px"> <div class="headercell {classes}" each="{headers.fixed}" no-reorder riot-style="top:0px;left:{left}px;width:{width}px;height:{rowHeight}px;">{text}</div> </div> <gridcelltag class="cell {cell.classes()}" tag="{cell.tag}" no-reorder data="{parent.opts.data}" val="{cell.text}" cell="{cell}" each="{cell in visCells.fixed}" onclick="{parent.handleClick}" riot-style="position: absolute;left:{cell.left}px;top:{cell.top}px;width:{cell.width}px;height:{parent.rowHeight}px;">{cell.text}</gridcelltag> </div> </div> </div>', 'grid2 { display: block; -webkit-font-smoothing: antialiased; text-rendering: optimizeSpeed; } grid2 .scrollArea { transform: translateZ(0); } grid2 .gridwrap { position: relative; display: block; border: 1px solid #ccc; font-family: sans-serif; font-size: 14px; } grid2 .gridbody { position: absolute; overflow: hidden; top: 0; left: 0; right: 0; bottom: 0; transform: translateZ(0); backface-visibility: hidden; } grid2 .fixedLeft { position: absolute; top: 0; bottom: 0; } grid2 .cell, grid2 .headercell { position: absolute; box-sizing: border-box; padding: 10px 5px; whitespace: no-wrap; overflow: hidden; background: #fff; border: 1px solid #eee; border-width: 0 1px 1px 0; cursor: pointer; } grid2 .cell.active { background: #eee; } grid2 .header { position: absolute; z-index: 1; overflow: hidden; transform: translateZ(0); }', '', function(opts) {
var calcArea, calcPos, calcVisible, reCalc, reUse;

this.on('before-mount', function() {
Expand All @@ -20,7 +20,8 @@ this.on('before-mount', function() {
this.activeRows = [];
this.rows = [];
this.scrollevents = ['DOMMouseScroll', 'mousewheel', 'touchmove'];
return this.point = null;
this.point = null;
return this.measured = false;
});

this.on('mount', function() {
Expand All @@ -34,6 +35,8 @@ this.on('mount', function() {
})(this));
this.refs.mainbody.addEventListener('touchstart', this.scrollstart, false);
this.refs.fixedleft.addEventListener('touchstart', this.scrollstart, false);
this.scrollbarwidth = this.refs.overlay.offsetWidth - this.refs.overlay.scrollWidth;
this.measured = true;
return this.update();
});

Expand Down Expand Up @@ -236,6 +239,14 @@ this.scrolling = (function(_this) {
};
})(this);

this.scrollbar = (function(_this) {
return function(e) {
e.preventUpdate = true;
_this.refs.header.scrollLeft = _this.refs.overlay.scrollLeft;
return _this.update();
};
})(this);

this.scrollstart = (function(_this) {
return function(e) {
return _this.point = {
Expand Down
22 changes: 15 additions & 7 deletions src/grid2.tag
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
grid2
.gridwrap(style="height:{opts.height}px")

//- scroll area
.gridbody(ref="overlay",onscroll="{scrollbar}",riot-style="overflow:auto;left:{fixedLeft.width}px;top:{rowHeight}px;bottom:0px;-webkit-overflow-scrolling: touch;")
div(if="{!measured}",style="height:100000px")
.scrollArea(if="{measured}",riot-style="background:rgba(0,0,0,0.005);width:{scrollWidth-fixedLeft.width}px;height:{scrollHeight-rowHeight}px;")

//- main body
.gridbody(ref="mainbody",riot-style="left:{fixedLeft.width}px;top:{rowHeight}px;bottom:0px")
.gridbody(ref="mainbody",riot-style="left:{fixedLeft.width}px;top:{rowHeight}px;bottom:{scrollbarwidth}px;right:{scrollbarwidth}px")
.fixedLeft(riot-style="transform:translate3d({fixedLeft.left}px,{fixedLeft.top}px,0px);backface-visibility: hidden;width:{fixedLeft.width}px;bottom:1px;z-index:2;")
gridcelltag.cell(tag="{cell.tag}",data="{parent.opts.data}",class="{cell.classes()}",no-reorder,val="{cell.text}",cell="{cell}",each="{cell in visCells.main}",onclick="{parent.handleClick}",riot-style="position: absolute;left:{cell.left}px;top:{cell.top}px;width:{cell.width}px;height:{parent.rowHeight}px;") {cell.text}

Expand All @@ -18,10 +22,6 @@ grid2
.headercell(each="{headers.fixed}",no-reorder,riot-style="top:0px;left:{left}px;width:{width}px;height:{rowHeight}px;",class="{classes}") {text}
gridcelltag.cell(tag="{cell.tag}",class="{cell.classes()}",no-reorder,data="{parent.opts.data}",val="{cell.text}",cell="{cell}",each="{cell in visCells.fixed}",onclick="{parent.handleClick}",riot-style="position: absolute;left:{cell.left}px;top:{cell.top}px;width:{cell.width}px;height:{parent.rowHeight}px;") {cell.text}

//- scroll area
.gridbody(ref="overlay",riot-style="overflow:auto;left:{fixedLeft.width}px;top:{rowHeight}px;bottom:0px;-webkit-overflow-scrolling: touch;pointer-events:none;")
.scrollArea(riot-style="background:rgba(0,0,0,0.005);width:{scrollWidth-fixedLeft.width}px;height:{scrollHeight-rowHeight}px;")

style(type="text/stylus").
grid2
display block
Expand Down Expand Up @@ -82,6 +82,7 @@ grid2
@rows=[]
@scrollevents = ['DOMMouseScroll','mousewheel','touchmove']
@point = null
@measured = false

@on 'mount',->
@rowHeight = +opts.rowheight || 40
Expand All @@ -91,6 +92,8 @@ grid2
@refs.fixedleft.addEventListener(ev,@scrolling.bind(@,true,false),false)
@refs.mainbody.addEventListener('touchstart',@scrollstart,false)
@refs.fixedleft.addEventListener('touchstart',@scrollstart,false)
@scrollbarwidth = @refs.overlay.offsetWidth - @refs.overlay.scrollWidth
@measured = true
@update()

@on 'before-unmount',->
Expand Down Expand Up @@ -202,6 +205,11 @@ grid2
@refs.header.scrollLeft = @refs.overlay.scrollLeft
@update()

@scrollbar = (e)=>
e.preventUpdate = true
@refs.header.scrollLeft = @refs.overlay.scrollLeft
@update()

@scrollstart = (e)=>
@point = {x:e.changedTouches[0].clientX,y:e.changedTouches[0].clientY}

Expand Down Expand Up @@ -252,7 +260,7 @@ grid2
tag = show.tag || "notag"
if unused[tag]?.length > 0 then visible[unused[tag].pop()] = show else visible.push(show)
return visible


gridcelltag
div(if="{!opts.tag}")
Expand Down
2 changes: 1 addition & 1 deletion test/grid.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ describe 'grid2',->
done()

it "should render only enough rows after scrolling (again)", (done) ->
document.querySelector('.gridbody').scrollTop = 4389
document.querySelector('.gridbody').scrollTop = 4380
setTimeout =>
expect(document.querySelectorAll('.cell').length).to.be.lt((gridheight/40)*4)
expect(document.querySelectorAll('.cell').length).to.be.gt((gridheight/40)*3)
Expand Down

0 comments on commit 8709399

Please sign in to comment.