Syncing and "un" syncing scrolling of 2 or more separate containers

I’m in the middle of trying to sync 2 or more table row elements when overflow-x happens. So far, it’s working… But something I’m struggling with is how to “reset” the TRs back to their original states (i.e. - “un” sync the sync).


    $('fieldset.group-project-table').livequery(function(){//Using the livequery plugin to listen for DOM changes (i.e. - add / remove of TRs).
        $('fieldset.group-project-table').append('<label id="locker">Scroll Lock?<input type="checkbox" /></label>');//Create a checkbox to activate the scroll-sync.
        $('#locker input[type="checkbox"]').click(function(){//Get the parent of the checkbox and listen for clicks...
            if($('#locker input[type="checkbox"]:checked').length == 1){//Is the checkbox checked? If yes...
                $('#group_project_table_values tbody tr').each(function(){//Grab each TR...
                    $('#group_project_table_values tbody tr:last-child td').scroll(function(){//Get the last TR in the bunch and listen for its scrolling event...
                        $('#group_project_table_values tbody tr:not(:last-child) td').scrollLeft($(this).scrollLeft());//Make the other TRs in the group scroll with this last TR in the group (aka "synced scrolling".)
                        return;//Not sure if this is necessary.
                    });
                });
            }else{//Try to reset the scrollers to return to separate scrolling (aka "un-synced scrolling".)
                if($('#locker input[type="checkbox"]:checked').length == 0){//If the checkbox is NOT checked...
                    $('#group_project_table_values tbody tr td').scroll(0,0);//Return the scollbars to start. <-- This isn't working and I have no clue why. The scrollbars remain synced.
                }
            }
        });
    });

Sorry for the comments above but I included them because I thought it might help what’s going through my mind with all of it.

The main problem: The scrollable TRs continue to be synced. When you scroll one, the others scroll with it, regardless of trying to break out of the syncing logic…

Any ideas why? I didn’t include any markup here because I didn’t think it would be needed, but let me know if it would help and I’ll include some… The TRs I’m speaking of here are dynamically created with a “Add More” button on the interface, hence my use of the livequery plugin to check for new elements. Otherwise, everything is inside a “document.ready” block and the TRs have overflow-x in their CSS (this whole thing is meant for an Excel type of interface).

I’d start off by removing the if condition from the else section. You only get to the else section when the checkbox is not checked, so there’s no point in complicating things even further with an additional if statement check.

Still not working. The IF condition is removed and here’s where I am now:

    $('fieldset.group-project-table').livequery(function(){
        $('fieldset.group-project-table').append('<label id="locker">Scroll Lock?<input type="checkbox" /></label>');
        $('#locker input[type="checkbox"]').click(function(){
            if($('#locker input[type="checkbox"]:checked').length == 1){
                $('#group_project_table_values tbody tr').each(function(){
                    $('#group_project_table_values tbody tr:last-child td').scroll(function(){
                        $('#group_project_table_values tbody tr:not(:last-child) td').scrollLeft($(this).scrollLeft());
                        return;
                    });
                });
            }else{
                $('#group_project_table_values tbody tr td').scroll(0,0);
            }
        });
    });

If the TRs are still synced even after unchecking that checkbox, then that says to me that something isn’t being “heard” by the overall listener when that checkbox IS unchecked after having been checked–which originally causes the syncing to occur. So with this in mind, would this mean then that my placement of the checkbox logic needs to be placed in some sort of bind or other kind of listener versus what I’m using with this livequery stuff?

It seems that you need now to remove the scroll event from elements that you assigned them to.

Here is where they are assigned:


$('#group_project_table_values tbody tr').each(function () {
    $('#group_project_table_values tbody tr:last-child td').scroll(function () {

When assigning an event handler, it’s preferred now to use the on method.


$('#group_project_table_values tbody tr').each(function () {
    $('#group_project_table_values tbody tr:last-child td').on('scroll', function () {

One of the benefits of using that, is that removing the event is achieved in a similar and consistant manner with the off method:


$('#group_project_table_values tbody tr').each(function () {
    $('#group_project_table_values tbody tr:last-child td').off('scroll');

That’s a good catch, Paul, but what if I’m using jQuery 1.3? Could ON() be traded for BIND()? And if so, how could one “un-bind()” a bind?

Ah geez, I just saw the “unbind()” function. Ha.
…long day. ;.)

So I’m using bind() and unbind() now… I think the code is working–just not like I think it should be. This code fires IF and ONLY IF the last TR’s TD scrolls horizontally and is meant to make the other TRs’ TDs sync with it’s scrollLeft position. Unfortunately, what happens is that the other TR TDs just don’t scroll. However, they do “lock in place” whereby I can still scroll with the last TR’s TD…

SO, long story short, that last TR TD scrolls, but the others don’t (when this code is fired). Otherwise, everything is working great. lol.

Any ideas what’s causing this?


        $('#locker input[type="checkbox"]').click(function(){
            $('#group_project_table_values tbody tr').each(function(){
                $('#group_project_table_values tbody tr:last-child td').bind('scroll', function(){
                    if($('#locker input[type="checkbox"]:checked').length == 1){
                        $('#group_project_table_values tbody tr:last-child td').scroll(function(){
                            console.log('Bound.');
                            $('#group_project_table_values tbody tr:not(:last-child) td').scrollLeft($('#group_project_table_values tbody tr:last-child td').scrollLeft());<-- All TR TDs (Table TDs) *should* scroll with the last TR TD here.
                        });
                    }else{
                        console.log('Unbound.');
                        $('#group_project_table_values tbody tr:last-child td').unbind('scroll');<-- Everything goes back to normal.
                    }
                });
            });
            return;
        });

Thoughts?

With no HTML code on which to test your scripting code, we are still stumbling around in the dark.

I think that you may want to do something about that.

Yeah, sorry about that, Paul. I would’ve posted that but I figured I’d just fix it on my own–which I did! :slight_smile:

Inside each TR resides TDs whereby only one of those accounts for the actual scrolling element… Duh. Something I probably would’ve caught if I had more rest. Anyway, here’s everything I wound up with:


    if($.isFunction($.livequery)){
        $('fieldset.group-project-table').livequery(function(){
            $('fieldset.group-project-table').append('<label id="locker">Scroll Lock?<input type="checkbox" /></label>');

            $('#locker input[type="checkbox"]').bind('click', function(){
                $('#group_project_table_values tbody tr:last-child td').bind('scroll', function(){

                    if($('#locker input[type="checkbox"]:checked').length == 1){
                        //CHECKED...
                        $('#group_project_table_values tbody tr:not(:last-child) td+td').scrollLeft($('#group_project_table_values tbody tr:last-child td+td').scrollLeft());
                    }else{
                        //NOT CHECKED...
                        $('#group_project_table_values tbody tr:last-child td+td').unbind('scroll');
                    }
                });
            });

        });

    }

Stupid me… I should’ve remembered what was actually scrolling in all this.