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

850 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 answers

1
Lenny 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
Lenny 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.