Getting the closest parent element - multiple class conundrum

Hi there,

I’ve got a conundrum to figure out with an element’s parent which has the same set of CSS classes as other parents.
The basic setup is that I’m trying to tag up all links within a navigation for tracking purposes using a templated class, and attaching both the parent’s heading text and the element’s text as well to differentiate them (some link text is shared between each dropdown).

So far I’ve managed to add in the text of the link itself and attach it to a class for each individual link. However, because all parents within the navigation have the same classes, when I try to use closest() or parents() it returns all parents’ and attaches this to the class instead.

Below is a diagram and detail explanation of what I’m looking to achieve.

For example, because there are multiple links with the same text, I need to be able to pinpoint the element’s parent’s text. Imagine that the “First”, “Second”, “Third” and “Fourth” headings all have the same class names and the only differing factor is the text used. This causes a problem when trying to use closest as it returns all of the parents as I’m trying to pinpoint them using classes. The same problem occurs when attempting to use parents. Then, for the “first-link” link under the “First” heading, I’d want to add the class to the individual link as “first-first-link”. For the “fourth-link” link under the “Third” heading, I’d want to tag this as “third-fourth-link” etc.

Is there a way that I can pinpoint classes of a parent of a specific element - i.e. only target an exact parent of the element, rather than returning all others that are close by in the DOM? For example, only picking out the parent of the “first-link” within the “First” column, not the other column headings as well.

Here is the script I have so far:

    //// Top navigation tagging
    $('.navbar a').each(function(){
        var thisText = $(this).text();
        thisText = thisText.replace(/[^a-z0-9\s]/gi, '').replace(/[_\s]/g, '').toLowerCase();

        // Nav Header links
        if($(this).parent('li.navbar__item.has-children').length > 0){
            $(this).addClass('navbar-link-' + thisText);
        }
        // Nav Dropdown Header links
        else if($(this).parents('dt').length > 0){
            $(this).addClass('navbar-dd-link-' + thisText);
        } 
        // Nav Dropdown Sub-links
        else if($(this).parents('dd').length > 0){
            var navHeader = ($(this).closest('.navbar-link-').text());
            navHeader = navHeader.replace(/[^a-z0-9\s]/gi, '').replace(/[_\s]/g, '').toLowerCase();
            $(this).addClass('navbar-dd-sublink-' + navHeader + thisText);

            // note: Add lookup for the parent of the dd element so that sublinks read as "navbar-sublink-(mens)-(thisText)"
        }
    });

Any suggestions as to how I could do this would be welcome.

Cheers,

Andrew

The script is not relevant at the moment so far as diagnosing goes. What’s the HTML look like?

Hi Paul,

Apologies for the delayed response.
Below is the barebones structure of the navigation at present:

<nav class="navbar collapse" id="js-header-navbar">
    <ul>
        <li class="navbar__item">
            <a href="#">Nav Dropdown 1 Link</a>
            <div class="navbar__dropdown collapse">
                <div class="navbar">
                    <div class="row top-navigation">
                        <div class="col-sm-4 col-md-2">
                            <dl class="navbar-subcategory has-children">
                                <dt>Column 1</dt>
                                <dd>
                                    <ul class="navbar-subcategory collapse">
                                        <li class="navbar-subcategory__item">
                                            <a class="blue-text" href="#">Link 1</a>
                                        </li>
                                        <li class="navbar-subcategory__item">
                                            <a href="#">Link 2</a>
                                        </li>
                                        <li class="navbar-subcategory__item">
                                            <a href="#">Link 3</a>
                                        </li>
                                        <li class="navbar-subcategory__item">
                                            <a href="#">Link 4</a>
                                        </li>
                                    </ul>
                                </dd>
                            </dl>
                        </div>
                        <div class="col-sm-4 col-md-3">
                            <dl class="navbar-subcategory has-children">
                                <dt>
                                    <a href="#">Column 2 - Link</a>
                                </dt>
                                <dd>
                                    <ul class="navbar-subcategory collapse">
                                        <li class="navbar-subcategory__item">
                                            <a href="#">Link 1</a>
                                        </li>
                                        <li class="navbar-subcategory__item">
                                            <a href="#">Link 2</a>
                                        </li>
                                        <li class="navbar-subcategory__item">
                                            <a href="#">Link 3</a>
                                        </li>
                                        <li class="navbar-subcategory__item">
                                            <a href="#">Link 4</a>
                                        </li>
                                    </ul>
                                </dd>
                            </dl>
                        </div>
                    </div>
                </div>
            </div>
        </li>
        <li class="navbar__item">
            <a href="#">Nav Dropdown 2 Link</a>
            <div class="navbar__dropdown collapse">
                <div class="navbar">
                    <div class="row top-navigation">
                        <div class="col-sm-4 col-md-2">
                            <dl class="navbar-subcategory has-children">
                                <dt>Column 1</dt>
                                <dd>
                                    <ul class="navbar-subcategory collapse">
                                        <li class="navbar-subcategory__item">
                                            <a class="blue-text" href="#">Link 1</a>
                                        </li>
                                        <li class="navbar-subcategory__item">
                                            <a href="#">Link 2</a>
                                        </li>
                                        <li class="navbar-subcategory__item">
                                            <a href="#">Link 3</a>
                                        </li>
                                        <li class="navbar-subcategory__item">
                                            <a href="#">Link 4</a>
                                        </li>
                                    </ul>
                                </dd>
                            </dl>
                        </div>
                        <div class="col-sm-4 col-md-3">
                            <dl class="navbar-subcategory has-children">
                                <dt>
                                    <a href="#">Column 2 - Link</a>
                                </dt>
                                <dd>
                                    <ul class="navbar-subcategory collapse">
                                        <li class="navbar-subcategory__item">
                                            <a href="#">Link 1</a>
                                        </li>
                                        <li class="navbar-subcategory__item">
                                            <a href="#">Link 2</a>
                                        </li>
                                        <li class="navbar-subcategory__item">
                                            <a href="#">Link 3</a>
                                        </li>
                                        <li class="navbar-subcategory__item">
                                            <a href="#">Link 4</a>
                                        </li>
                                    </ul>
                                </dd>
                            </dl>
                        </div>
                    </div>
                </div>
            </div>
        </li>
    </ul>
</nav>

Note that there are multiple “navbar__item” elements, one for each dropdown - in the example I’ve just kept it as two as they are all of the same structure.

Please let me know if you need any other information.

Cheers,

Andrew

Hi all,

I realised after much thought that I was thinking about this all the wrong way. Instead of trying to get the closest element, I needed to get the closest parent element. Not only that but I realised that to get the text of the parent, I needed to target the “A” element within this parent (titles on the top of the navigation are all linked).

I therefore broke this down by first targeting the parent element, and then using the “children()” method, I could get the “A” element’s text. It’s quite a simple thing really but had me stumped for a while in-between doing other work. My final script is as follows:

$(document).ready(function(){
    //// Top navigation tagging
    $('.navbar a').each(function(){
        var elementText = $(this).text();
        elementText = elementText.replace(/[^a-z0-9\s]/gi, '').replace(/[_\s]/g, '').toLowerCase();
        var topNavHeader = $(this).closest('li.navbar__item.has-children').children('a[class^="navbar-link-"]').text().replace(/[^a-z0-9\s]/gi, '').replace(/[_\s]/g, '').toLowerCase();
        // console.log($(this).closest('li.navbar__item.has-children').children('a[class^="navbar-link-"]').text().replace(/[^a-z0-9\s]/gi, '').replace(/[_\s]/g, '').toLowerCase());

        
        // Nav Main Category links
        if($(this).parent('li.navbar__item.has-children').length > 0){
            $(this).addClass('topnav-maincat-link-' + elementText);
        }
        // Nav Category Type links
        else if($(this).parents('dt').length > 0){
            $(this).addClass('topnav-cattype-link-' + topNavHeader + "-" + elementText);
        } 
        // Nav Sub Category links
        else if($(this).parents('dd').length > 0){
            $(this).addClass('header-subcat-link-' + topNavHeader + "-" + elementText);
        }
    });

    // Footer navigation tagging
    $('footer a').each(function(){

        var elementText = $(this).text();
        elementText = elementText.replace(/[^a-z0-9\s]/gi, '').replace(/[_\s]/g, '').toLowerCase();

        var footerHeader = $(this).closest('div.footer__link-col').children('h4').text().replace(/[^a-z0-9\s]/gi, '').replace(/[_\s]/g, '').toLowerCase();

        $(this).addClass('footer-link-' + footerHeader + "-" + elementText);
        
    });

});

As I say, quite simple, but a rewarding thing to figure out.

Cheers,

Andrew

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.