Insert Parents for all links in menu list - javascript

I am trying to insert h2 tags and make them parents for all links inside of a vertical navigation menu.
I can do this for a single element but now I want to do it for all elements within a menu.
JavaScript:
var menu_item = document.querySelector("div.righ-nav-style1 ul li a");
// `menu_item` is the element you want to wrap
var parent = menu_item.parentNode;
var wrapper = document.createElement('h2');
wrapper.className = 'category_links';
// set the wrapper as child (instead of the 'menu_item')
parent.replaceChild(wrapper, menu_item);
// set 'menu_item' as child of wrapper
wrapper.appendChild(menu_item);
I want to use the replaceChild() and appendChild() methods within a forloop for all menu items.
Any help would be greatly appreciated!

EDIT: I actually just found a solution to my problem.
Edited JavaScript:
// Replaced 'querySelector()' with 'querySelectorAll()' to get all elements
var menu_item = document.querySelectorAll("div.righ-nav-style1 ul li a");
// Created 'for' loop to use 'replaceChild()' and 'appendChild()' methods for all elements
for (var i = 0; i < menu_item.length; i++){
var parent = menu_item[i].parentNode;
var wrapper = document.createElement('h2');
wrapper.className = 'category_links';
// set the wrapper as child (instead of the 'menu_item')
parent.replaceChild(wrapper, menu_item[i]);
// set 'menu_item' as child of wrapper
wrapper.appendChild(menu_item[i]);
}

Related

How can i make my new bullet points display a string?

First time posting, sorry if i do something wrong.
When i try to make a new list with js, the list elements only display [object HTMLLIElement] in the DOM. I would want it to make a new bullet point which says "Hello" each time i press the button.
It only shows this https://gyazo.com/f441c11ce81d80ff14ba4e207c1a7e2d
Here's my code.
var bodyEl = document.querySelector("body");
var ulist = document.createElement("ul");
var bulletpointEl = document.createElement("li");
bulletpointEl.innerHTML = "hello"
bodyEl.appendChild(ulist);
function bulletpoint() {
ulist.innerHTML += bulletpointEl;
}
<button onclick="bulletpoint()">New bulletpoint</button>
You have to use appendChild instead of innerHTML. To create new li element in each button click, you have to create that inside the function.
I will also suggest you to use textContent instead of innerHTML when the content is simple text.
var bodyEl = document.querySelector("body");
var ulist = document.createElement("ul");
function bulletpoint(){
var bulletpointEl = document.createElement("li");
bulletpointEl.textContent = "hello"
ulist.appendChild(bulletpointEl);
bodyEl.appendChild(ulist);
}
<button onclick="bulletpoint()">New bulletpoint</button>
back
The problem is that you're trying to give innerHTML an object instead of a string.
innerHTML accepts a string - https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML#Syntax
If you want to append an html element to the ulist you'll need to use the .appendChild() method same as you did with the bodyEl -
function bulletpoint(){
ulist.appendChild(bulletpointEl);
}
Hope this helps!

Adding new element to nested classes

I need to use JS to create a new element within specific nested classes in HTML. So in this example, I need to create a new span with the class of "paw-print" only where the "collies" class is nested within "dogs".
Here's what I have so far: https://jsfiddle.net/p50e228w/6/
The problem is that my current JS works on the first instance, but not on the other. I currently have document.getElementsByClassName set to "collies" but I need to target that class only when it's inside the parent "dogs" class.
What am I missing here?
var span = document.createElement("span");
span.className = "paw-print";
var wrap = document.getElementsByClassName("collies");
for(var i = 0; i < wrap.length; i++) {
wrap[i].appendChild(span);
}
I can use jQuery, but I've been using vanilla JS just because I'm such a noob and want to understand what my code is doing.
There are 2 issues with your code.
Positioning : The images are being given a absolute position, and they rest in the same position based on the page layout. So set relative positioning for the parent container.
CSS
.relative {
position: relative;
}
You need to append that to parent element which is collie here.
You can use querySelectorAll to find the nested relation ship that you are looking for.
var collies = document.querySelectorAll('.dogs .collies');
for (var i = 0; i < collies.length; i++) {
var span = document.createElement("span");
span.className = "paw-print";
collies[i].appendChild(span);
}
Fiddle
If you want to append to parent ( element with class 'dog')
$('.dogs .collies').each(function() // finds elements in the dom with parent element 'dog' and it's child element 'collies'
{
$(this) // 'this' would represent 'collies' element
.closest('.dogs') // .closest('.dogs') would get it's nearest occurence in the heirarchy ( basically it's parent )
.append($('<span/>', { class: 'paw-print'})); // create a dynamic span element and append to 'this'
});
If you want to append to child( element with class 'collies')
$('.dogs .collies').each(function()
{
$(this).append($('<span/>', { class: 'paw-print'}));
});
In addition to this, you also need to set position: relative as pointed out by Rob.
Example : https://jsfiddle.net/DinoMyte/1zxn8193/1/

javascript issue getElementById to modify CSS

I have an issue about getElementById.
Here is the part of the javascript code that causes a problem:
var elmt = document.getElementById("cardSlotsJoueur");
elmt.style.backgroundImage = "url('images/backcard.png')";
I wanted to modify this (Css) :
#cardSlotsJoueur div {
But it actually modifies #cardSlotsJoueur {
Could you help me to find a way to modify the first one with getElementById ?
Thanks !
If you only want to modify the first div within the element with id=cardSlotsJoueur, you can use this:
var elmt = document.getElementById("cardSlotsJoueur").getElementsByTagName("div")[0];
To target #cardSlotsJoueur div it's better to use querySelector method which would retrieve children div element of the #cardSlotsJoueur container:
var elmt = document.querySelector("#cardSlotsJoueur div");
If you expect multiple div elements under the #cardSlotsJoueur then you need to get them all first
var elmt = document.querySelectorAll("#cardSlotsJoueur div");
and then set backgroundImage to each in the for loop.
You need to find div elements within #cardSlotsJoueur:
var elmt = document.getElementById("cardSlotsJoueur");
var divs = elmt.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
divs[i].style.backgroundImage = "url('images/backcard.png')";
}
Probably the best way to do what you want is to use a class with the required styling and add it to the element. But as an alternative, you can add a rule to the last style sheet, e.g.
function addBackground() {
var sheets = document.styleSheets;
// If there are no style sheets, add one
if (!sheets.length) {
document.head.appendChild(document.createElement('style'));
}
// The sheets collection is live, if a new sheet was needed, it's automatically a member
sheets[sheets.length - 1].insertRule('#cardSlotsJoueur div{background-image:url("images/backcard.png")');
}
You can make it generic:
function addRule(ruleText) {
var sheets = document.styleSheets;
if (!sheets.length) {
document.head.appendChild(document.createElement('style'));
}
sheets[sheets.length - 1].insertRule(ruleText);
}
and call it like:
addRule('#cardSlotsJoueur div{background-image:url("images/backcard.png")');

document.getElementsByClassName('name') has a length of 0

I'm trying to retrieve all the elements by class name by using the method getElementsByClassName (no jQuery). Console.log shows the array of the elements, but when I try to get the length of the array, it returns 0.
Saw a previous post with a similar problem that provided a solution of making sure that the element exists. I took this into consideration and fire the function after DOMcreation.
What is going on here?
document.addEventListener("DOMContentLoaded", function(){
// Load current todo items from db
loadTodoItems();
var submitBtn = document.getElementById('submit-btn');
submitBtn.addEventListener('click', addItem);
var removeButton = document.getElementsByClassName("remove-btn");
console.log(removeButton);
console.log(removeButton.length);
}, false)
Another issue to note, is that I am noticing that in chrome Dev Tools when I look at the head tag, I'm seeing that some sort of angular code is being loaded in a script tag in the head, while the content that should be in my head tag are being loaded in the body. I am not using angular for my app.
Edit. Here is my HTML. It is in Jade:
Layout.jade:
doctype html
html(lang='en')
head
meta(charset="utf-8")
title To Do List
link(rel="stylesheet" href="main.css")
body
block content
script(src="main.js")
index.jade:
extends layout
block content
div.container
h1 Get-Er-Done!
form#todo-form(role="form" method="POST" action="/todo")
div.form-group
label(for="addToDo") Add To-Do item:
input#todoItemText.form-control(type="text")
button(type="submit")#submit-btn.btn.btn-default Add
ul#todo-list
Edit. The remove button is for the new todo item. This is called every time the user clicks add to post the new item.
function renderItems(items){
// Before rendering todo-items, clear the existing items in the list
var list = document.getElementById('todo-list');
while(list.hasChildNodes()){
list.removeChild(list.lastChild);
}
// Loop through items
for (var i = 0; i < items.length; i++) {
var el = document.createElement("li");
var removeBtn = document.createElement('button');
var btnText = document.createTextNode('Done');
removeBtn.appendChild(btnText);
removeBtn.className = 'remove-btn';
var newItemText = document.createTextNode(items[i].item);
el.appendChild(newItemText); // Add new content to new div
el.appendChild(removeBtn);
// To-Do list to append to
list.appendChild(el);
}
}
Length is 0 because when you run it there's no element with class remove-btn. You can see the items in the console because getElementsByClassName returns a live HTMLCollection, which is updated when new elements are added.
The problem is that you create the elements with that class in renderItems, which runs after you run getElementsByClassName.
You can fix it using
function renderItems(items){
var list = document.getElementById('todo-list');
while(list.hasChildNodes()){/* ... */}
for (var i = 0; i < items.length; i++) {/* ... */}
// Load current todo items from db
loadTodoItems();
var submitBtn = document.getElementById('submit-btn');
submitBtn.addEventListener('click', addItem);
var removeButton = document.getElementsByClassName("remove-btn");
console.log(removeButton);
console.log(removeButton.length);
}

How can I get an element's attribute from the parent's parent element's ID using JavaScript?

So I have the following HTML...
HTML:
<div id="col1">
<img src="1.jpg">
</div>
And I am implementing a HTML5 drag and drop feature where the inner html of col1 is changed for the dragged element's inner html - so basically the columns change their content.
I have another div (let's call that swap-text) where I want to change its text content depending on what image is presently inside col1.
This is why I want to figure out how I can obtain col1's img element's src attribute value through JavaScript so I can then write an if statement to change the content of the swap-text depending on which image is in col1.
I could add ID's to the img elements but then I still don't know how I would write the condition to check if say, img-id1 parent is col1.
Attempt(s):
var doc = document.getElementById("col1");
var children = null;
var imgEle;
//gets img node, but also got 1/2 text object(s)?
for (var i = 0; i < doc.childNodes.length; i++) {
children = doc.childNodes[i];
console.log(children);
}
//document.getElementById("img")
//children[1].getAttribute('src'); - cannot call method 'getAttribute' of undefined
//imgEle = doc.childNodes[0].getElementById('img'); - Object #<Text> has no method 'getElementById'
console.log(imgEle);
console.log(children);
This work fine pure javascript:
document.getElementById("col1").getElementsByTagName("img")[0].getAttribute("src");
var doc = document.getElementById("col1");
var img = document.getElementsByTagName('img')[0];
var imgParent = img.parentElement;
This is how you determine the elements parent/
I suggest you to use JQuery so you can simply use:
$("img").attr("id"); //Return the id of the img element
Check this:
var column = document.getElementById("col1");
var imgSrc = column.getElementsByTagName("img")[0].getAttribute("src");
Or just use the jQuery - it's simpler:
$('#col1 img').attr('src');
as you will only have one child node in col1 (the img), change the for loop.
var doc = document.getElementById("col1");
var children = null;
var imgEle;
//gets img node, but also got 1/2 text object(s)?
//for (var i = 0; i < doc.childNodes.length; i++) {
// children = doc.childNodes[i];
// console.log(children);
//}
childen = doc.childNodes[0];
// or children = doc.firstChild;
console.log(children);
//document.getElementById("img")
console.log(children.getAttribute('src')); - children is single object
//imgEle = doc.childNodes[0].getElementById('img'); - Object #<Text> has no method 'getElementById'
console.log(imgEle);
console.log(children);

Categories

Resources