jQuery show / hide elements based on *multiple* jQuery UI sliders

875 Views Asked by At

I'm trying to create an airline style time filter.

I have a series of 'badges', each with a series of times in seconds:

<div id="block732914299" class="pull-left" data-departuretime1="1340" data-departuretime0="865" data-arrivaltime0="980" data-arrivaltime1="10">

Now I want to use the jQuery UI sliders to show/hide various badges based on these times.

I have one working.

$(".slider-range1").slider({
    range: true,
    min: mintime,
    max: maxtime,
    step: steptime,
    values: [mintime, maxtime],

    slide: function (e, ui) {
        var time2 = moment().startOf('day').add('m', ui.values[0]).format('h:mma');
        var time3 = moment().startOf('day').add('m', ui.values[1]).format('h:mma');
        $('.slider-time2').html(time2);
        $('.slider-time3').html(time3);

        // show or hide badges based on attr for each badge
        $('div[id^="block"]').each(function(e){
            if($(this).data('arrivaltime0') >= ui.values[0] && $(this).data('arrivaltime0') <= ui.values[1]){
                $(this).show();
            } else {
                $(this).hide()
            }
        });
    }
}); // slider-range1

But I'm a bit stuck when I add the second slider because now they are conflicting. When I alter one slider it overrides the other.

Digging through the jQuery docs I'm looking at .filter - but I'm not sure how best to proceed using that.

I can probably write a bunch of ugly if/else statements to check all the permutations but it seems like there should be a more efficient way to do this?

Update:

Fiddle: http://jsfiddle.net/thecrumb/FB4Sv/27/

Use/test case:

  • Set departure slider to 7-9AM - Badge A and B should display (8am)
  • Without changing first slider, set arrival slider to 7-9PM - Badge C should display (8pm)
  • At this point Badges A, B AND C should be displayed.
  • D should still be hidden.

Still stuck with this :(

2

There are 2 best solutions below

1
On

Here is the updated answer using a function. I just figured I'd create a new answer to make it cleaner...

$(".slider-range1").slider({
    range: true,
    min: mintime,
    max: maxtime,
    step: steptime,
    values: [mintime, maxtime],

    slide: function (e, ui) {
        var time2 = moment().startOf('day').add('m', ui.values[0]).format('h:mma');
        var time3 = moment().startOf('day').add('m', ui.values[1]).format('h:mma');
        $('.slider-time2').html(time2);
        $('.slider-time3').html(time3);
        doShowHideBadges();         
    }
}); // slider-range1

function doShowHideBadges(){
    //show all initially then loop through and hide each invalid option
    $('div[id^="block"]').show().each(function(e){
       //show items for first slider
        var sliderValue = $('.slider-range0').slider("option", "values");
        if($(this).data('departuretime0') < sliderValue[0] ||
           $(this).data('departuretime0') > sliderValue[1]){
           $(this).hide();            
       }
       // show items for second slider
       var slider2Value = $('.slider-range1').slider("option", "values");
       if($(this).data('arrivaltime0') < slider2Value[0] ||
          $(this).data('arrivaltime0') > slider2Value[1]){
           $(this).hide();           
       }

    });
}

http://jsfiddle.net/FB4Sv/17/

9
On

is it an AND or an OR situation?

Assuming it's OR you could do something like this...

FIRST you hide them all. THEN you show the applicable ones for each slider

// show or hide badges based on attr for each badge
$('div[id^="block"]').hide().each(function(e){
    if($(this).data('arrivaltime0') >= ui.values[0] && $(this).data('arrivaltime0') <= ui.values[1]){
        $(this).show();
    }
});

If you wanted AND you just do the opposite. show them all then hide the invalid ones

// show or hide badges based on attr for each badge
$('div[id^="block"]').show().each(function(e){
    if(! ($(this).data('arrivaltime0') >= ui.values[0] && $(this).data('arrivaltime0') <= ui.values[1])){
        $(this).hide();
    }
});

The problem with your current code is that it is showing or hiding every element every time so the different sliders are stepping on eachother.