Как мне показать / скрыть элементы, используя jQuery, когда есть два пересекающихся принципа, определяющих, должны ли они быть видимыми или нет? - PullRequest
0 голосов
/ 22 января 2011

У меня есть веб-страница, которая содержит набор элементов, которые помечены метаданными с помощью HTML5-тега «data-». Каждый элемент представляет определенный курс или программу в школе. Вот пример того, как может выглядеть набор элементов:

<div class="courseBox" data-type="course" data-location="campus">info about this particular course</div>

<div class="courseBox" data-type="program" data-location="campus">info about this particular course</div>

<div class="courseBox" data-type="course" data-location="distance">info about this particular course</div>

<div class="courseBox" data-type="program" data-location="distance">info about this particular course</div>

Как вы можете видеть, каждый элемент представляет собой либо курс (короткий одиночный курс), либо программу (полное образование, охватывающее несколько лет). Кроме того, каждый элемент - это кампус eithar (в кампусе) или дистанция (дистанционное обучение).

В интерфейсе для этой страницы пользователь имеет четыре кнопки, которые могут быть либо вкл. / Выкл., Либо выкл. / Ложно. Четыре кнопки:

Курс | Программа | Кампус | Расстояние

Когда страница загружается, все четыре кнопки включены / true, поскольку на странице отображаются все курсы и программы, как в кампусе, так и в дистанционном обучении.

Когда пользователь нажимает одну из кнопок, я хочу использовать jQuery, чтобы скрыть все элементы, которые больше не соответствуют критериям; другими словами: фильтр.

Сначала это казалось легкой задачей. Просто напишите что-нибудь вроде:

$("#courseButton").toggle(function(){
   $("courseBox[data-type='course']").hide();
},
function(){
   $("courseBox[data-type='course']").show();
});

Это прекрасно работает, пока два разных способа категоризации элементов не сталкиваются. Но рассмотрим этот случай:

  1. Пользователь сначала нажимает «Курс» кнопка, которая скрывает все курсы (помечены «курсы»).

  2. Затем нажимает кнопку «Расстояние» который скрывает все элементы, отмеченные "Расстояние".

  3. Затем пользователь нажимает «Курс» кнопка снова, которая покажет все элемент, помеченный "курсами", включая те, которые отмечены «расстояние», несмотря на то, что они должен быть скрыт.

Мой вопрос теперь таков: как мне создать функцию фильтра, используя jQuery, которая будет работать правильно, даже если есть два разных (пересекающихся) способа категоризации элементов?

Заранее спасибо!

/ Томас Кан

Ответы [ 3 ]

3 голосов
/ 22 января 2011

На самом деле, ваша ситуация немного сложнее.У вас есть две группы, тип и местоположение.Вам нужно пересечение типа и местоположения.

Это означает, что вы выбираете все элементы выбранного типа (типов), а затем отфильтровываете все предметы, которые не находятся на выбранном расстоянии (s) или наоборот.

Вот пример:

$(".button").click(function() {
    $(this).toggleClass('selected');

    $(".courseBox").hide();

    var datatypes = $(".courseBox");

    $(".button.datatype").not('.selected').each(function() {
        var selClass = $(this).attr('id').replace('Button', '');

        datatypes = datatypes.filter(".courseBox[data-type!='" + selClass + "']");
    });

    $(".button.selected.datalocation").each(function() {
        var selClass = $(this).attr('id').replace('Button', '');

        datatypes.filter(".courseBox[data-location='" + selClass + "']").show();
    });
});

http://jsfiddle.net/jtbowden/qjpctye4/

Я фактически начинаю со всех элементов, удаляю все, которые имеют тип, которыйне выбран, а затем отображать только те, которые находятся на выбранном расстоянии.

$(".button").click(function() {
  $(this).toggleClass('selected');

  $(".courseBox").hide();

  var datatypes = $(".courseBox");

  $(".button.datatype").not('.selected').each(function() {
    var selClass = $(this).attr('id').replace('Button', '');

    datatypes = datatypes.filter(".courseBox[data-type!='" + selClass + "']");
  });

  $(".button.selected.datalocation").each(function() {
    var selClass = $(this).attr('id').replace('Button', '');

    datatypes.filter(".courseBox[data-location='" + selClass + "']").show();
  });
});
.button {
  border: 1px solid black;
  padding: 2px;
  margin: 4px;
  float: left;
  cursor: default;
}
.courseBox {
  clear: both;
  background-color: lightBlue;
  margin: 3px;
}
.selected {
  background-color: lightGreen;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="button selected datatype" id="courseButton">Courses</div>
<div class="button selected datatype" id="programButton">Programs</div>
<div class="button selected datalocation" id="distanceButton">Distance</div>
<div class="button selected datalocation" id="campusButton">Campus</div>

<div class="courseBox" data-type="course" data-location="campus">Course Campus</div>

<div class="courseBox" data-type="program" data-location="campus">Program Campus</div>

<div class="courseBox" data-type="course" data-location="distance">Course Distance</div>

<div class="courseBox" data-type="program" data-location="distance">Program Distance</div>
0 голосов
/ 22 января 2011

Я думаю, что лучшим решением будет использование контроллера, который сохраняет бизнес-логику показа и скрытия объектов. Затем просто используйте методы этого контроллера для переключения состояния модели и всегда вызывайте один и тот же метод для обновления видимости элементов. Вот возможное решение:

var someController = (function(){
    var model = {
        showCourse: true,
        showProgram: true,
        showCampus:true,
        showDistance: true
    }

    var _UpdateView = function(){
        $(".courseBox[data-type='course']").filter(".courseBox[data-location='campus']").toggle(model.showCourse && model.showCampus);
        $(".courseBox[data-type='program']").filter(".courseBox[data-location='campus']").toggle(model.showProgram && model.showCampus);
        $(".courseBox[data-type='course']").filter(".courseBox[data-location='distance']").toggle(model.showCourse && model.showDistance);
        $(".courseBox[data-type='program']").filter(".courseBox[data-location='distance']").toggle(model.showProgram && model.showDistance);
    };

    var _toggleCourse = function(){
        model.showCourse = !model.showCourse;
        _UpdateView();
    };

    var _toggleProgram = function(){
        model.showProgram = !model.showProgram;
        _UpdateView();
    };

    var _toggleCampus = function(){
        model.showCampus = !model.showCampus;
        _UpdateView();
    };

    var _toggleDistance = function(){
        model.showDistance = !model.showDistance;
        _UpdateView();
    };


    return {
        toggleCourse: function(){_toggleCourse();},
        toggleProgram: function(){_toggleProgram();},
        toggleCampus: function(){_toggleCampus();},
        toggleDistance: function(){_toggleDistance();}
    }
})();

Тогда на странице вы можете использовать такие кнопки:

<input type='button' value='Course' onclick='someController.toggleCourse();' />
<input type='button' value='Program' onclick='someController.toggleProgram();' />
<input type='button' value='Campus' onclick='someController.toggleCampus();' />
<input type='button' value='Distance' onclick='someController.toggleDistance();' />
0 голосов
/ 22 января 2011

Создайте полный селектор каждый раз на основе всех четырех входов.

Примерно так:

var selector = '';
$('input:checkbox').each(function(){
    if (this.checked){
        selector += '[data-type="' + this.id +'"], '; // assuming checkbox.id =  Course|Program|Campus|Distance
    }
});

selector = selector.substring(0, selector.length-1); // kill trailing ' ,'

var all = $('.courseBox'),
    toShow = all.filter(selector),
    toHide = all.not(toShow);

toShow.show();
toHide.hide();
...