Replicate CSS :focus selector for multiple elements using javascript

ε祈祈猫儿з 提交于 2021-02-11 12:19:05

问题


I have this website: https://www.australianathleticscalendar.com.au/

I want to make it so you can have selected an 'Events' filter and 'State' filter at once (I.e. 100m and QLD at once), and the bubbles in each filter will have styling (I.e. like :focus). With each filter, select one category. When you change categories within a filter, the previous one selected must also be unstyled (I.e. can't select 100m and 200m at once. Moving from 100m to 200m would remove styling from 100m and add it to 200m).

The problem is with css is that you can only :focus one element at a time.

How can I achieve this using javascript?

I've pulled the relevant code into a codepen here.

This is the functions which draw the two filters:

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();
}

And this is the HTML for the two filters:

        <!-- 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:


As often there are many ways to achieve this. I think the easiest might be to add an extra argument to the calls made in the click handlers -- passing this -- so the handler knows exactly which DOM element needs to get styling:

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

Then in your code define a function that will apply a CSS class to a given DOM element, but also makes sure that it will be the only element having that class. Then use this utility function in the click handlers, which must now also take that extra argument:

// 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();
}

Now it is up to you to define the style of two new CSS classes: selectedEvent and selectedState. You can give them the same definition with a comma:

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


来源:https://stackoverflow.com/questions/65857843/replicate-css-focus-selector-for-multiple-elements-using-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!