Реплицировать CSS: селектор фокуса для нескольких элементов с использованием javascript

#javascript #html #jquery #json #filter

#javascript #HTML #jquery #json #Фильтр

Вопрос:

У меня есть этот веб-сайт: https://www.australianathleticscalendar.com.au /

Я хочу сделать так, чтобы вы могли выбрать фильтр «События» и фильтр «Состояние» одновременно (т.Е. 100m и QLD одновременно), и пузырьки в каждом фильтре будут иметь стиль (например, как: фокус). С каждым фильтром выберите одну категорию. Когда вы меняете категории внутри фильтра, предыдущая выбранная также должна быть без стилей (т.е. Невозможно выбрать 100m и 200m одновременно. Переход от 100m к 200m приведет к удалению стиля из 100m и добавлению его к 200m).

Проблема с css заключается в том, что вы можете: фокусировать только один элемент за раз.

Как я могу добиться этого с помощью javascript?

Я поместил соответствующий код в codepen здесь .

Это функции, которые рисуют два фильтра:

 function drawCategories() {
var template = Handlebars.compile(document.getElementById("menu-template").innerHTML);
console.log('draw ', this.products);
document.getElementById('menu-container').innerHTML = template(this.events);
}

function drawStates() {
    var template = Handlebars.compile(document.getElementById("menu-template-2").innerHTML);
    console.log('draw ', this.products);
    document.getElementById('menu-container-states').innerHTML = template(this.states);
}


function showCategory(event) {
    this.title = event;
    drawProducts();
}

function showState(state) {
    this.titleStates = state;
    drawProducts();
}
 

И это HTML для двух фильтров:

         <!-- Events filter -->
<div class="container">
    <script id="menu-template" type="text/x-handlebars-template">           
                <ul class="navbar-nav">
                    {{#each this as |event|}}
                        <li class="nav-item"></li>
                            <a class="nav-link" href="#" onclick="showCategory('{{event.name}}');">{{event.name}}</a>
                    {{/each}}
                    <a class="navbar-brand hover-color" href="#" onclick="showAllEvents();">All Events</a>
                </ul>
                
                <ul class="navbar-nav ml-auto"></ul>
                    <li class="nav-item">                       
                    </li>
                </ul>
        </div>
    </script>
</div>

<!-- States filter -->
<div class="container">
    <script id="menu-template-2" type="text/x-handlebars-template">
                <ul class="navbar-nav">
                    {{#each this as |state|}}
                        <li class="nav-item"></li>
                            <a class="nav-link nav-link-states" href="#" onclick="showState('{{state.name}}');">{{state.name}}</a>
                    {{/each}}
                    <a class="navbar-brand hover-color-states" href="#" onclick="showAllStates();">All States</a>
                </ul>               
                <ul class="navbar-nav ml-auto"></ul>
                    <li class="nav-item">                       
                    </li>
                </ul>
        </div>
    </script>
</div>
 

Комментарии:

1. Кстати, ваш HTML будет иметь повторяющиеся id значения атрибутов (например stateFilter ), что недопустимо в HTML. Вы должны удалить эти id атрибуты. Похоже, они не служат какой-либо цели.

2. существует eventsFilter и stateFilter , который я добавил, когда пытался использовать classList для :focus, но, похоже, я не могу найти дубликат stateFilter

3. Он становится дублирующимся, когда шаблон расширяется с помощью цикла handlebar #each . Ни один из HTML-файлов в таком цикле не должен иметь id атрибутов.

4. Кроме того, у вас больше закрытия </li> , чем открытия <li> .

5. Спасибо, я удалил эти идентификаторы и </li> .

Ответ №1:

Как часто бывает, есть много способов добиться этого. Я думаю, что проще всего было бы добавить дополнительный аргумент к вызовам, выполняемым в обработчиках щелчков — передача this — чтобы обработчик точно знал, какой элемент DOM должен получить стиль:

 <a onclick="showCategory(this, '{{event.name}}');">
<a onclick="showAllEvents(this);">
<a onclick="showState(this, '{{state.name}}');">
<a onclick="showAllStates(this);">
 

Затем в вашем коде определите функцию, которая будет применять класс CSS к данному элементу DOM, но также гарантирует, что это будет единственный элемент, имеющий этот класс. Затем используйте эту служебную функцию в обработчиках щелчков, которые теперь также должны принимать этот дополнительный аргумент:

 // Utility function that ensures only one element has the given CSS class:
function selectElem(elem, className) {
    let prevSelected = document.querySelector("."   className);
    if (prevSelected) prevSelected.classList.remove(className);
    elem.classList.add(className);
}

function showCategory(elem, event) { // <-- extra parameter, here and below...
    selectElem(elem, "selectedEvent"); // <-- add this call, here and below...
    this.title = event;
    drawProducts();
}

function showAllEvents(elem) {
    selectElem(elem, "selectedEvent");
    this.title = "All Events";
    drawProducts();
}

function showState(elem, state) {
    selectElem(elem, "selectedState"); // <-- different style here and below
    this.titleStates = state;
    drawProducts();
}

function showAllStates(elem) {
    selectElem(elem, "selectedState");
    this.titleStates = "All States";
    drawProducts();
}
 

Теперь вам предстоит определить стиль двух новых классов CSS: selectedEvent и selectedState. Вы можете дать им одинаковое определение с помощью запятой:

 .selectedState, .selectedEvent {
    # Your styling ...
}