I have made a script with jQuery. The script split a list of li's, to more ul's. When the list is moer than 10 li items the list must be split in more ul's.
I have made the script in this post.
But the script is not working. What I did wrong here.
The script is for a submenu in the navigation. When the navigation li items are more than 4 than the ul of li items must be splitted in two ul's. How can I fix this script. Thanks!
submenu();
function submenu() {
$(".submenu").each(function () {
if($("li", this).length > 4){
$(this).closest(".submenu").addClass("width-2")
var submenu = $(this).closest(".submenu");
var $bigList = $(this), group;
while((group = $bigList.find('li:lt(8)').remove()).length) {
$('<ul/>').append(group).appendTo(submenu);
}
}
if($("li", this).length > 10){
$(this).closest(".submenu").addClass("width-3")
}
});
}
I'm not entirely sure I understand what you're trying to do, but this code will split each submenu UL into more submenus of the specified size while keeping all items in the original DOM order:
function splitSubmenu(maxNumItems) {
$(".submenu").each(function () {
// get all child li tags
var list$ = $(this).children("li");
var num, nextAfter$, after$ = $(this);
// as long as the current list it too long, loop
while (list$.length > maxNumItems) {
// decide how many to remove this iteration
num = Math.min(maxNumItems, list$.length - maxNumItems);
// create new UL tag, append num items to it
// and insert it into the DOM
nextAfter$ = $('<ul class="submenu">')
.append(list$.slice(maxNumItems, maxNumItems + num))
.insertAfter(after$);
// update insertion point for next loop iteration
after$ = nextAfter$;
// remove the items we just took out from the current jQuery object
list$ = list$.filter(function(index) {
return(index < maxNumItems || index >= 2 * maxNumItems);
});
}
});
}
splitSubmenu(4);
You can see it work here: http://jsfiddle.net/jfriend00/VMjvQ/.
I did not understand what you were trying to do with the additional classes so that part is not included.
Related
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.
So I wanted to add items to a list by typing the items in an with a beside that returns the value, adds the value to the list. Which I have done... But I want to limit the amount of times I add items the list. Say I want to limit it to 5 times only. So I can basically add 5 items to a list... And that's all... Now...How do I do that?
Thx for response.
<script type="text/javascript">
var input = document.getElementById('username');
function checkLength() {
var node = document.createElement('li');
var nodeText = document.createTextNode(input.value);
var ul = document.getElementsByTagName('ul')[0];
node.appendChild(nodeText);
ul.appendChild(node);
input.value = "";
node.setAttribute('style', "color:green; text-transform:uppercase;");
}
}
</script>
You can get the number of children of a node:
var ul = document.getElementsByTagName('ul')[0];
if (ul.childNodes.length < 5) {
ul.appendChild(node);
}
Note that this counts all the child nodes not just li elements so if you have text nodes in there which I don't think you will they will be included in this count.
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
I have the following javascript function that I call on body onload. But I want to change the javascript function into jQuery statements and call them directly inside of the document.ready() function.
function ChangeSomeStyles(){
//hide the last two links of TopNav
var container = document.getElementsByTagName("ul")[0];
var lastchild = container.lastChild;
var secondlastchild = container.childNodes[container.childNodes.length-2];
lastchild.style.display = 'none';
secondlastchild.style.display = 'none';
//Show TopNav as it is hidden by default in CSS
document.getElementById('WrapperTopNav').style.display = 'block';
//if homepage, set Footer width to 960
if ((document.URL === "http://testsiteqa/Pages/Default.aspx") || (document.URL === "http://testsitetf/Pages/Default.aspx") || (document.URL === "http://testsite/Pages/Default.aspx")){
document.getElementById('Footer').style.width = '960px';
}
}
======================================================>
$(document).ready(){
$('ul li:last-child').hide();
//how do I get the second last li?
$('#WrapperTopNav').css('display','block');
if ((document.URL === "http://testsiteqa/Pages/Default.aspx") || (document.URL === "http://testsitetf/Pages/Default.aspx") || (document.URL === "http://testsite/Pages/Default.aspx")){
$('#Footer').css('width','960px');
}
});
How do I get the second last menu item to hide? Is the above conversion look about right?
You can achieve that by using .eq()
Try,
var cache = $('ul li');
cache.eq(cache.length-1).hide(); //last one
cache.eq(cache.length-2).hide(); //second one from the last
or you can use .prev() to get the previous sibling of the last li element,
var cache = $('ul li:last-child').hide(); //last one
cache.prev().hide(); //second one from the last
Conceptual DEMO
Or as A.wolf suggested we can access the collection reversely by providing index in negative,
var cache = $('ul li');
cache.eq(-1).hide(); //last one
cache.eq(-2).hide(); //second one from the last
I would use this:
$('ul > li:gt(-3)').hide();
That will select the last two li that are direct descendants of the ul and hide them.
I'm having trouble limiting a list to only add unique items this is what I have so far
function addTab(tabName)
{
var tabList=$("#pageContent ul").find("li").text();
if($("#pageContent ul li:contains('"+tabList+"')").length<1)
{
$("#pageContent ul").append("<li>"+tabName+"</li>");
}
else
{
}
}
but it doesn't work I'm not sure what's wrong and from what I can tell this should be the best way to do it.
I was going to use jQuery UI tabs but my layout uses floats and messes with the tabs widget
You are getting text content of all li elements and then try to select li elements that contain that specific text, this doesn't make sense, you don't even use tabName in your filtering logic, try the following using filter method.
function addTab(tabName) {
var $e = $("#pageContent ul");
var n = $e.find("li").filter(function(){
var t = this.textContent || this.innerText;
return t === tabName
}).length;
if (n === 0) {
$e.append("<li>"+tabName+"</li>");
} else {
// ...
}
}