3

Good evening, I would like to copy an html menu and change its class using only pure Javascript (ie. no jQuery).

Input:

<header>
    <nav class="page-nav">
        <ul class="social"><li>...</li></ul>
    </nav>
</header>
<main>...</main>
<footer>
    <nav class="footer">
        <ul class="footer-menu"><li>...</li></ul>
    </nav>
</footer>

.footer-menu is copied into .page-nav and the class changed to .main-menu.

Output:

<header>
    <nav class="page-nav">
        <ul class="social"><li>...</li></ul>
        <ul class="main-menu"><li>...</li></ul>
    </nav>
</header>
<main>...</main>
<footer>
    <nav class="footer">
        <ul class="footer-menu"><li>...</li></ul>
    </nav>
</footer>

Any help would be appreciated.

Thanks

Edit... This is what I've tried, but although it creates the wrapper it doesn't create any content...

var menuBar = (function () {
    var footerMenu = document.querySelector('.footer-menu'),
        headerMenu = document.querySelector('.page-nav');

    function init() {
        var wrapper = document.createElement('ul');
        wrapper.setAttribute("class", "main-menu");
        headerMenu.insertBefore(wrapper, headerMenu.childNodes[0]);
        wrapper.appendChild(footerMenu.childNodes);
    }

    init();

})();
Jamie
  • 323
  • 2
  • 12
  • 3
    So what did you try? – epascarello Mar 24 '17 at 23:50
  • 2
    I'm sure there's a bunch of duplicate questions for both copying an element as well as changing its class. – Roope Mar 24 '17 at 23:55
  • I've added what I've tried. As for duplicate questions, I've pulled the copying from a duplicate. As for changing the class, I found that the examples I found were changing the class of both the header and footer elements, so instead tried creating the wrapper element and appending the childNodes of the footer menu (see my edit) – Jamie Mar 24 '17 at 23:59

6 Answers6

3

Six lines of code using:

Details commented in Snippet


SNIPPET

// Reference the .footer-menu
var ftMenu = document.querySelector('.footer-menu');

// Reference the .page-nav
var pgNav = document.querySelector('.page-nav');

// Clone the .footer-menu
var dupe = ftMenu.cloneNode(true);

// Clear .footer-menu of any classes
dupe.className = "";

// Add .main-menu to .footer-menu's clone
dupe.classList.add('main-menu');

// Append the clone of .footer-menu to .page-nav
pgNav.appendChild(dupe);
.main-menu {
  border: 2px solid white;
  background: red;
  color: white;
  width: 250px;
}

.footer-menu {
  border: 1px solid black;
  background: tomato;
  width: 250px;
}

footer,
header {
  border: 2px dashed blue;
}

footer {
  background: seagreen
}

header {
  background: goldenrod;
}

main {
  background: brown;
  color: white
}

.social {
  background: lightblue;
  border: 2px solid grey;
  width: 250px;
}
<header>
  HEADER
  <nav class="page-nav">
    <ul class="social">
      <li>FB</li>
      <li>TW</li>
    </ul>
  </nav>
</header>
<main>
  MAIN CONTENT
</main>
<footer>
  FOOTER
  <nav class="footer">
    <ul class="footer-menu">
      <li>SO</li>
      <li>MDN</li>
      <li>DT</li>
    </ul>
  </nav>
</footer>
zer00ne
  • 41,936
  • 6
  • 41
  • 68
  • This is excellent, really appreciate the links as well. Thanks. I combined the removal and addition of the class just by using `className('main-menu')` – Jamie Mar 25 '17 at 14:56
  • Great, one less step in code is a step forward in efficiency. Happy coding, – zer00ne Mar 25 '17 at 15:57
2

Try this:

Firstly clone the node

var clone = document.querySelectorAll(".one")[0].cloneNode(true);

Next append the cloned node into position

document.querySelectorAll(".two")[0].appendChild(clone);

Then change the class of the cloned element

document.querySelectorAll(".two .one")[0].className = "cloned";

Example: https://jsfiddle.net/5zjvved6/1/

rorymorris89
  • 1,144
  • 7
  • 14
1

1) make a deep clone of the .footer-menu element (to ensure it copies the elements children):

var copy = document.getElementsByClassName('footer-menu');

2) Set the class name of this copy to the new class name:

copy.setAttribute('class', 'main-menu');

3) Append the copy to the nav.page-nav element:

document.getElementsByClassName('page-nav')
  .appenChild (copy);
Pineda
  • 7,435
  • 3
  • 30
  • 45
  • Is there a benefit of using `setAttribute` over `className`? – Jamie Mar 25 '17 at 14:39
  • @Jamie: `setAttribute` sets the attribute, `.className` sets the property. Since the OP's question regarded changing HTML nodes I preferred the former approach.[here's a SO answer](http://stackoverflow.com/q/33451050/2902660), – Pineda Mar 25 '17 at 15:03
0

var footerMenu - document.getElementsByClassName('footer-menu')[0].cloneNode(true);
footerMenu.className = 'main-menu';

document.getElementsByClassName('page-nav')[0].appenChild(footerMenu);

here is my code, try it

0

var Hello = document.getElementById("Fdiv");

Hello.className = "Bye!";
<html>
    <head><title>Test</title></head>
    <body>
        <div class="Hello" id="Fdiv">
            <p>Hello world!</p>
        </div>
        <script src="notstyle.js"></script>
    </body>
</html>
Solution

If you want to change class you use the (AnyElement).className = "String".

Tips

I would recommend you to add an ID to the element that you would not change so that you can refer to it later even after the class changes.

Resources

One resource I highly recommend, especially for newbies like you, is the Mozilla Developer Network (MDN). They have EVERYTHING you need to know about javascript, HTML, and css.

0

This works.

var doc = document;
var pageNav = doc.getElementsByClassName("page-nav")[0];
var socialList = doc.getElementsByClassName("social")[0];
var footerMenu = doc.getElementsByClassName("footer-menu")[0];
var footerItems = footerMenu.getElementsByTagName("li");
var text;
var item;
var mainMenu = doc.createElement("ul");
mainMenu.classList.add("main-menu");

for (var i = 0; i < footerItems.length; i++) {
  text = doc.createTextNode(footerItems[i].innerHTML);
  item = doc.createElement("li");
  item.appendChild(text);
  mainMenu.appendChild(item);
}

pageNav.appendChild(mainMenu);
.socal{
  background:grey;
}
.main-menu{
  background:blue;
  color:white;
}
.footer-menu{
  background:green;
  color:white;
}
<header>
    <nav class="page-nav">
        <ul class="social">
          <li>apple</li>
          <li>orange</li>
        </ul>
    </nav>
</header>
<main>
</main>
<footer>
    <nav class="footer">
        <ul class="footer-menu">
          <li>up</li>
          <li>down</li>
        </ul>
    </nav>
</footer>
Ronnie Royston
  • 16,778
  • 6
  • 77
  • 91
  • I'm fairly sure this will work, but it seems a complicated way of going about it compared to some of the other suggestions. Is there a benefit of doing it this was around? – Jamie Mar 25 '17 at 14:31
  • It certainly works in the 'run code snippet' embedded demo. I see your point though. `.cloneNode` appears the better tool, but above is how I did it. Learned something new (cloneNode) though! – Ronnie Royston Mar 25 '17 at 17:05