1

I'm trying to push my Javascript knowledge and improve for my current job as a designer-developer. The other developer and I cooperated on this jQuery to alter Squarespace's default menu behavior, which is really weird. But we're loading the entire jQuery library just to accomplish this one thing.

I'd like to rewrite the code to run in plain vanilla javascript so that I don't have to load the library on every website we make, but I'm not experienced enough in Javascript to just wing through this.

Here is the code:

$(function () {
    if ($(window).width() > 640) {
        $(function () {
            $(".folder-parent a").each(function () {
                $(this).next().find("a").first().hide();
            });
            $(".folder-parent a").click(function () {
                window.location = $(this).next().find("a").first().attr("href");
            });
        });
    }
});

I see some potential issues. First off, I know the class selector will have to be rewritten, or is there another way around that? I don't have the option of adding IDs so I can use getElementsById. Can Javascript hop through the DOM (next, find) and so on?

I'll put up my own attempt at rewriting this code, but I was wondering if y'all had any pointers for converting code, or any pitfalls to avoid, or things like that. Thank you very much!

Andrew

EDIT: Here is my attempt in vanilla Javascript. This is literally the first function I've ever written that's not from a tutorial, so it didn't work. What am I doing wrong? I guess I left some jQuery mixed in.

// Function to change the default menu behavior of Squarespace. Written minus jQuery!
function fixSquarespaceNav {
    if (document.documentElement.offsetWidth > 640) { 
        var navElement = document.querySelectorAll(".folder-parent a");
        foreach (navElement) { 
            this.next().find("a").first().style.display = "none";
        }
        navElement.onclick=function(){
            window.location = this.next().find("a").first().attr("href");
        }; /* navElement */
    }
}
6
  • developer.mozilla.org/en/docs/Web/API/Document.querySelectorAll Commented May 23, 2014 at 15:30
  • just take it one step at a time, could for instance just forcus on the window.location to begin with. Commented May 23, 2014 at 15:30
  • 1
    You'll find document.querySelectorAll() is almost exactly the same as a jQuery selector. Loop over the NodeList, and check out the source code for find()/first()/next() (which are conveniently in plain ol' JavaScript ;) ) Commented May 23, 2014 at 15:30
  • 1
    Where is your own attempt? And yes, vanilla JS can certainly do all of those things. Commented May 23, 2014 at 15:31
  • you can also just do all of this stuff without a module. Commented May 23, 2014 at 15:39

1 Answer 1

2

A more or less literal translation is

function fixSquarespaceNav() {
    if (document.documentElement.offsetWidth > 640) { 
        var navElements = document.querySelectorAll(".folder-parent a");
        for(var i=0, l=navElements.length; i<l; ++i)
            navElements[i]
                .nextElementSibling
                .getElementsByTagName('a')[0]
                .style.display = "none";
        for(var i=0, l=navElements.length; i<l; ++i)
            navElements[i].onclick = function(){
                window.location =
                    this
                    .nextElementSibling
                    .getElementsByTagName('a')[0]
                    .getAttribute('href');
            };
    }
}

But you can use

(function() {
    function getAnchor(el) {
        return el.nextElementSibling.getElementsByTagName('a')[0];
    }
    function handler() { window.location = getAnchor(this).href; }
    return function fixSquarespaceNav() {
        var navElements = document.querySelectorAll(".folder-parent a");
        for(var i=0, l=navElements.length; i<l; ++i) {
            getAnchor(navElements[i]).style.display = "none";
            navElements[i].onclick = handler;
        }
    }
})();
Sign up to request clarification or add additional context in comments.

20 Comments

I'll look at this in more detail when I get home, but getAnchor is a helper function since it is repeated in the first code section, right? then the function is setting the same variable, and then running the for loop which is shorter and more compact because of the getAnchor function.
@authorandrew Yes. And I use a wrapping self-executing function function to avoid possible conflict with other codes.
What does this line do? function handler() { window.location = getAnchor(this).href; }
@authorandrew That's the event handler. Event handlers shouldn't be defined inside loops because then a new function is recreated at each iteration. And I use href property instead of href attribute because it's the "good" way of doing it (and it's shorter).
Gotcha. What event is it handling, exactly? window.location captures what? I can see that it's running the getAnchor function. Aha, I see! The handler function is called later on, to set the new href to the original element. What's the difference between a property and attribute?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.