Barrett Kuethen
Barrett Kuethen

Reputation: 1914

How to bind multiple elements to scroll together?

I have 3 different tables that scroll horizontally (one scrolls vertically). How do I bind them all together so if I scroll horizontally on one, they all scroll?

I've read through here (Mozilla docs) but I can't get it to work.

It seems like it should be fairly simple.

<div class="page-wrapper relative">
<div class="table-wrapper-outter">
    <div class="table-wrapper">
        <div class="header header-wrapper">
            <div class="header-inner">
                <table id="headerTable" class="table-contents">
                    <tr>
                        <td> 1234567890 </td>
                        <td> 1234567890 </td>
                        <td> 1234567890 </td>
                        <td> 1234567890 </td>
                        <td> 1234567890 </td>
                        <td> 1234567890 </td>
                        <td> 1234567890 </td>
                        <td> 1234567890 </td>
                        <td> 1234567890 </td>
                        <td> etc... </td>
                    </tr>

                </table>
            </div>
        </div>
        <div id="bodyHolder" class="table-content-outter">
            <div class="table-content-inner">
                <table id="mainTable" class="table-contents">
                        <tr>
                            <td> 1234567890 </td>
                            <td> 1234567890 </td>
                            <td> 1234567890 </td>
                            <td> 1234567890 </td>
                            <td> 1234567890 </td>
                            <td> 1234567890 </td>
                            <td> 1234567890 </td>
                            <td> 1234567890 </td>
                            <td> 1234567890 </td>
                            <td> etc... </td>
                        </tr>
                        <!-- many rows -->

                </table>
            </div>
        </div>
        <div class="header footer-wrapper">
            <div class="header-inner">
                <table id="footerTable" class="table-contents">
                    <tr>
                        <td> 1234567890 </td>
                        <td> 1234567890 </td>
                        <td> 1234567890 </td>
                        <td> 1234567890 </td>
                        <td> 1234567890 </td>
                        <td> 1234567890 </td>
                        <td> 1234567890 </td>
                        <td> 1234567890 </td>
                        <td> 1234567890 </td>
                        <td> etc... </td>
                    </tr>
                </table>
            </div>
        </div>
    </div>
</div>

And here is the javascript I tried:

function megaTableInit(tableBodyHolder, mainTable, headerTable, footerTable, tablePullDivs, tableRowHeads) {
var bodyHolder = document.getElementById(tableBodyHolder);
var mTable = document.getElementById(mainTable);
var hTable = document.getElementById(headerTable);
var fTable = document.getElementById(footerTable);
var pullDivs = document.getElementsByClassName(tablePullDivs);
var rowHeads = document.getElementsByClassName(tableRowHeads);

bodyHolder.onmousemove = bodyHolder.onscroll = function() {

    pullDivs[0].scrollLeft = this.scrollLeft;

    var sl = this.scrollLeft;

    if(this.oldSL != sl) {
        this.oldSL = sl;

        for (i=0; i<pullDivs.length; i++) {
            pullDivs[i].scrollLeft = this.scrollLeft;
        }
    }
}

I don't get any errors. It just doesn't do anything with the over divs. When I run console.log for sl and this.scrollLeft I get the pixels as I scroll. But it doesn't set the scroll for the other divs.

Any help would be appreciated.

Upvotes: 3

Views: 9478

Answers (3)

Philll_t
Philll_t

Reputation: 4437

Okay, you already picked the answer, but there are some elements to your problem that weren't addressed. I liked the idea of binding a scroll to all boxes, including one that is horizontal. I've created this jQuery plugin that will allow you to bind scroll boxes together, and will even bind cross-plane scrolling. You can check it out here

Now, it's a pretty big plugin but I'll explain what it does.

say you have three divs

<div class="scroll">
    Vertical
    Vertical
    vertical
    Vertical
    Vertical
    vertical

</div>

<div class="scroll">
    Vertical
    Vertical
    vertical
    Vertical
    Vertical
    vertical
    Vertical
    Vertical
    vertical
</div>

<div class="scroll" data-horizontal="true"> horizontal horizontal horizontal horizontal </div>

Two of these are vertical (and different heights) and the last one is vertical.

To bind these together, you simply implement the jQuery extension like so:

$(".scroll").bindScroll();

Not only will the plugin bind the scroll, but it will also adjust to accommodate different heights. So if you scroll to the bottom (or far right) of one div, despite the difference in size, it will go to the bottom or far right of the other divs.

If you have any questions regarding the plugin, let me know.

Upvotes: 0

Ricky Nelson
Ricky Nelson

Reputation: 876

I'm not sure if this is exactly what you want but it does what you described, it scrolls all the others when you scroll 1.

$('.scroller').scroll(function(e){
  $('.scroller').scrollLeft(e.target.scrollLeft);
});

http://codepen.io/anon/pen/QbaKNz

EDIT: here is the same example with vanilla JavaScript:

var scrollers = document.getElementsByClassName('scroller');

var scrollerDivs = Array.prototype.filter.call(scrollers, function(testElement) {
  return testElement.nodeName === 'DIV';
});

function scrollAll(scrollLeft) {
  scrollerDivs.forEach(function(element, index, array) {
    element.scrollLeft = scrollLeft;
  });
}

scrollerDivs.forEach(function(element, index, array) {
  element.addEventListener('scroll', function(e) {
    scrollAll(e.target.scrollLeft);
  });
});

http://codepen.io/anon/pen/zGpNrm

Upvotes: 5

dgrundel
dgrundel

Reputation: 568

Here's a fairly simple implementation:

<style>
    .container { width: 300px; height: 400px; overflow-y: scroll; float: left; margin: 20px; }
</style>

<div class="container">
    <table>
        <!-- table rows here -->
    </table>
</div>
<div class="container">
    <table>
        <!-- table rows here -->
    </table>
</div>
<div class="container">
    <table>
        <!-- table rows here -->
    </table>
</div>

<script>
    (function(){
        var boxes = document.querySelectorAll('.container');
        for(var boxIndex = 0, bl = boxes.length; boxIndex < bl; boxIndex++) {

            boxes[boxIndex].onscroll = function(){
                for(var boxIndex2 = 0, bl2 = boxes.length; boxIndex2 < bl2; boxIndex2++) {
                    if(boxes[boxIndex2] !== boxes[boxIndex]) {
                        boxes[boxIndex2].scrollTop = this.scrollTop;
                    }
                }
            };
        }
    })();
</script>

When the container element is scrolled, it updates the scrollTop value for the remaining elements.

Upvotes: 0

Related Questions