Get the previous visible element jquery - javascript

I have a <ul> like
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li style="display:none;">4</li>
<li class="curSelected">5</li>
<li>6</li>
</ul>
Now from <li> 5 I want the reference of the previous visible element i.e <li> 3
How can I get it?
I tried $('li.curSelected').prev(":visible:last");
But this is not working.
Please help.

Try this:
$('li.curSelected').prevAll(":visible:first");
prev() returns only the immediate element preceding the selected one. prevAll() returns all previous.

You can use .prevUntil() to search up to (but not including) the first visible item, then use .prev():
$('.curSelected').prevUntil(':visible').prev()
Update
As pointed out in the comments, this wouldn't work if the immediately previous item is already visible. Unfortunately, there's no optimal jQuery for that, so here's an alternative:
$prev = $('.curSelected')
do {
$prev = $prev.prev();
} while ($prev.length && $prev.is(':hidden'));

Since jQuery traverses the dom, using prev, from the current to the first, but returns only one element(the previous), you should use .prevAll.
$("li.curSelected").prevAll(":visible:first");
See a working fiddle of this example.

Here's my example. Works perfect, any browser.
var elem = $( some_thing ).next();
while( elem && elem[0] != undefined && !elem.is( ':visible' ) )
elem = elem.next();
if( elem && elem[0] != undefined )
elem.doSomething();

Related

I need jQuery to perform a task if two conditions are true

I need some help to put an if statement together using jQuery. I want to change the logo on my site, if two conditions are true.
Here is some pseudo code, hopefully explaining what i want to archive:
if(li hasClass active and data-menuid is equal to 0033){
change logo...
}
Here is a simple example of the menu structure:
<div id="menu">
<ul id="menu-primary">
<li class="menuactive" data-menuid="0011">
Test1
<ul class="menu-dropdown">
<li data-menuid="0022">Test2</li>
<li class="active" data-menuid="0033">Test3</li>
</ul>
</li>
<li data-menuid="0044">Test4</li>
<li data-menuid="0055">Test5</li>
</ul>
</div>
You can check the combination of class and Attribute Equals Selector [name="value"]
if($('li.menuactive[data-menuid="0033"]').length){
//Your code to change the logo
}
You can use $.fn.filter()
Reduce the set of matched elements to those that match the selector or pass the function's test.
var listMeetingCondition = $('li').filter(function(){
return $(this).hasClass('menuactive') && $(this).attr('data-menuid') == "0033"
});
if(listMeetingCondition.length){
//Your code to change the logo
}
if($('li:has(.menuactive[data-menuid="0033"])').length){
change logo...
}
Another workaround:
var $target = $('li', '#menu-primary');
if( $target.hasclass('active') && $target.data('menuid') == '0033' ){
// change logo
}

How to check if element is last child without JQuery

I have a pure Javascript script with an onclick event that checks the value of the next sibling before deciding what to do. This will cause an error if the element clicked is the last element in its container (because of accessing nextSibling). I need to first check that the element clicked is not the last element in the container, but can't seem to find out how.
Note: I don't think this is a duplicate. There are quite a few questions about checking if an element is the last child, but all accepted answers—all answers in general—use JQuery.
You can use the .nextSibling property on the element and see if it comes back as empty (undefined, etc).
You can use the node.lastChild Property
The Node.lastChild read-only property returns the last child of the node. > If its parent is an element, then the child is generally an element node, > a text node, or a comment node. It returns null if there are no child elements..
var tr = document.getElementById("row1");
var corner_td = tr.lastChild;
The error you get should be some kind of can't set property on undefined.
You have just to check whether the next element exists:
if (typeof element.nextSibling === "undefined")
return;
For some reason none of the answers worked for me, I always ended up seeing a #text node instead of undefined or null, so I ended up comparing my element with the last child of the parent of the element:
element === element.parentNode.children[element.parentNode.children.length-1]
or if you want it as a function
function isLastChild(el) {
return (el === el.parentNode.children[el.parentNode.children.length-1])
}
//Useage
if(isLastChild(el)) {
//Element is the last child of its parent.
}
Might be longer than other answers but surly won't fail you.
Accessing an element's nextSibling element you'll get null if the element has no next sibling, so you can just check before going on with your code, like this:
if (myElement.nextSibling) {
// the element has a next sibling
// go on...
} else {
// the element is the last child
}
Use the .lastChild property of the node.
Example:
Here, we are removing last 4 child nodes in the list.
function clearAll() {
var sidemenu = document.getElementById('side_menu');
console.log("sidemenu.childNodes.length = " + sidemenu.childNodes.length);
while (sidemenu.childNodes.length > 2) {
console.log(sidemenu.childNodes);
sidemenu.removeChild(sidemenu.lastChild);
console.log("removed");
console.log("sidemenu.childNodes.length = " + sidemenu.childNodes.length);
}
console.log("What we have left now:");
console.log(sidemenu.childNodes);
}
clearAll();
<ul id="side_menu">
<li>List Item 1</li>
<li>List Item 2</li>
<li>List Item 3</li>
<li>List Item 4</li>
<li>List Item 5</li>
</ul>
Learn more: Node.lastChild - Web API Interfaces | MDN
This is one way to check:
document.querySelector(":last-child");
Here's one more:
var isLastChild = (element === element.parentNode.lastChild);
If you're trying to make this compatible with older browsers, just use childNodes:
// Last element in the body
document.getElementsByTagName('body')[0].childNodes[document.getElementsByTagName('body')[0].childNodes.length-1]
so for your particular problem, use the event object in your onclick:
element.onclick = function(event) {
var parent = event.target.parentNode;
if(event.target === parent.childNodes[parent.childNodes.length-1])
// Code here
}
How about var isLastChild = element === element.parentNode.lastChild?
Ask if there is a next element or not to know if it is the last or not:
if (typeof element.nextElementSibling == null) {
//is last
return;
} else {
//is not last
}
you must use nextElementSibling, no nextSibling or typeof ...
function isLastElement(element) {
return element.nextElementSibling === null;
}

jQuery: How to select a child or element with attribute that contains x?

Let's say I have some unordered lists with items, and one or many that has a class of 'active'
<ul id='list'>
<li class='row active'></li>
<li attrA='something active'></li>
<li attrB='active'></li>
</ul>
<ul id='otherList'>
<li class='row active'></li>
<li attrA='something active'></li>
<li attrB='active'></li>
</ul>
I want to get the item where class is "active" that is a child or element of the unordered list, "list".
I tried...
$("#list li[class~='active']")
$("#list > li[class~='active']")
But to no avail...
Here's a more detailed version of my problem. The code used to print this output is...
var listId = "typeahead-3-6260";
console.log( $("#"+listId+" li") );
console.log( $("#"+listId+" li[class~='active']") );
As you can see, line 2 had some results, but line 3 didn't.
$("#list li").filter(function(){return $(this).attr('name').indexOf("name") >= 0)
Use element.attributes to get the list of attributes and use nodeValue to get the value of attribute to check if it has active
Live Demo
$("#list li").each(function(){
for(i=0; i < this.attributes.length; i++)
if(this.attributes[i].nodeValue.indexOf('active') != -1)
$(this).text('has active attribute');
});
As you have mentioned that you need to check the 'class' attribute as 'active' here is the code that might help you
$(document).on('click','#list>li.active',function(){
alert('I am here');
});
JSFiddle

Select element by element's content

I have list:
<ul class='mates'>
<li class='m' id='1'>Jakub</li>
<li class='f' id='2'>Vinnie</li>
<li class='m' id='3'>David</li>
</ul>
How can I select 'li' tags "ONE BY ONE" to be checked if their content (between 'li' tags) is equal to 'xyz'.
element = document.getElementsByClassName('.mates').firstChield.innerHTML;
do {
if(){
//do something
}
}while (element = element.nextSibling);
but I'm not getting even far enough to select firstChild. This error is showing in console: "Cannot read property 'innerHTML' of undefined". This needs to be done in plain JavaScript. Any ideas?
<ul class='mates'>
<li class='m' id='1'>Jakub</li>
<li class='f' id='2'>Vinnie</li>
<li class='m' id='3'>David</li>
</ul>
<script>
var mates = document.getElementsByClassName('mates')[0];
for (var i=0; i< mates.childNodes.length; i++){
if(mates.children[i].innerHTML == 'Vinnie') alert("Got you! ID "+mates.children[i].id)
}
</script>
Drop the dot in the parameter. Like this:
element = document.getElementsByClassName('mates').firstChild.innerHTML;
The dot is not a part of the name of the class.
EDIT also notice that the question originally had a typo in firstChild.
Your element variable is not an element (its value is probably undefined). It should work if you use it like this:
var element = document.getElementsByClassName('mates')[0].firstChild;
do {
if(element.innerHTML == 'foo'){
//do something
}
} while (element = element.nextSibling);
The code above fixes:
The class name as pointed out by #Renan
The typo in .firstChild
Also note that getElementsByClassName returns a list of elements, so you have to grab the first one in the list (index 0) to reach your <ul>.
Finally, keep in mind that you'll be looping over all children of the <ul>, including empty text nodes (see a demonstration at http://jsfiddle.net/58ZZF/). This can be avoided if you use firstElementChild and nextElementSibling, but I'm not sure if there are cross browsers issues with those properties (MDN only says it's Firefox 3.5+).
Few mistakes
Class name to getElementsByClassName should not have .
Spelling mistake in firstChild
getElementsByClassName returns an array, not a dom reference
When using nextSibling it could return text nodes also, you need to check the nodeType to make sure the element is a element node(nodeTye = 1), also you can check the tagName == 'LI'
Try
var element = document.getElementsByClassName('mates')[0].firstChild;
do {
if(element.nodeType == 1){
console.log(element.textContent)
}
}while (element = element.nextSibling);
Demo: Fiddle

Pass this value from a list with javascript

I have the following list:
<ul>
<li onclick="populateComment(..this.)">very good </li>
<li onclick="populateComment(..this.)">not so good</li>
<li onclick="populateComment(..this.)">no t.....</li>
</ul>
and javascript:
function populateComment() {
document.getElementById("COMMENT").value = document.getElementById("COMMENT").value + 'THE_STRING_VALUE_FROM_THE_LIST';
}
So the idea is that I have a textarea, which I fill by clicking on the list.
So if I click on the first list, the text "very good" should be appended to the textarea. But I dont want to retype the text "very good" in my function, can I take it directly with something as an argument like this.value.. so it automatically takes the string between the <li> ...</li>
Thank you for your time.
You're looking for:
this.textContent || this.innerText
this.textContent is supported in all decent browsers, this.innerText is needed for older versions of IE.
Instead of duplicating the onclick handler multiple times, you can also bind a listener to the <ul> element:
// Replace <ul> with <ul id="populatefrom">
document.getElementById("populatefrom").onclick = function(ev) {
ev = ev || window.event; //Backwards compatible with IE
var target = ev.target;
if (target.nodeName.toLowerCase() == "li") {
document.getElementById("COMMENT").value += target.textContent || target.innerText;
}
};
If you don't have anything other than a simple bit of text, you could also use:
this.firstChild.nodeValue;
However if there are any nodes at all (bold, span, or anything else other than text... even an HTML comment) then this won't work and you need the textContent/innerText combo Rob W gave.
Sure you could do this with jQuery like so (didn't test this yet):
<ul>
<li class="populateComment">very good </li>
<li class="populateComment">not so good</li>
<li class="populateComment">no t.....</li>
</ul>
and your jQuery:
$('.populateComment').click(function(){
$('#textboxID').val($(this).html());
});
Working jsfiddle: http://jsfiddle.net/zEaam/

Categories

Resources