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');
});
Related
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>
I want to be able to compare two lists using data attribute in either Javascript or jQuery. I can't find an example of this anywhere and don't know how to go about it.
The first list is static and the second list is sortable. Once the user sorts the lists in the right order, [data-compare 1 to 4] in both lists, they click a button to check if they got the matches correct.
There are examples of setting the correct order 1 to X in a single list, but, none I can find to compare two lists.
The basic HTML:
<ul>
<li data-compare="1">Bananas</li>
<li data-compare="2">tomatoes</li>
<li data-compare="3">carrots</li>
<li data-compare="4">dates</li>
</ul>
<ul>
<li data-compare="1">Tree</li>
<li data-compare="4">Palm tree</li>
<li data-compare="2">Bush</li>
<li data-compare="3">In the ground</li>
</ul>
If an ordered list has data-compare attributes with the values 1, 2, 3, 4, you can just check if the the value of the data-compare is identical to the list item's index + 1:
function checkOrdered(list) {
return Array.from(list).every((item, i) => item.getAttribute('data-compare') == (i + 1));
}
console.log(checkOrdered(document.querySelectorAll('#list1 > li')));
console.log(checkOrdered(document.querySelectorAll('#list2 > li')));
<ul id="list1">
<li data-compare="1">Tree</li>
<li data-compare="4">Palm tree</li>
<li data-compare="2">Bush</li>
<li data-compare="3">In the ground</li>
</ul>
<ul id="list2">
<li data-compare="1">Tree</li>
<li data-compare="2">Bush</li>
<li data-compare="3">In the ground</li>
<li data-compare="4">Palm tree</li>
</ul>
You can do the same thing using another list as the compare basis:
function checkOrdered(list1, list2) {
return Array.from(list1).every((item, i) =>
item.getAttribute('data-compare') === list2[i].getAttribute('data-compare'));
}
const src = document.querySelectorAll('#src > li');
const target1 = document.querySelectorAll('#target1 > li');
const target2 = document.querySelectorAll('#target2 > li');
console.log(checkOrdered(src, target1));
console.log(checkOrdered(src, target2));
<ul id="src">
<li data-compare="1">Bananas</li>
<li data-compare="2">tomatoes</li>
<li data-compare="3">carrots</li>
<li data-compare="4">dates</li>
</ul>
<ul id="target1">
<li data-compare="1">Tree</li>
<li data-compare="4">Palm tree</li>
<li data-compare="2">Bush</li>
<li data-compare="3">In the ground</li>
</ul>
<ul id="target2">
<li data-compare="1">Tree</li>
<li data-compare="2">Bush</li>
<li data-compare="3">In the ground</li>
<li data-compare="4">Palm tree</li>
</ul>
You can first get two arrays with data-compare values and then use every method to check if each element is the same in both arrays.
const getData = arr => {
return arr.map(function() {
return $(this).attr('data-compare')
}).get();
}
const l1 = getData($('ul:nth-of-type(1) li'))
const l2 = getData($('ul:nth-of-type(2) li'))
const check = l1.every((e, i) => l2[i] == e);
console.log(check)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li data-compare="1">Bananas</li>
<li data-compare="2">tomatoes</li>
<li data-compare="3">carrots</li>
<li data-compare="4">dates</li>
</ul>
<ul>
<li data-compare="1">Tree</li>
<li data-compare="4">Palm tree</li>
<li data-compare="2">Bush</li>
<li data-compare="3">In the ground</li>
</ul>
I have this HTML:
<h5>something</h5>
<ul>
<li class="name">John</li>
<li class="age">21</li>
</ul>
<h5>specific text</h5>
<ul>
<li class="name">Peter</li>
<li class="age">19</li>
</ul>
<h5>something else</h5>
<ul>
<li class="name">Ali</li>
<li class="age">62</li>
</ul>
I want to select this part:
<h5>specific text</h5>
<ul>
<li class="name">Peter</li>
<li class="age">19</li>
</ul>
The logic is the content of <h5> tag. I want the one which is specific text. Actually expected result is an array of both that name and that age. Some thing like this: var res = ['Peter', 19];.
But my code selects all those <ul>s:
$('ul').map(function (){
var res = [$(this).find('li.name').text(), $(this).find('li.age').text()];
});
How can I fix it?
You can use :contains() to find the H5 that contains the specific string you want. Then use .next() to get that ul associated with the h5
$("h5:contains('specific text')").next('ul').map(function (){
var res = [$(this).find('li.name').text(), $(this).find('li.age').text()];
console.log(res)
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h5>something</h5>
<ul>
<li class="name">John</li>
<li class="age">21</li>
</ul>
<h5>specific text</h5>
<ul>
<li class="name">Peter</li>
<li class="age">19</li>
</ul>
<h5>something else</h5>
<ul>
<li class="name">Ali</li>
<li class="age">62</li>
</ul>
Jquery script for getting data from ul list :
$('ul').map(function (){
var res = [$(this).find('li.name').text(), $(this).find('li.age').text()];
// console.log(res);
});
var htmVal = '';
$('h5').each(function(index){
htmVal = $(this).html();
if(htmVal == 'something else'){
var detail ={name:$(this).next().find('li.name').html(),age:$(this).next().find('li.age').html()};
console.log(detail);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h5>something</h5>
<ul>
<li class="name">John</li>
<li class="age">21</li>
</ul>
<h5>specific text</h5>
<ul>
<li class="name">Peter</li>
<li class="age">19</li>
</ul>
<h5>something else</h5>
<ul>
<li class="name">Ali</li>
<li class="age">62</li>
</ul>
How can convert below DOM to JSON array which will have many more leafs in thefuture . I have tried a lot but didn't got any solution. I found this but it is not possible in my case.
HTML Code
<ul id="org1">
<li>
Main
<ul data-self="1">
<li data-self="2" data-parent="1">A
<ul data-self="2">
<li data-self="5" data-parent="2">A1</li>
<li data-self="6" data-parent="2">A2</li>
<li data-self="7" data-parent="2">A3</li>
<li data-self="8" data-parent="2">A4</li>
<li data-self="9" data-parent="2">A5</li>
<li data-self="10" data-parent="2">A6</li>
</ul>
</li>
<li data-self="3" data-parent="1">B
<ul data-self="3">
<li data-self="11" data-parent="3">B1</li>
<li data-self="12" data-parent="3">B2</li>
<li data-self="13" data-parent="3">B3</li>
<li data-self="14" data-parent="3">B4</li>
</ul>
</li>
</ul>
</li>
</ul>
JSON Required is
{
1:{
2:{5,6,7,8,9,10},
3:{11,12,13,14}
}
}
Script
function recursive(dis)
{
$(this).find(' > ul ').each(function(){
params[$(this).attr('data-self')]=[];
var i=0;
$(this).find('li').each(function(){
if($(this).has('ul'))
{
params[$(this).attr('data-parent')][i++]=rec(this);
}else
{
params[$(this).attr('data-parent')][i++]=$(this).attr('data-self');
}
});
});
}
recursive('#org1');
console.log(params);
I would prefer something like the following. The 2 changes in the HTML you need to make are:
1) Add a class to your ul such as <ul data-self="2" class="nodes">. 2) Add a class to the wrapper ul such as <ul data-self="1" class="parent">.
var json = {};
$("#org1").find("ul.parent").each(function() {
var $this = $(this);
json[$this.data("self")] = {};
var $nodes = $this.find("ul.nodes");
$nodes.each(function() {
var children = $(this).find("li").map(function() {
return $(this).data("self")
}).get();
json[$this.data("self")][$(this).data("self")] = children;
});
});
alert (JSON.stringify(json));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="org1">
<li>
Main
<ul data-self="1" class="parent">
<li data-self="2" data-parent="1">A
<ul data-self="2" class="nodes">
<li data-self="5" data-parent="2">A1</li>
<li data-self="6" data-parent="2">A2</li>
<li data-self="7" data-parent="2">A3</li>
<li data-self="8" data-parent="2">A4</li>
<li data-self="9" data-parent="2">A5</li>
<li data-self="10" data-parent="2">A6</li>
</ul>
</li>
<li data-self="3" data-parent="1">B
<ul data-self="3" class="nodes">
<li data-self="11" data-parent="3">B1</li>
<li data-self="12" data-parent="3">B2</li>
<li data-self="13" data-parent="3">B3</li>
<li data-self="14" data-parent="3">B4</li>
</ul>
</li>
</ul>
</li>
</ul>
Here is my code :
<ul>
<li class="active">
<div class="course_video_heading"><span class="minus"></span> Introduction <div class="course_duration" align="right">1m 21s</div></div>
<ul>
<li class="course_video viewed">
Welcome <div class="course_duration" align="right">1m 21s</div>
</li>
<li class="course_video viewed">
I need to select this <div class="course_duration" align="right">1m 21s</div>
</li>
</ul>
</li>
<li>
<div class="course_video_heading"><span class="plus"></span> Warm up <div class="course_duration" align="right">1h 15m</div></div>
<ul>
<li class="course_video viewed current">
Roll down <div class="course_duration" align="right">57s</div>
</li>
<li class="course_video">
Roll down with demi pointe variation <div class="course_duration" align="right">57s</div>
</li>
<li class="course_video" data-file="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4" data-image="http://content.bitsontherun.com/thumbs/nPripu9l-480.jpg">
Side roll down <div class="course_duration" align="right">57s</div>
</li>
<li class="course_video">
Side roll down variation with contraction <div class="course_duration" align="right">57s</div>
</li>
<li class="course_video">
Class exercise <div class="course_duration" align="right">57s</div>
</li>
</ul>
</li>
<li>
<div class="course_video_heading"><span class="plus"></span> Brushes <div class="course_duration" align="right">1h 5m</div></div>
<ul>
<li class="course_video">
Welcome <div class="course_duration" align="right">1m 21s</div>
</li>
</ul>
</li>
</ul>
My requirement : There is a element, <li class="course_video viewed current">, I need the previous li which has course_video class. In this case it would be :
<li class="course_video viewed">
I need to select this <div class="course_duration" align="right">1m 21s</div>
</li>
What have I tried :
$(".current").prev(".course_video")
This is not working as it is in different li
Note : It is not the duplicate of following questions :)
jQuery to find nearest Div of Parent
Getting next closest select element with jquery
jquery find closest previous sibling with class
Try this : read the index of current li and if it is 0 then find the previous li of its parent li and then find the course_video. And if index is not 0, then find previous li using prev()
var index = $(".current").index();
if(index==0)
{
var previousLi = $(".current").closest('li').prev('li').find("li.course_video:last");
}
else
{
var previousLi = $(".current").prev(".course_video");
}
var vindex;
$().ready(function () {
$("li .course_video").each(function (index) {
if ($(this).hasClass('current')) {
vindex = index;
}
});
$("li .course_video").each(function (index) {
if (index == vindex - 1) {
alert($(this)[0].outerHTML);
}
});
});
this code will help you.
$('.current').parents('li').prev().find('li:last')
Here's the jsFiddle
You can do it easily with a function that checks the index of the item: if the index is 0 then you'll select the last li in the previous ul.
Element.prototype.previousLi = function() {
var i = $(this).index(),
n = this.parentElement.previousSibling.children.length;
if (i) return this.parentElement.children[i-1];
else return this.parentElement.previousSibling.children[n-1];
}
Then you can do:
var el = $(".course_video.viewed.current")[0];
var previous = el.previousLi();
Try this code , it will give you the desired result :
<script>
var currentLI = $("li.current");
prevLi=$(currentLI).parent('ul').parent('li').prev('li').find('li.viewed:last');
alert($(prevLi).html());
</script>