Wrapping groups of lists within divs - javascript

What I'm trying to achieve:
<ul>
<li class="group4">
<ul class="group2">
<li class="first">stuff</li>
<li class="last">stuff</li>
</ul>
<ul class="group2">
<li class="first">stuff</li>
<li class="last">stuff</li>
</ul>
</li>
<li class="group4">
<ul class="group2">
<li class="first">stuff</li>
<li class="last">stuff</li>
</ul>
<ul class="group2">
<li class="first">stuff</li>
<li class="last">stuff</li>
</ul>
</li>
</ul>
What I'm currently equipped with:
<ul>
<li class="first">stuff</li>
<li class="last">stuff</li>
<li class="first">stuff</li>
<li class="last">stuff</li>
<li class="first">stuff</li>
<li class="last">stuff</li>
<li class="first">stuff</li>
<li class="last">stuff</li>
</ul>
Essentially this will make the list items appear in rows of 4, and rows of 2 in mobile view.
I can't hardcode this since the list items are retrieved via php.
Is there a script or something that can help me do this?

var $ul = $('ul').find('.first').each(function() {
$(this).next('.last').addBack().wrapAll('<ul class="group2"/>');
}).end();
while( $ul.children('.group2').length )
$ul.children('.group2').slice(0, 2).wrapAll('<li class="group4"/>');
http://jsfiddle.net/Twr9z/

Another way to do it if you don't know how many items will be in each group:
function relist() {
var list = $("ul.list");
var li = list.children("li");
var _li, _ul, item;
for (var i = 0 ; i < li.length; i++) {
if (i % 2 == 1) {
item = list.find("li:eq(" + i + "), li:eq(" + parseInt(i - 1) + ")");
_ul = $("<ul class='group_" + item.length + "'></ul>");
item.wrapAll(_ul);
}
}
var ul = list.find("ul");
for (var j = 0; j < ul.length; j++) {
if (j % 2 == 1) {
item = list.find("ul:eq(" + j + "), ul:eq(" + parseInt(j - 1) + ")");
_li = $("<li class='group_" + item.find('li').length + "'></li>");
item.wrapAll(_li);
}
}
}
$(function () { relist()});
The name of the classes will be group + the number of items under it.

this will do what you want, plus preserving the W3C validation:
$('.first').each(function(){
if(!$(this).data('wrapped')){
$(this).wrap('<ul class="group2"></ul>');
$(this).parent('.group2').append($(this).parent('.group2').nextAll('.last:first').clone()).html();
$(this).parent('.group2').nextAll('.last:first').remove();
$(this).parent('.group2').wrap('<li class="group4"></li>');
$(this).data('wrapped',true);
}
});

Related

How to get the anchor tag link and name using URL?

I have a URL
https://example.com/test/test1/test1_1/test1_2/
I am using the script below to get all the page names like breadcrumbs
var current = location.pathname.slice(1).split('/').join(' > ');
//Output: test > test1 > test1_1 > test1_2 >
Is there a way I can get along with the anchor tag? I have to set the click event. I have tried the code below
var current = location.pathname.slice(1).split('/').join(' > ');
$('#nav_menu-2').prepend('<div id="menu-breadcrumb"></div>');
var menuBreadcrumb = document.getElementById('menu-breadcrumb');
$('#nav_menu-2 li a').each(function() {
var $this = $('#nav_menu-2 li a');
var thismenuLi = $($this).parent().attr('id');
let thismenuText = $($this).text();
var shortText = jQuery.trim(thismenuText).substring(0, 15)
.split(" ").slice(0, -1).join(" ") + "...";
let mbcElement = '<a class="mbc-link-back" href="#" data-menu-item-id="' + thismenuLi + '">' + shortText + '</a>'
menuBreadcrumb.insertAdjacentHTML('beforeend', mbcElement);
});
<div class="secondary">
<div id="menu-breadcrumb"></div>
<nav class="nav" id="nav_menu-2">
<ul id="menu-inner-page-menu" class="menu">
<li id="menu-item-204" class="menu-item-has-children">Test
<ul class="sub-menu">
<li id="menu-item-304" class="menu-item-has-children">Test 1
<ul class="sub-menu">
<li id="menu-item-401" class="menu-item-has-children">Test 1.2
<ul class="sub-menu">
<li>Test 1.2.1</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

Hide li have span child withouth jquery

I need to hide li has a span child without jquery, how can i do it?
<ul class="select2-results__options" role="tree" id="select2-upsell_ids-results">
<li class="select2-results__option">first (#404)</li>
<li class="select2-results__option" >second (#496)</li>
<li class="select2-results__option">abc (#2482)</li>
<li class="select2-results__option">defg (#2484)<span class="description">Size: 47</span></li>
<li class="select2-results__option">hil (#2485)<span class="description">Size: 46,5</span></li>
</ul>
To be fair, #j08691's answer is perfectly valid and neat, and is absolutely not jQuery.
However, if #Geme doesn't like it, take a look at the code below. Trust me none of the code below contains any jQuery.
You can check if there is a span element inside each li by looping through the childNodes of each li.
If the childNode has a constructor of HTMLSpanElement, it is a span element.
var lists = document.getElementsByClassName('select2-results__option'); // NOT JQUERY
var i = 0;
var x = 0;
// NOT JQUERY AT ALL
for (; i < lists.length; i++)
for (; x < lists[i].childNodes.length; x++)
if (lists[i].childNodes[x].constructor === HTMLSpanElement){
lists[i].style.display = 'none';
break;
}
/* ALTERNATIVE */
// NOT JQUERY TOO
Array.prototype.forEach.call(lists, function(li){
var child = li.childNodes,
i = 0,
len = child.length;
for (; i < len; i++)
if (child[i].constructor === HTMLSpanElement)
li.style.display = 'none';
});
<ul class="select2-results__options" role="tree" id="select2-upsell_ids-results">
<li class="select2-results__option">first (#404)</li>
<li class="select2-results__option" >second (#496)</li>
<li class="select2-results__option">abc (#2482)</li>
<li class="select2-results__option">defg (#2484)<span class="description">Size: 47</span></li>
<li class="select2-results__option">hil (#2485)<span class="description">Size: 46,5</span></li>
</ul>
You can use document.querySelectorAll('li > span') to select the elements and then loop to hide them.
var items = document.querySelectorAll('li > span')
for (var item of items) {
item.parentNode.style.display = 'none';
}
<ul class="select2-results__options" role="tree" id="select2-upsell_ids-results">
<li class="select2-results__option">first (#404)</li>
<li class="select2-results__option">second (#496)</li>
<li class="select2-results__option">abc (#2482)</li>
<li class="select2-results__option">defg (#2484)<span class="description">Size: 47</span></li>
<li class="select2-results__option">hil (#2485)<span class="description">Size: 46,5</span></li>
</ul>

Creating an Array of Id's

I have an array, var players = ['', '', '', '', '', ''];. Now I want that array to contain 6 items from a list:
<ul id="Available Players">
<li id="node7">Player A</li>
<li id="node8">Player B</li>
<li id="node9">Player C</li>
<li id="node10">Player D</li>
<li id="node11">Player E</li>
<li id="node12">Player F</li>
</ul>
Now, I want the array to look kinda like this:
var players = [.node7, .node8, .node9, .node10, .node11, .node12];. Also, if I were to create a new array called round1, can I get the values of the first 4 values from the players array? It should look somewhat similar to this: var round1 = [players[0], players[1], players[2], players[3]];
So how can I do all of this?
You could get the node of the parent id, and then all list elements and extract the id.
var nodes = document.getElementById('Available Players').getElementsByTagName('li'),
ids = Array.prototype.map.call(nodes, function(a) {
return '.' + a.getAttribute('id');
}),
round1 = ids.slice(0, 4);
console.log(ids);
console.log(round1);
<ul id="Available Players">
<li id="node7">Player A</li>
<li id="node8">Player B</li>
<li id="node9">Player C</li>
<li id="node10">Player D</li>
<li id="node11">Player E</li>
<li id="node12">Player F</li>
</ul>
You can use following approach.
var parent = document.getElementById('Available Players'), //get the 'ul' element
round1 = [], // create 'round1' array
players = Array.from(parent.children).map(function(v){ //get all the 'li' elements
return "." + v.id; //return 'id' attribute of every 'li' element
});
for (var i = 0; i < 4; i++){ // push only four first elements from 'players' array
round1.push(players[i]); // to the 'round1' array
}
console.log(players); //reveal the results
console.log(round1);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<ul id="Available Players">
<li id="node7">Player A</li>
<li id="node8">Player B</li>
<li id="node9">Player C</li>
<li id="node10">Player D</li>
<li id="node11">Player E</li>
<li id="node12">Player F</li>
</ul>
HTML:
<ul id="available-players">
<li id="node7">Player A</li>
<li id="node8">Player B</li>
<li id="node9">Player C</li>
<li id="node10">Player D</li>
<li id="node11">Player E</li>
<li id="node12">Player F</li>
</ul>
Javascript:
var players = [];
var li = document.querySelectorAll('#available-players li');
for (var i = 0; i < li.length; i++) {
players.push(li[i].getAttribute('id'));
}
You can use the element.children property to get a list of every li inside your ul, and then use Array#map to get their id. Then, use players.slice(0, 4) to get your round1 players.
It is unclear from your question whether you want players to hold the names of each player, the li elements themselves, or the id of each li element. Here is how you would get all three:
var nodes = [].slice.call(
document.getElementById('Available Players').children
)
function prop (o) { return o[this] }
var nodeIds = nodes.map(prop, 'id')
var playerNames = nodes.map(prop, 'textContent')
console.log(nodes)
console.log(nodeIds)
console.log(playerNames)
var players = nodeIds // or whichever array above you meant
var round1 = players.slice(0, 4)
console.log(round1)
.as-console-wrapper { min-height: 100vh; }
<ul id="Available Players">
<li id="node7">Player A</li>
<li id="node8">Player B</li>
<li id="node9">Player C</li>
<li id="node10">Player D</li>
<li id="node11">Player E</li>
<li id="node12">Player F</li>
</ul>
var players=[];
var round1=[];
var items=$("#Available_Players li")
items.each(function(){
console.log($(this));
players.push('.'+$(this)[0].id);
});
round1 = players.slice(0, 4);
console.log(players);
console.log(round1);
https://plnkr.co/edit/PxvzROhFotj0p4UKMCC4?p=preview

compare the class name and sort the item list

I want to
1) compare the class name of the list
2) fix the list item in center which has active-slider node_id
3) sort the list with class name
I have the list item 233,299,68.
consider 233 node_id is active and I want to place it in center(working).
my new list is 299,233,69. I want to sort the list ordered as 69,233,299
setTimeout(function(){
console.log('timeout');
var node_id = $('.flex-active-slide .node_id').text();
console.log('node_id', node_id);
$('.thumbnailIcon').each(function(index, item){
console.log(item);
$(item).find('.'+node_id).insertAfter($(item).find('li:eq(2)'));
});
},1000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<li class="parent flex-active-slide">
<div class="node_id"><span>233</span></div>
<ul class="thumbnailIcon">
<li>left</li>
<li class="233">1 233</li>
<li class="299">3 299</li>
<li class="69">2 69</li>
<li>right</li>
</ul>
</li>
<li class="parent">
<div class="node_id"><span>222</span></div>
<ul class="thumbnailIcon">
<li>left</li>
<li class="233">1</li>
<li class="299">3 299</li>
<li class="69">2</li>
<li>right</li>
</ul>
</li>
<a href="#" class="flex-next">click<a>
<li class="parent">
<div class="node_id"><span>333</span></div>
<ul class="thumbnailIcon">
<li>left</li>
<li class="233">1</li>
<li class="299">3 299</li>
<li class="69">2</li>
<li>right</li>
</ul>
</li>
As far as my understanding I think you want to sort li items based on the class inside child of ul which is child of li having class parent if it has class flex-active-slide
Plunker Link for demonstration
So there is code
$(document).ready(function() {
$('li').each(function() {
if ($(this).hasClass("flex-active-slide")) {
var lisElems = []; //empty array
var childUl = $(this).children().eq(1).html()
$(childUl).each(function() {
if ($(this).attr('class')) { //select all li having class
var classNum = $(this).attr('class');
//pushing inside array key as class and html
lisElems.push({
"class": classNum,
"html": $(this).html()
})
}
})
lisElems.sort(function(a, b) {
return a.class - b.class;
});
$(this).children().eq(1).remove() //removing child ul of li
var newlis = "<li>left</li> ";//creating new li
for (var i = 0; i < lisElems.length; i++) {
newlis += '<li class="' + lisElems[i].class + '">' + lisElems[i].html + '</li>'
}
newlis += '<li>right</li>'
$(this).children().append("<ul>" + newlis + "<ul>") //appending in parent li
}
})
})

Jquery add css class to parent <ul> elements

I'm new on jquery so if this is a noob question sorry for all.
I have a nested category tree and html Looks like;
<ul class="product-cat-list">
<li data-id="1287">PRODUCTS - 1 (MAIN CATEGORY)
<ul>
<li data-id="1200">PRODUCTS - 1.1</li>
<li data-id="1203">PRODUCTS - 1.2
<ul>
<li data-id="1204">PRODUCTS - 1.2.1</li>
<li data-id="1205">PRODUCTS - 1.2.2</li>
</ul>
</li>
</ul>
</li>
<li data-id="1288">PRODUCTS - 2 (MAIN CATEGORY)
<ul>
<li data-id="1300">PRODUCTS - 2.1</li>
<li data-id="1303">PRODUCTS - 2.2
<ul>
<li data-id="1304">PRODUCTS - 2.2.1</li>
<li data-id="1305">PRODUCTS - 2.2.2</li>
</ul>
</li>
</ul>
</li>
</ul>
I'm getting category id with PHP's $_GET super global ($_GET['category']).
If i'm on PRODUCTS - 2.2.2 my url looks like products.php?category=1305
Question: How can i add (for. eg.) active css class only it's parent uls ?
So result must be looks like;
<ul class="product-cat-list">
<li data-id="1287">PRODUCTS - 1 (MAIN CATEGORY)
<ul>
<li data-id="1200">PRODUCTS - 1.1</li>
<li data-id="1203">PRODUCTS - 1.2
<ul>
<li data-id="1204">PRODUCTS - 1.2.1</li>
<li data-id="1205">PRODUCTS - 1.2.2</li>
</ul>
</li>
</ul>
</li>
<li data-id="1288">PRODUCTS - 2 (MAIN CATEGORY)
<ul class="active">
<li data-id="1300">PRODUCTS - 2.1</li>
<li data-id="1303">PRODUCTS - 2.2
<ul class="active">
<li data-id="1304">PRODUCTS - 2.2.1</li>
<li data-id="1305">PRODUCTS - 2.2.2</li>
</ul>
</li>
</ul>
</li>
</ul>
I try to fetch URL parameter like above regex and it works. But i can not add active css class on uls.
Any Help greatly appricated.
// Getting URL Parameter
$.urlParam = function(name){
var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(window.location.href);
return results[1] || 0;
}
// Products sidebar
var dataid = $('#product-cat-list > li').data('id');
if( dataid == $.urlParam('category')){
find($('#product-cat-list > ul').addClass('active'))
};
Select the li by data attribute and use parents() to get the uls.
function getParameterByName(name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(location.search);
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
$( function() {
var id = getParameterByName("category"); //1035;
var li = $("li[data-id=" + id + "]");
li.parents("ul").addClass("active");
});
If you want to exclude the first ul, than use not()
li.parents("ul").not(".product-cat-list").addClass("active");
Try this:
var id = $.urlParam('category');
var active = $('[data-id=' + id + ']');
active.parents('ul:not(.product-cat-list)').addClass('active');
jsFiddle Demo
You can use a combination of selecting based on the data-id and parentsUntil to do this.
var dataid = 1305;//$.urlParam('category')
$('li[data-id='+dataid+']')//find elements with data-id equal to 1305
.parentsUntil('.product-cat-list')//find element's parents prior to cat-list
.find('ul')//only take the ul elements of the parents
.addClass('active');//add class active to them
.active, .active a{
color:red;
text-decoration:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="product-cat-list">
<li data-id="1287">PRODUCTS - 1 (MAIN CATEGORY)
<ul>
<li data-id="1200">PRODUCTS - 1.1</li>
<li data-id="1203">PRODUCTS - 1.2
<ul>
<li data-id="1204">PRODUCTS - 1.2.1</li>
<li data-id="1205">PRODUCTS - 1.2.2</li>
</ul>
</li>
</ul>
</li>
<li data-id="1288">PRODUCTS - 2 (MAIN CATEGORY)
<ul>
<li data-id="1300">PRODUCTS - 2.1</li>
<li data-id="1303">PRODUCTS - 2.2
<ul>
<li data-id="1304">PRODUCTS - 2.2.1</li>
<li data-id="1305">PRODUCTS - 2.2.2</li>
</ul>
</li>
</ul>
</li>
</ul>
If you only want the first UL in #product-cat-list the It should probably be:
if( dataid == $.urlParam('category')){
$('#product-cat-list > ul:first).addClass('active');
});
If you want the first UL in every LI, it would be:
if( dataid == $.urlParam('category')){
$('li > ul:first).addClass('active');
});
And every UL would be:
if( dataid == $.urlParam('category')){
$('li > ul).addClass('active');
});

Categories

Resources