How to select nested UL element without class in JavaScript - javascript

In my Joomla template I've created a vertical menu including a dropdown which should "push" the elements below away when opening a submenu onclick. Somehow I don't get it to work..
I am trying to grab the UL inside an LI, but how can I do this in JavaScript without the UL's having a class or ID.
I've come to this yet:
function getElements(){
var listitems = {};
for(var i = 0; i< arguments.length; i++){
var id = arguments[i];
var item = navigation.getElementsByTagName("li");
if (item == null)
throw new Error ("No list items found.");
listitems[id] = item;
}
return listitems;
}
Now I should get something like: (I now the following code is impossible, but it describes what I am trying)
var nav = document.getElementById("navigation");
var nestedList = nav ul li ul;
nestedList.onclick(nav ul li ul.style = "display: block";);
The HTML looks like:
<div id="navigation">
<ul>
<li class="parent">
<ul><li></li></ul>
</li>
</ul>
</div>
The CSS looks like:
#navigation ul li ul{display: none;}
Now I want it to display: block when clicking on .parent
Thanks!

Since you already have MooTools included in your page, something like this should work (not a MooTools expert here):
$('#navigation li.parent').addEvent('click', function () {
$('#navigation li.parent ul li ul').setStyle('display', 'block');
});
Old post:
Pure JS (this is not the full code, you have to loop over the elements several times for adding the click listener and applying the styles):
var listItems = document.querySelectorAll("nav ul li ul");
var count = listItems.length;
for (var i=0; i<count; i++) {
var item = listItems.get(i);
item.style.display = "block";
}

Of course the easiest is using jQuery or some other library.
To do it with pure JavaScript for modern browsers, use JS querySelector.
Otherwise you will spend a lot of time in this.

Related

How to separate Li items when selecting multiple options in a variable product?

I am creating a feature on a Woocommerce variable product page where a user can select an option and that option gets added to a summary of items selected. I have multiple variations on the page so I have tried to get the innerHTML of every selected target and tried to add it to the UL by dynamically creating an li and adding to it. But at the moment only one li gets created and it adds all the options selected to it. Is there a way to separate each variation into multiple li's so that it adds the selected option to its own individual li? This is what I have so far.example here. It would be greatly appreciated if I am pointed in the right direction. Thanks a lot :)
var wrappers = document.querySelectorAll('.rtwpvs-terms-wrapper');
var summary = document.querySelector('.selection-summary');
var list = document.querySelector('.selected-items');
var li = document.createElement("li");
wrappers[0].classList.remove('opacity');
let increment = 0;
wrappers.forEach((item, sel) => {
item.addEventListener('click', (e) => {
summary.style.display = 'block';
// Create li items and assign on click innerhtml
li.appendChild(document.createTextNode(e.target.innerHTML));
list.appendChild(li);
increment++;
for(var i = 0; i < wrappers.length; i++) {
wrappers[increment].classList.remove('opacity');
}
})
})
You're appending to the same li (which you created at the top level) at every iteration of your loop. You should be creating a new <li> for each item, and append said <li> to your list, like so:
// Create li items and assign on click innerhtml
const li = document.createElement("li");
li.innerHTML = e.target.innerHTML;
list.appendChild(li);
You don't need the var li = document.createElement("li"); at the top level anymore.

For loop only loops 1 time - JavaScript

Hi i am trying to make a for loop which will automatically add "dots" depending on how many images there are, i use the myArrImg.length but it only outputs a li with a class of dots once even tho it should do it four times? can anyone help me :)
var myArrImg = ['img/erftdgdf33.jpg','img/iajdi89.jpg','img/isdkfj01.jpg','img/wergf43.jpg'];
function dotsAuto(){
var test = document.getElementById('test');
var li = document.createElement('li');
li.className = 'dots';
for (i = 0; i < myArrImg.length; i++) {
test.appendChild(li);
}
}
dotsAuto();
Your problem is not what you think. The loop is operating the right number of times, but it is not doing what you intend.
The problem is that you only ever create one li element. You then repeatedly insert that same element. So the browser thinks you are doing this:
Create an li element. Give it a className. Now, start looping through the myArrImg array. On the first time, insert that li element. On the second time, insert that li element. On the third time, insert that li element. And so on.
You need to create new li elements each time, because any element can only exist once in the document. Essentially, you keep removing the element from the document and putting it back in the same place To create new elements each time, create the li within the loop:
var li;
for (i = 0; i < myArrImg.length; i++) {
li = document.createElement('li');
li.className = 'dots';
test.appendChild(li);
}
Here I created an ul since JSFiddle doesn't allow to manipulate document, but the process is the same
var myArrImg = ['img/erftdgdf33.jpg','img/iajdi89.jpg','img/isdkfj01.jpg','img/wergf43.jpg'];
function dotsAuto(){
var test = document.getElementById('test');
for (i = 0; i < myArrImg.length; i++) {
var li = document.createElement('li');
li.className = 'dots';
li.innerHTML = myArrImg[i];
test.appendChild(li);
}
}
dotsAuto();
<ul id="test">
</ul>
Basically you create ONE li for EACH loop cycle, and then append it to the list

Adding dynamically <li> in javascript

I'm trying to add elements dynamically in an ul with ajax and my current code is this in ajax method:
var ul = document.getElementById("menu");
var li = document.createElement("li");
li.appendChild(document.createTextNode(array[i]));
ul.appendChild(li);
But it creates "standard" li elements, i want to create them in this type:
<li style="cursor:pointer;"><a onclick="javascript:$('#cod').val(array[i])">array[i]</a></li>
How can i do this?
[EDIT]
What i want to create is THIS (you can see that it appears a "shadow" that signify it is selectable
But jvascript creates this type of OPTIONS,
now you can see that the options doesn't got that "shadow".
How i understand content for this <%=IDAnag%> insert your back end. And when you click on link this content has already been generated. Maybe you can try something like that:
function AppendLi(val){
var ul = document.getElementById("menu");
var li = document.createElement("li");
li.innerHTML= val;
ul.appendChild(li);
}
<li style="cursor:pointer;">
<a onclick="AppendLi(this.textContent)">
<%=IDAnag%>
</a>
</li>
<ul id="menu"></ul>
But I do not know how you have built the your backend. maybe best way add this event on backend side?
I solved the problem by myself, if someone needed here is the code:
var ul = document.getElementById("menu");
var li = document.createElement("li");
$("li").each(function()
{
var $li = $(this);
$li.css("cursor","pointer");
});
var a = document.createElement("a");
var l = array[i];
a.textContent = array[i];
a.addEventListener("click",function(){
$("#cod").val(array[i]);
});
li.appendChild(a);
ul.appendChild(li);

Get an element id and generic element in JavaScript

I have a CSS selector #menu li {background-color: red;}.
I want to access its attributes in JavaScript. It's important that I need to access both #menu and li since #menu alone has different attributes. It seems like getElementById(menu li), QuerySelector and getComputedStyle are not working in this case.
Is there any other way to achieve that or am I missing something here?
You should use jQuery for this, here the easy code example
//html
<div id="menu" data-number="123" >
</div>
//jquery
var menu = $('#menu').attr('data-number');
console.log(menu);
//print 123
jquery version
https://jsfiddle.net/pn52uvw1/
$(".button_1").click(function(){
alert($("#menu").attr("data-item-id"));
})
$(".button_2").click(function(){
alert($("#menu li").attr("data-item-id"));
})
non jquery version
https://jsfiddle.net/pn52uvw1/2/
window.firstFunction = function(){
var target = document.getElementById("menu");
alert(target.getAttribute('data-item-id'));
}
window.secondFunction = function(){
var target = document.getElementById("menu").children[0];
alert(target.getAttribute('data-item-id'));
}
but you will need to get rid of that [0] index probably, and use a for or something for multiple li items
If you want to get that css rule's property, you can do like this:
function getStyleFromSelector(selector, styleName) {
// Get all style elements
var styles = document.styleSheets;
var styleIndex = 0, styleCount = styles.length;
var rules, ruleCount, ruleIndex;
// Iterate though styles
for (styleIndex = 0; styleIndex < styleCount; ++styleIndex) {
// Get the css rules under the style.
rules = styles[styleIndex].rules;
ruleCount = rules.length;
for (ruleIndex = 0; ruleIndex < ruleCount; ++ruleIndex) {
// Check if the selector match the one we want
if (rules[ruleIndex].selectorText === selector) {
return styleName ?
rules[ruleIndex].style.getPropertyValue(styleName) : rules[ruleIndex];
}
}
}
}
var div = document.getElementById("results");
var result = getStyleFromSelector('#menu li');
console.log(result);
div.innerHTML = 'background-color is : ' + result.style.backgroundColor;
console.log(getStyleFromSelector('#menu li', 'background-color'));
#menu li {background-color: red;}
<div id="results"></div>
You can try it without additional Libraries with the following
var len = document.querySelectorAll("#menu li").length;
for(i = 0; i<len; i++)
document.querySelectorAll("#menu li")[i].style.backgroundColor="blue";
I also made you (a not very beautiful) jsfiddle
https://jsfiddle.net/gmeewsmz/

Parse header to unordered list IN PLAIN JS

A part of my script
function lab()
{
var h1 = getElementsByTagName("H1");
var li = document.createElement("LI");
var ul = document.createElement("UL");
li.innerHTML = h1.innerHTML;
h1[0].parentNode.replaceChild(ul,h1[0]);
h1[0].parentNode.appendChild(li);
}
doesn't do anything.
The whole task is to change a combination of headers to unordered list using only plain js with DOM. There has already been a question here but unfortunately the solution provided there was in jQuery, not in plain JS.
Could you please give me a hint?
I'm not sure what exactly you need, perhaps something like this:
function lab() {
var h1 = document.getElementsByTagName('h1'), // Create a collection of H1 elements
ul = document.createElement('ul'), // Create a new UL element
parent = h1[0].parentNode, // Store the parent node of the first H1
n, len, li; // Declare some variables to use later
for (n = 0, len = h1.length; n < len; n++) { // Iterate through H1 elements
li = document.createElement('li'); // Create a new LI element
li.appendChild(h1[0]); // Move a H1 to LI (Live collection, 0 instead of n as index)
// Or switch the line above to the next two lines, if you want to remove the H1 and list the content only
// li.innerHTML = h1[0].innerHTML;
// h1[0].parentElement.removeChild(h1[0]);// If you want to preserve H1s, remove this line
ul.appendChild(li); // Append the newly-created LI to the UL
}
parent.appendChild(ul); // Append the UL to the parent
}
This collects all H1 elements to an unordered list, which is appended to the parent element of the first H1.
A live demo at jsFiddle.

Categories