QuerySelector with specified index in Javascript (like [1]) - javascript

How do I make:
document.getElementsByClassName("first")[1].getElementsByClassName("second")[2];
but with querySelector?
My guess would be:
document.querySelector(".first[1] > .second[2]");
But that doesn't work.

In your original selection you're grabbing the second element with the class of .first and the third element with the class of .second that is also the child of the former. With this in mind you could use the nth-of-type pseudo selector for both classes and count up accordingly. The only difference with this method in comparison to the JS you have now is that it doesn't use the zero-index.
// document.getElementsByClassName("first")[1].getElementsByClassName("second")[2];
document.querySelector('.first:nth-of-type(2) .second:nth-of-type(3)').style = 'border: 1px solid red;'
.first {
border: 1px solid black;
padding: 10px;
}
.first:nth-of-type(2) {
margin-top: 10px;
}
<div class="first">
<div class="second">Second (1)</div>
<div class="second">Second (2)</div>
<div class="second">Second (3)</div>
</div>
<div class="first">
<div class="second">Second (1)</div>
<div class="second">Second (2)</div>
<div class="second">Second (3)</div>
</div>

document.querySelector(".first:nth-of-type(2) .second:nth-of-type(3)").style.color = "red"
<div class="first">
<div class="second">second1</div>
<div class="second">second2</div>
<div class="second">second3</div>
<div class="second">second4</div>
</div>
<div class="first">
<div class="second">second1</div>
<div class="second">second2</div>
<div class="second">second3</div>
<div class="second">second4</div>
</div>

You don't need the > operator of the querySelector, you could use the following syntax:
document.querySelector('.first:nth-child(1) .second:nth-child(2)');
Within this HTML code:
var test = document.querySelector('.first:nth-child(1) .second:nth-child(2)').innerText;
console.log(test);
<div class="first">
<div class="second"></div>
<div class="second">Hello, I'm your selected div!</div>
<div class="second"></div>
</div>
<div class="first">
</div>
The JS code will produce the output:
Hello, I'm your selected div!
Keep in mind that CSS pseudoselectors start counting from 1, not from 0, so to achieve the example you posted, you'd need to set :nth-child(2) and :nth-child(3).
Also, if you have a different structure, it might as well be worth taking a look at the :nth-of-type selector, as the :nth-child will require to be the nth child of a parent, in an absolute sense. Differently, :nth-of-type will look for the nth (typeof) child of a parent.

Related

How can I wrap inner divs that are dynamic?

I have been trying badly to wrap some divs with an outer div so that I can style them. But I'm unable to do so thus far.
I have this list div which contains some inner divs that I need to wrap. That is the inner divs which have same letters need to be bundled together. Although targeting the divs with the letters is not a good idea as they are gonna be dynamic.
This is an example of what I have been trying to achieve:
<div class="list-wrapper">
<div class="el">A</div>
<div>
<a>A</a>
</div>
</div>
<div class="list-wrapper">
<div class="el">C</div>
<div>
<a>C</a>
</div>
<div>
<a>C</a>
</div>
</div>
Another example:
This is what I have tried so far:
$(list).find('div.el').each(function(idx, item) {
$(item).nextAll('div').wrapAll('<div class="list-wrapper"></div>')
});
.wrapper {
background-color: red;
padding: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="list">
<div class="el">A</div>
<div>
<a>A</a>
</div>
<div class="el">B</div>
<div>
<a>B</a>
</div>
<div class="el">C</div>
<div>
<a>C</a>
</div>
<div>
<a>C</a>
</div>
<div class="el">D</div>
<div>
<a>D</a>
</div>
<div>
<a>D</a>
</div>
<div>
<a>D</a>
</div>
<div class="el">E</div>
<div>
<a>E</a>
</div>
</div>
To achieve your goal you can use a combination of nextUntil() within the loop, to get the div elements between each .el, and wrapAll(). You can include addBack() in there to add the current .el in the loop in to the collection to be wrapped. Try this:
$('#list').find('.el').each((i, el) => {
$(el).nextUntil('.el').addBack().wrapAll('<div class="list-wrapper"></div>')
});
.wrapper {
background-color: red;
padding: 20px;
}
.list-wrapper { border: 1px solid #C00; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="list">
<div class="el">A</div>
<div><a>A</a></div>
<div class="el">B</div>
<div><a>B</a></div>
<div class="el">C</div>
<div><a>C</a></div>
<div><a>C</a></div>
<div class="el">D</div>
<div><a>D</a></div>
<div><a>D</a></div>
<div><a>D</a></div>
<div class="el">E</div>
<div><a>E</a></div>
</div>
Note that $(list) was only working by proxy, as elements with an id attribute are available as properties on the document. It's much better practice to use a valid string selector.

How to select the first element on a page using a particular class when each subsequent element using the same class is also a first child?

I'm making a Fibonacci spiral. Code below. I need to create a second layer of the spiral (a spiral is made with a series of nested divs) and am creating multiple layers using the for loop.
I need to change the height of the first div element in the file with class .item-one, no subsequent divs with class .item-one.
How do I select just the first one, bearing in mind there will be a further 4 div elements with class .item-one which are also all the first child of their parents, using just CSS and vanilla JS?
(I need to change the height of just the first one and need all the rest of the .item-one divs to be a different height.)
I've tried :first-child and :first-of-type but all .item-one elements are the first children of their respective parents, so both :first-child and :first-of-type select all of the .item-one elements, not just the first on the page.
This post select first element of the same class is close, except the solution selects all first child elements, whereas I only want to select the first div in the file with that class.
Code:
HTML
<div class="item-one">
<div class="item-two">
<div class="item-three">
<div class="item-four"></div>
</div>
</div>
</div>
JS
window.addEventListener('load', function() {
var $items = document.getElementsByTagName("div");
var $item = $items[0];
var $cloned_item = $item.cloneNode(true);
var $final_item = $items[$items.length - 1];
for (var i = 1; i <= 5; i++) {
$final_item.appendChild($cloned_item);
$final_item = $items[$items.length - 1];
$cloned_item = $item.cloneNode(true);
}
});
The end result looks something like this.
<div class="item-one">
<div class="item-two">
<div class="item-three">
<div class="item-four">
<div class="item-one">
<div class="item-two">
<div class="item-three">
<div class="item-four">
<div class="item-one">
<div class="item-two">
<div class="item-three">
<div class="item-four">...and so on...</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
You'd have to use the parent to be able to single out the first child element. I used body in this case, but if you have a different parent then you'd use that.
body > .item-one {
border: 1px solid red;
}
<div class="item-one">
<div class="item-two">
<div class="item-three">
<div class="item-four">
<div class="item-one">
<div class="item-two">
<div class="item-three">
<div class="item-four">
<div class="item-one">
<div class="item-two">
<div class="item-three">
<div class="item-four">...and so on...</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Or better would be to just give that outer div another class and use that if that's an option.
Does that what you are looking for?
div {border: 1px solid blue;}
.item-one {border: 1px solid yellow;}
body > .item-one {border: 2px solid red;}
<div class="item-one">
<div class="item-two">
<div class="item-three">
<div class="item-four">
<div class="item-one">
<div class="item-two">
<div class="item-three">
<div class="item-four">
<div class="item-one">
<div class="item-two">
<div class="item-three">
<div class="item-four">...and so on...</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Edit after #LGSon open eyes comments.
You can use the > selector to apply the styling to the immediate first child of its parent with the .item-one class. If you don't have a parent for all of those elements, then using the body should do.
body>.item-one {
/* Styling here */
padding: 5px;
margin: 5px;
border: 5px black solid;
}

A Multi-Level Up Css Selector

I'm trying to find a way to use css selectors to format a specific parent div. For example, in the following sample code...
<div id="one">
<div id="two"
<div id="three">
something
...etc
I want to format div#one but only if the link inside of #one is a specific page like "foo.html".
I have tried several things but here is one example of what I have tried to use...
a[href *="foo"] #one:parent {
background-color: #FF0000;
}
Is there a way to do this using css selectors, js or jQuery? I've included a code snippet below for testing...
a[href *="foo"] #one:parent {
background-color: #FF0000;
}
<div id="one">
<div id="two"
<div id="three">
something
</div>
</div>
</div>
Everywhere I have searched for an answer has only given clues to how to do this with parent elements that are just one parent above but not several divs as in this example.
With CSS you cannot but with JS you can simply consider parentNode:
document.querySelector('a[href *="foo"]').parentNode.parentNode.parentNode.style.backgroundColor = "red";
#one {
padding:50px;
}
<div id="one">
<div id="two">
<div id="three">
something
</div>
</div>
</div>
And if you have n parent and you don't know the number you can create a loop to find your element:
var a = document.querySelector('a[href *="foo"]');
while (a.parentNode.getAttribute('id') != "one") {
a = a.parentNode;
}
a.parentNode.style.background = "red";
#one {
padding: 50px;
}
<div id="one">
<div id="two">
<div id="three">
<div>
something
</div>
</div>
</div>
</div>

jquery back to element before find or filter

I am looking a way to back to previous element which i was selected , take a look to this example :
$("Selector")
.find(".class")
.attr("data-foo" , "bar")
.eq(1)
.attr("data-isFirst" , "Yeah")
.find("span")
.filter(".blue")
.addClass("IAmHere")
now if I want to back before filtering .blue or finding .class I can not do , I use caching selector like this :
var $main = $("Selector");
var $myDest = $main.find(".class");
$myDest.filter(".blue").addClass("IAmHere");
$myDest.filter(".red").addClass("ItIsRed");
var $myDestTwo = $main.find(".otherClass").eq(5);
$myDestTwo.filter(".foo").addClass("bar");
$myDestTwo.filter(".bar").addClass("foo");
but this is a lot of codes , if we can create some thing like unFilter or unFind with jquery fn it will be a cool thing like this :
$("Selector")
.find(".class")
.attr("data-foo" , "bar")
.filter(".blue")
.addClass("IAmHere")
.unfilter(".blue")
.addClass("ItIsRed")
.unfind(".class")
.find(".otherClass")
.attr("data-foo" , "bar")
.filter(".foo")
.addClass("bar")
.unfilter(".bar")
.addClass("foo")
Thanks
You can use the end function
$("Selector").find(".red").addClass("IAmRed").end().find('.blue').addClass("IAmRBlue").end();
Your eq() is confusing as you call filter on a set of 1, meaning the filter is redundant and you might as well make anything you filter on part of the original selector.
Anyway, You can use closest as an alternative if you need to go further up the chain than what end() gets you too (Though end() should work fine):
$(main).find(myClass).filter('.blue').addClass('itIsBlue').closest(main).find(myClass).filter('.red').addClass('itIsRed')
You didn't post any HTML so trying to understand exactly what your desired end result would be is challenging. Hence made up some HTML simply to demonstrate the use of closest. You need to change any logic to apply to your HTML off course as needed.
function traversalCode() {
var main = '.mySelector';
var myClass = '.myClass';
var otherClass = '.otherClass';
$(main)
.find(myClass).filter('.blue').addClass('itIsBlue')
.closest(main)
.find(myClass).filter('.red').addClass('itIsRed')
.closest(main)
.find(otherClass).filter('.yellow').addClass('itIsYellow')
.closest(main)
.find(otherClass).filter('.green').addClass('itIsGreen')
}
$(document).ready(function() {
traversalCode();
})
.itIsBlue {
background-color: lightblue;
}
.itIsRed {
background-color: pink;
}
.itIsYellow {
background-color: yellow;
}
.itIsGreen {
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="mySelector">
<div class="myClass red">
<span>myClass red</span>
</div>
<div class="otherClass yellow">
<span>otherClass yellow</span>
</div>
<div class="myClass red">
<span>myClass red</span>
</div>
<div class="otherClass green">
<span>otherClass green</span>
</div>
<div class="myClass blue">
<span>myClass blue</span>
</div>
<div class="otherClass yellow">
<span>otherClass yellow</span>
</div>
<div class="myClass blue">
<span>myClass blue</span>
</div>
<div class="otherClass green">
<span>otherClass green</span>
</div>
<div class="myClass blue">
<span>myClass blue</span>
</div>
<div class="otherClass green">
<span>otherClass green</span>
</div>
<div class="myClass red">
<span>myClass red</span>
</div>
<div class="otherClass yellow">
<span>otherClass yellow</span>
</div>
</div>

Detach and append divs/html jquery

I thought this would be kinda straightforward but i cant wrap my head around this. I got to following html:
<div id="foo">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
</div>
<div id="bar">
<div class="test">test1</div>
<div class="test">test2</div>
<div class="test">test3</div>
<div class="test">test4</div>
</div>
I need to grab/detach the div's .test and put/append them into the .item div's. So the first div .test needs to go in the first div .item, the second div .test to the second div .item etc. So it becomes:
<div id="foo">
<div class="item">1<div class="test">test1</div></div>
<div class="item">2<div class="test">test2</div></div>
<div class="item">3<div class="test">test3</div></div>
<div class="item">4<div class="test">test4</div></div>
</div>
Now i found some jquery code and i came to this:
var child = $('#bar').find("div").eq(0);
var parent = $('#foo').eq(0);
child.detach();
parent.append( child );
This works but as suspected, it detaches/appends the first div. Now i need to detach/append them all one by one and from reading a lot of topics, i think i need to put a loop/each in there somewhere but i have no idea how and im not getting any closer after screwing around for hours.
Anyone who can put me in the right direction with this?
You can move all of them easily by just using the append() method and selecting all the divs:
$('#bar').append( $('#foo div') )
/* This is just for showing that the elements actually moved. */
#foo { background:red; }
#bar { background:blue; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="foo">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
</div>
<div id="bar">
<div class="test">test1</div>
<div class="test">test2</div>
<div class="test">test3</div>
<div class="test">test4</div>
</div>
<div>
Alternatively, if you want to do something with each element, you can use .each():
$('#foo div').each(function(i, elem) {
var $elem = $(elem);
//Do stuff
$('#bar').append($elem);
});
/* This is just for showing that the elements actually moved. */
#foo { background:red; }
#bar { background:blue; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="foo">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
</div>
<div id="bar">
<div class="test">test1</div>
<div class="test">test2</div>
<div class="test">test3</div>
<div class="test">test4</div>
</div>
<div>
On solution is to get both collections and iterate over one of the collections. Also note that you don't need to use .detach. .append will already do that.
var $fooItems = $("#foo .item");
var $barTests = $("#bar .test");
$fooItems.each(function(index, el) {
$(this).append($barTests.eq(index));
});
Example Fiddle
I think there are two solutions for your issue : .childern() function or usiing jQuery selectors
For example using selector :
$("#bar > div")
or using children() function :
$("#bar").children("div");
also look at this post, you may have your answer here : jQuery - get all divs inside a div with class ".container"

Categories

Resources