How to get specific element javascript based on style - javascript

I need to acces an element that has a certain style.
This is my structure
<ul>
<li> Hi </li>
<li> bye </li>
<li> third one </li>
</ul>
The list items are placed on top of each other (last one first) and I can dislike something or like something. Once I do that, it gets a style display:none like following:
<ul>
<li> Hi </li>
<li> bye </li>
<li style:"display:none;"> third one </li>
</ul>
Now after I did that I want to be able to acces the last element that does not have display:none, (the bye) how can I do this?
I was thinking of something in the form of:
var myId = $("#slider > ul li").last().attr("id");
But obviously I always get the ID of the item that is hidden since its still there.
Can I do something like select last where !display:hidden ?

Can I do something like select last where !display:hidden ?
Yes, with jQuery's :visible pseudo-class:
var myId = $("#slider > ul li:visible").last().attr("id");
(Note: Your li elements don't actually have id values, but that's a tweak.)
Live Example:
var listItem = $("#slider > ul li:visible").last();
$("<p>")
.text("Text of last visible item: " + listItem.text())
.appendTo(document.body);
<div id="slider">
<ul>
<li>Hi</li>
<li>bye</li>
<li style="display:none;">third one</li>
</ul>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

Can use ':visible' selector
var myId = $("#slider > ul li:visible").last().attr("id");

It should work using:
$("#slider > ul li:visible").last().attr("id");
https://api.jquery.com/visible-selector/

so your inline styling is a bit off it should be
<ul>
<li> Hi </li>
<li> bye </li>
<li style="display:none;"> third one </li>
</ul>
You could do a few different things, best is probably just iterate through and check for where display = none, then go to the previous element:
$('ul').children().each(function(e) {
if($(this)[0].style.display == 'none') {
console.log($(this).prev());
}
})

Related

Trying to get the value of very next element of the current selected element using jQuery

I am trying to get the value of very next element of the current/selected element for example here is the list
<ul>
<li class="abc selected">test </li>
<li class="abc">test1 </li>
<li class="abc">test2 </li>
</ul>
From the above code I am trying to get the value of "a" tag which is very next to the selected li, in above case I am try to get the value of a tag which is test1 and this "a" tag is within the very next li after the selected one.
I tried to use the jQuery below but its fetching the empty result. Any help
var linktext1= jQuery(".selected").next("li a").text();
alert (linktext1);
The selector string passed to .next will filter out the next element if it doesn't match the selector string. But the next element is a li, not an a, so .next('li a') won't work.
Use .next("li").find('a') instead:
var linktext1 = jQuery(".selected").next("li").find('a').text();
console.log(linktext1);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li class="abc selected">test </li>
<li class="abc">test1 </li>
<li class="abc">test2 </li>
</ul>
In this particular situation, though, there's no need for a li selector to pass to .next, because what is .selected will be a li, so any of its siblings will also be lis:
var linktext1 = jQuery(".selected").next().find('a').text();
console.log(linktext1);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li class="abc selected">test </li>
<li class="abc">test1 </li>
<li class="abc">test2 </li>
</ul>
I think you should remove "li a" and it works. Below is the code
var linktext1= jQuery(".selected").next().text();
alert (linktext1);
Here is the example jsfiddle

querySelector() where display is not none

I have a long list of <li> items I need to filter. I want the visible ones. Here's an example hidden one:
<li style="display:none;"
<a href="https://www.example.com/dogs/cats/">
<img class="is-loading" width="184" height="245"
</a><span>dogscats</span>
</li>
Those which are not hidden don't have a display visible attribute, they just don't have a style attribute at all.
This gives me the opposite of what I want:
document.querySelectorAll('.newSearchResultsList li[style="display:none;"]')
How can I select based on style attribute does not equal or contain "display:none;"?
This whole thing is kind-of hacky, but you could use the :not() selector to invert your selection. Beware some browser normalize the style attribute, so you will want to include a selector for the space that may be normalized in.
var elements = document.querySelectorAll(
'.newSearchResultsList li:not([style*="display:none"]):not([style*="display: none"])'
);
console.log(elements);
<ul class="newSearchResultsList">
<li style="display:none;">hidden 1</li>
<li style="display:block;">visible 1</li>
<li style="display:none;">hidden 2</li>
<li style="display:block;">visible 2</li>
</ul>
If you want you could also select both these elements and any child elements.
const selector = '.newSearchResultsList li:not([style*="display:none"]):not([style*="display: none"])';
const elements = document.querySelectorAll(`${selector}, ${selector} *`);
console.log(elements);
<ul class="newSearchResultsList">
<li style="display:none;">hidden <i>1</i></li>
<li style="display:block;">visible <b>1</b></li>
<li style="display:none;">hidden <i>2</i></li>
<li style="display:block;">visible <b>2</b></li>
</ul>
Of course, these only work when selecting elements with inline styles.
Try this:
document.querySelectorAll('.newSearchResultsList li:hidden')
or (EDIT: Based on style attribute) Note that a simple SPACE destroys the selector. I mean: "display:none" can not be "display: none"
document.querySelectorAll('.newSearchResultsList li[style*="display:none"]');
or opossite
document.querySelectorAll('.newSearchResultsList li:not([style*="display:none"])');
Use '.newSearchResultsList li' selector to select all the li elements
Use Array#filter over collection
Use getComputedStyle to get all styles associated with element
Return only those elements having style !== none
var liElems = document.querySelectorAll('.newSearchResultsList li');
var filtered = [].filter.call(liElems, function(el) {
var style = window.getComputedStyle(el);
return (style.display !== 'none')
});
console.log(filtered);
<ul class="newSearchResultsList">
<li style="display:none;">
<a href="https://www.example.com/dogs/cats/">
<img class="is-loading" width="184" height="245">
</a><span>dogscats</span>
</li>
<li>
<a href="https://www.example.com/dogs/cats/">
<img class="is-loading" width="184" height="245">
</a><span>Visible</span>
</li>
</ul>

Text not updating as expected using jQuery

I'm wondering if anyone could explain to me what is going on here?
var testNo = $("#test").text()
$("ul li a").click(function() {
$("#test").text($(this).text());
console.log(testNo)
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>
1
<ul>
<li>
<a href="#" >1</a>
</li>
<li>
2
</li>
<li>
<a href="#" >3</a>
</li>
</ul>
</li>
</ul>
It is strange to me why this wouldn't update the list item as you click using this method. However, if you change the javascript to;
$("ul li a").click(function() {
var testNo = $("#test").text()
$("#test").text($(this).text());
console.log(testNo)
})
It shows the value as one behind, but set the following as;
$("ul li a").click(function() {
$("#test").text($(this).text());
var testNo = $("#test").text()
console.log(testNo)
})
and it has the desired behaviour.
Is there a way to achieve what this last code snippet gives me, but by using the first code format?
Let me know something doesn't make sense,
thanks
You need to update the testNo variable text, then only it will show the latest text. Try:
var testNo = $("#test").text()
$("ul li a").click(function() {
testNo = $(this).text();
$("#test").text($(this).text());
console.log(testNo)
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<ul>
<li>
1
<ul>
<li>
<a href="#" >1</a>
</li>
<li>
2
</li>
<li>
<a href="#" >3</a>
</li>
</ul>
</li>
</ul>
It's all about when you get the value of the $('#test').text() -- because you then go on to change the source value.
Your code does two things: (1) It reads #test and stores its value as testNo, and (2) it gets the text from the clicked anchor tag and puts that value into #test. So two things change: the var testNo and #test.
If you save the value of #test as var testNo, then change the value of #test before displaying testNo, they will have different values.
I think what you want to do is this:
$("ul li a").click(function() {
var testNo = $(this).text()
$("#test").text(testNo);
console.log(testNo)
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>
1
<ul>
<li>
<a href="#" >1</a>
</li>
<li>
2
</li>
<li>
<a href="#" >3</a>
</li>
</ul>
</li>
</ul>
In your first code testNo is set globally and take the value at page load in the second and 3th it is set locally so the value changes at each click event ,
In the second the value is incremented before the text is change so it captures the previous altered value, the 3th the value is saved after the text is saved so testNo is display the updated value

Determine what number li element a div is in

Say I have:
<ul>
<li></li>
<li>
<div id="test"></div>
</li>
<li></li>
</ul>
Is there a way to tell from the div tag what number li tag it's in?
I.e. in the div there is a javascript function that returns 2 since it's inside the second li element.
I realise I could go:
get parent ul
check each li child until the div is found.
Is there a more elegant way to do this?
You can use different variations of jQuery index()
$('li').index( $('li:has(div)') );
or
$('li:has(div)').index();
demo
You could use jQuery .find(); something like :
<ul class="level-1">
<li class="item-i">I</li>
<li class="item-ii">II
<div class="text">this is the div</div>
</li>
<li class="item-c">C</li>
<li class="item-iii">III</li>
</ul>
$("ul.level-1").find( "div" ).css( "background-color", "yellow" );
Depends what you need ...
You can use .index() to get the index of the li, since index is zero based add 1 to it to get 2
var $div = $('#test')
var index = $div.parent().index() + 1

jquery next siblings

I've been trying to get this problem solved, but I can't seem to figure it out without some serious workarounds.
if I have the following HTML:
<ul>
<li class="parent"> headertext </li>
<li> text </li>
<li> text </li>
<li> text </li>
<li class="parent"> headertext </li>
<li> text </li>
<li> text </li>
</ul>
Now, how do I now just select the <li> tags following the first parent (or second, for that matter)? Basically selecting an <li> with class="parent" and the following siblings until it reaches another <li> with the parent class.
I could restructure the list with nested lists, but I don't want to do that. Any suggestions?
actually, you can easily do this using nextUntil().
no need to write your own "nextUntil" since it already exists.
ex. -
$(".a").nextUntil(".b");
or as suggested by Vincent -
$(".parent:first").nextUntil(".parent");
The root of your problem is that the <li>s you have classed as parent really are NOT parents of the <li>s "below" them. They are siblings. jQuery has many, many functions that work with actual parents. I'd suggest fixing your markup, really. It'd be quicker, cleaner, easier to maintain, and more semantically correct than using jQuery to cobble something together.
I don't think there is a way to do this without using each since any of the other selectors will also select the second parent and it's next siblings.
function getSibs( elem ) {
var sibs = [];
$(elem).nextAll().each( function() {
if (!$(this).hasClass('parent')) {
sibs.push(this);
}
else {
return false;
}
});
return $(sibs);
}
You will have to run the loop yourself since jQuery does not know how to stop on a specific condition.
jQuery.fn.nextUntil = function(selector)
{
var query = jQuery([]);
while( true )
{
var next = this.next();
if( next.length == 0 || next.is(selector) )
{
return query;
}
query.add(next);
}
return query;
}
// To retrieve all LIs avec a parent
$(".parent:first").nextUntil(".parent");
But you may be better using a really structured list for your parent/children relationship
<ul>
<li class="parent"> <span>headertext</span>
<ul>
<li> text </li>
<li> text </li>
<li> text </li>
</ul>
</li>
<li class="parent"> <span>headertext</span>
<ul>
<li> text </li>
<li> text </li>
</ul>
</li>
</ul>
$("li.parent ~ li");
I know this is a very old thread, but Jquery 1.4 has a method called nextUntil, which could be useful for this purpose:
http://api.jquery.com/nextUntil/
<html>
<head>
<script type="text/javascript">
$(document).ready(function() {
$("a").click(function() {
var fred = $("li").not('.parent').text();
$('#result').text(fred);
});
});
</script>
</head>
<body>
Click me
<ul>
<li class="parent"> headertextA </li>
<li> text1 </li>
<li> text2 </li>
<li> text3 </li>
<li class="parent"> headertextB </li>
<li> text4 </li>
<li> text5 </li>
</ul>
<div id="result"></div>
</body>
</html>

Categories