find an element by style with jquery - javascript

How could I find an element in an HTML document using it's style properties?
here is an example:
HTML:
<ul>
<li style='z-index=1;'>e1</li>
<div style='z-index=8;'>div</div>
<li style='z-index=2;'>e2</li>
<li style='z-index=3;'>e3</li>
<li style='z-index=4;'>e4</li>
<li style='z-index=5;'>e5</li>
<ul>
The question is how do i select, for example..: the element <li> with z-index=4.
and how to select all div's with z-index=8 ...

If the style is set inline, you can use an attribute selector:
$('li[style*="z-index:4"]') //returns any li's with z-index = 4
see here. The advantage to this method is that it is very fast.
If the style is set via a stylesheet, you can access it this way:
var elem;
var elems = $("li");
for(var i=0; i<elems.length; i++) {
if($(elems[i]).css('z-index') == '4') {
elem = elems[i]; //assign elem we found
break; //exit loop early
}
}
Note Webkit browsers, (Safari, Chrome, etc), will not return a z-index value unless it is positioned as well. See this example
Also, for loop is still faster than .filter()

There isn't a style selector (how would it work, the style is a combination of inherited and explicitly stated rules), but you can filter (demo):
var things = $("li").filter(function() {
return $(this).css('z-index') == '4';
});
Now if you are using z-index to attach a piece of data to an HTML element you might have more luck using data attributes (cleaner, and searchable by Sizzle). One interpretation might look like this: (demo)
<div data-id='8'>div</div>
<ul>
<li data-id='1'>e1</li>
<li data-id='2'>e2</li>
<li data-id='3'>e3</li>
<li data-id='4'>e4</li>
<li data-id='5'>e5</li>
<ul>
<script>
alert($('[data-id=4]').text())
alert($('[data-id=8]').text())
</script>

Related

How to find the class of element in a each loop

I am trying to create a menu system where I can change the style of the active page item in the menu. I am using a separate body class on each page, then I want to cycle through the li in the menu and find a match to the body class. At that match I will add the new styling to that menu item.
Here is my code so far.
HTML
<body class="home-state">
...
<div class="menu-left">
<ul>
<li class="home-state">
Home
</li>
<li class="work-state">
Work
</li>
<li class="services-state">
Services
</li>
<li class="about-state">
About
</li>
<li class="blog-state">
Blog
</li>
<li class="shop-state">
Shop
</li>
<li class="contact-state">
<a data-toggle="modal" href="#modal-coworking">Contact</a>
</li>
<li class="project-state">
Project brief
</li>
</ul>
</div>
...
</body>
JS
var bodyClass = $("body").attr('class');
$('.menu-left ul li').each(function(){
First: I want to find the element's class here I have used $(this).attr("class"); which didn't work
var element = $(this);
Second: I want to use a if statement to check to see if the class matches the bodyClass
console.log(element);
Last: If there is a match I want to add the class .active to the element li.
});
Given that elements can have multiple classes, I'd suggesting changing your body element to use a data- attribute rather than a class to specify what the current page is:
<body data-current="home-state">
Then the JS needed to add the active class to the relevant menu item is simple:
$("li." + $("body").attr("data-current")).addClass("active")
You don't need to loop over the menu items comparing classes as mentioned in the question, because you can just directly select the required li element based on its class.
In the event that the body element doesn't have a data-current attribute then $("body").attr("data-current") would return undefined, which would mean the code above tries to select an element with $("li.undefined") and add a class to it. Probably you have no elements with such a class so that would be harmless, but if you wanted to explicitly test that the data-current attribute exists:
var current = $("body").attr("data-current")
if (current) {
$("li." + current).addClass("active")
}
You can do this in couple ways, here is the simple way to do this;
var bodyClass = $("body").attr('class');
$("li." + bodyClass).addClass("active")
You can also use a loop for this one;
var bodyClass = $("body").attr('class');
$(".menu-left li").each(function(i, classes) {
if (bodyClass === $(this).attr("class")) {
$(this).addClass("active")
}
})
both will do the job.
enter image description here
enter image description here
as the comment said,the element can have more than one class ,so you should check it one by one
You missed to bind the click event for the menu item. Follow like below
var bodyClass = $("body").attr('class');
$('.menu-left ul li').on( "click", function() {
var myClass = $(this).attr("class");
alert(myClass);
});
Tested: https://codepen.io/anon/pen/XzYjGY

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
}

Accessing a specific li within a ul

After looking at past examples and source code I have made, I can't seem to work out accessing a specific <li><a>the value in this</a></li> based on a parameter sent in.
Mockup:
<ul class="selectBox-dropdown-menu selectBox-options size-dropdown mediumSelect footwear" style="top: 309px; left: 34px; display: none;">
<li class="" style="display: none;"><a rel=""></a></li>
<li class="size-not-in-stock"><a rel="3096786:6"> 6</a></li>
<li class="size-not-in-stock"><a rel="3096787:6.5"> 6.5</a></li>
<li class=""><a rel="3096788:7"> 7</a></li>
<li class="selectBox-selected"><a rel="3096789:7.5"> 7.5</a></li>
<li class=""><a rel="3096790:8"> 8</a></li>
<li class=""><a rel="3096791:8.5"> 8.5</a></li><li><a rel="3096792:9"> 9</a></li>
<li><a rel="3096793:9.5"> 9.5</a></li><li><a rel="3096794:10"> 10</a></li>
<li><a rel="3096795:10.5"> 10.5</a></li><li><a rel="3096796:11"> 11</a></li>
<li><a rel="3096797:11.5"> 11.5</a></li><li><a rel="3096798:12"> 12</a></li>
<li><a rel="3096799:12.5"> 12.5</a></li><li><a rel="3096800:13"> 13</a></li>
<li><a rel="3096801:14"> 14</a></li><li><a rel="3096802:15"> 15</a></li></ul>
</ul>
Here is what I am trying to get. Let us say that a user puts in a value of 7, well than it should find the corresponding <li><a></a></li> that contains the number 7 and click it.
My troubles are with finding that value inside this, I know I need to use find within the <ul> but what stumps me is based on a value.
UPDATE:
I just want to make clear that, this is something that is going to be an auto process so I am trying to make it so I don't have to do anything except load the page.
You need something like
var test = "the content to seek";
$('ul.footwear').find('a').filter(function(idx, el){
return $.trim($(this).text()) == $.trim(test);
}).closest('li').trigger('click')
Demo: Fiddle
There is no need to loop through and read the innerHTML of every element like all of the other solutions appear to be doing. You can just do it with a selector.
Since the rel attribute seems to have the data you are after at the end :size, you can use use :has() and ends with $= selectors to get the lis you are after.
var num = 7;
var elems = $(".footwear li:has(a[rel$=':" + num + "'])");
console.log(elems.length);
And if you want to click it, than you call .click() or .trigger("click")
function findAndClick (size) {
var elem = $(".footwear li:has(a[rel$=':" + size + "'])");
elem.trigger("click");
}
And to trigger it on the page load it would be something like
$(window).on("load", function() { findAndClick(7); } );
or document ready
$( function() { findAndClick(7); } );
Sad thing is, this solution appears to be great with a simple selector, but the performance can be subpar. If there is only going to be one element with the size, the best performance would be an each() loop and breaking out of it when you find the one element. No need to look at the other elements.
The best performing would be an each()
function findAndClick (size) {
var elem;
size = size.toString();
$('.footwear').find('a').each(function () {
if ($.trim($(this).text()) == size) { //compare the text
elem = $(this).parent(); //set the element that contains the link
return false; //exit each loop
}
});
if (elem) {
elem.trigger("click"); //fire click
}
}
For even better performance, eliminate the need to read the text of the element or use a ends with selector. Add a data attribute to the element.
<li data-size="7">
and than you would just use a selector
function findAndClick (size) {
$('.footwear li[data-size="' + size + '"]').trigger("click");
}
I would optimize this by making your structure better suited for these types of queries
<li id="10"><a rel="3096793:9.5"> 9.5</a></li><li><a rel="3096794:10"> 10</a></li>
Put an id on the li that corresponds to the value of the a tags.
Then you can do a simple $("#10") selector
While it's possible to make complex selectors based on filters etc, keep in mind that performance will not be great in general for non browser backed selectors (pseudo selectors)
Since you have an attribute rel that finish with the content, you can use this:
$('a[rel$="\:'+valueToMatch+'"]').parent()

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

reorder list elements - jQuery? [duplicate]

This question already has answers here:
How may I sort a list alphabetically using jQuery?
(10 answers)
Closed 5 years ago.
Is it possible to reorder <li> elements with JavaScript or pure jQuery. So if I have a silly list like the following:
<ul>
<li>Foo</li>
<li>Bar</li>
<li>Cheese</li>
</ul>
How would I move the list elements around? Like put the list element with Cheese before the list element with Foo or move Foo to after Bar.
Is it possible? If so, how?
var ul = $("ul");
var li = ul.children("li");
li.detach().sort();
ul.append(li);
This is a simple example where <li> nodes are sorted by in some default order. I'm calling detach to avoid removing any data/events associated with the li nodes.
You can pass a function to sort, and use a custom comparator to do the sorting as well.
li.detach().sort(function(a, b) {
// use whatever comparison you want between DOM nodes a and b
});
If someone is looking to reorder elements by moving them up/down some list one step at a time...
//element to move
var $el = $(selector);
//move element down one step
if ($el.not(':last-child'))
$el.next().after($el);
//move element up one step
if ($el.not(':first-child'))
$el.prev().before($el);
//move element to top
$el.parent().prepend($el);
//move element to end
$el.parent().append($el);
One of my favorite things about jQuery is how easy it is to write tiny little add-ons so quickly.
Here, we've created a small add-on which takes an array of selectors, and uses it to order the children of the target elements.
// Create the add-on
$.fn.orderChildren = function(order) {
this.each(function() {
var el = $(this);
for(var i = order.length - 1; i >= 0; i--) {
el.prepend(el.children(order[i]));
}
});
return this;
};
// Call the add-on
$(".user").orderChildren([
".phone",
".email",
".website",
".name",
".address"
]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="user">
<li class="name">Sandy</li>
<li class="phone">(234) 567-7890</li>
<li class="address">123 Hello World Street</li>
<li class="email">someone#email.com</li>
<li class="website">https://google.com</li>
</ul>
<ul class="user">
<li class="name">Jon</li>
<li class="phone">(574) 555-8777</li>
<li class="address">123 Foobar Street</li>
<li class="email">jon#email.com</li>
<li class="website">https://apple.com</li>
</ul>
<ul class="user">
<li class="name">Sarah</li>
<li class="phone">(432) 555-5477</li>
<li class="address">123 Javascript Street</li>
<li class="email">sarah#email.com</li>
<li class="website">https://microsoft.com</li>
</ul>
The function loops backwards through the array and uses .prepend so that any unselected elements are pushed to the end.
Here is a jQuery plugin to aid with this functionality: http://tinysort.sjeiti.com/
something like this?
​var li = $('ul li').map(function(){
return this;
})​.get();
$('ul').html(li.sort());
demo
I was somewhat lost you may be wanting something like this...
$('ul#list li:first').appendTo('ul#list'); // make the first to be last...
$('ul#list li:first').after('ul#list li:eq(1)'); // make first as 2nd...
$('ul#list li:contains(Foo)').appendTo('ul#list'); // make the li that has Foo to be last...
more of it here1 and here2
Have a look at jquery ui sortable
http://jqueryui.com/demos/sortable/

Categories

Resources