Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laggy element position update on mobile scrolling

I'm trying to make a sticky header + first column table. Works fine on desktop browsers.

However, when I scroll the table's x-axis on a mobile device, the position update is dragging i.e. not fast enough.

I've read various SO-threads that suggest iScroll. I'm not really sure how to use it appropriately in this case. Should intercept the tbody scroll event, perevent the default behaviour and update the position based on iScroll's event values? Please point me in the right direction here :)

$(function() {
  var $tbody = $('tbody');

  $tbody.on('scroll', function(e) { 
    var left = $tbody.scrollLeft();
    $('thead').css('left', -left); 
    $('tbody td:nth-child(1), thead th:nth-child(1)').css('left', left);
  });

  var iScroll = new IScroll($tbody[0], { probeType: 3 });
  iScroll.on('scroll', function(){
    console.log('not fired?');
  });
});

https://jsfiddle.net/97r799gr/

To reproduce the problem, it's probably easiest for you to visit https://jsfiddle.net/97r799gr/show on your mobile. I'm using an SGS7 edge so I think this will be reproducible on pretty much any mobile device.

like image 495
Johan Avatar asked Jan 30 '17 08:01

Johan


1 Answers

IScroll uses a wrapper with fixed dimensions with one scrollable content in it. Therefore we can't use tbody as a wrapper. We should wrap the whole table and hold desired elements with CSS when scrolling.

I've created a fiddle with iscroll-probe.js code in it (iscroll.js hasn't got a scroll event). Bad news is that it works only on my iPhone. Scrolling is suddenly stops when scrolling it on my android5.1 device.

// main code
$(document).ready(function(){ 
  $('#pos').text('initialize iscroll');
  try{
    var iScroll = new IScroll('#wrapper', { 
      interactiveScrollbars: true, 
      scrollbars: true, 
      scrollX: true, 
      probeType: 3, 
      useTransition:false, 
      bounce:false
    });
  } catch(e) {
    $('#error').text('Error ' + e.name + ":" + e.message + "\n" + e.stack);
  }

  $('#pos').text('initialized');

  iScroll.on('scroll', function(){
    var pos = $('#scroller').position();
    $('#pos').text('pos.left=' + pos.left + ' pos.top=' + pos.top);

    // code to hold first row and first column
    $('#scroller th:nth-child(1)').css({top: (-pos.top), left: (-pos.left), position:'relative'});
    $('#scroller th:nth-child(n+1)').css({top: (-pos.top), position:'relative'});

    $('#scroller td:nth-child(1)').css({left: (-pos.left), position:'relative'});
  });
});

https://jsfiddle.net/0qv1kjac/11/

like image 166
shukshin.ivan Avatar answered Nov 08 '22 06:11

shukshin.ivan