How can I select every single element with JS or jQuery? - javascript

I want to select every single element in a document and make them color red when I scroll to them.
$(document).ready(function() {
$(document).on("scroll", animationDivs);
function animationDivs(event) {
var scrollPos = $(document).scrollTop();
var divs = $("*");
$(divs).each(function() {
var currLink = $(this);
if (currLink.position().top <= scrollPos && currLink.position().top + currLink.height() > scrollPos) {
currLink.style.color = "red";
}
});
};
});
I used this codes but didn't work.

using JS:
document.querySelectorAll('*')
.forEach(el => el.style.color = 'red')
Try it in the console of your browser to see how it works and here's a brief overview of DOM selection with JS vs jQuery.
This is a similar question with a variety of solutions.

First add some common css class on each divs and add following jquery.
$('.class-name').each(function() {
var currLink = $(this);
if (currLink.position().top <= scrollPos && currLink.position().top + currLink.height() > scrollPos) {
currLink.style.color = "red";
}
});

using jq, you could simple get all element withing the html by "*"
var items = $("*").css({background : "red"})
console.log(items)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div></div>
<p></p>

currLink is a jQuery object in your code. So use a jQuery method on it.
That would be the .css() method in your case.
And I suggest you use an else part to your condition so the elements does not turn red after the first single wheel spin... Since <body> is also collected in $("*").
$(document).ready(function() {
$(document).on("scroll", animationDivs);
function animationDivs(event) {
var scrollPos = $(document).scrollTop();
var divs = $("*");
$(divs).each(function() {
var currLink = $(this);
if (currLink.position().top <= scrollPos && currLink.position().top + currLink.height() > scrollPos) {
currLink.css({"color":"red"});
}else{
currLink.css({"color":"initial"});
}
});
};
});
.spacer{
height:500px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<br>
<span>Scroll me.</span>
<div class="spacer"></div>
<div>div
<p>paragraph</p>
<a>anchor</a>
<span>span</span>
</div>
<div class="spacer"></div>
By the way... Using an .each() loop on the $("*") collection on every scroll event is the worst jQuery usage I suppose I will ever see. I can assure you that you'll scratch your head pretty soon with a real web page with real content.
Every elements, including <br> and <script> and <link> etc. are collected using $("*") that way... And are compared in the loop. You should only use it when absolutely necessary and within at least a container to lower the amount of collected elements.... Like $(".some-class *").

Related

How can I select only the nth child of an class in JS?

Hey there I wrote a small JS to flip elements when I am reaching a specific div, that works fine. I just want to flip one of the elements but I am trying to avoid giving that element and extra id or class in the markup since it's cms based content.
How can I tell JS to just apply it on the 8th element, for example?
JavaScript:
function flip_scroll() {
var window_top = $(window).scrollTop();
var Services = $('.c-services').offset().top;
if (window_top > Services)
$(".c-services__item").addClass("applyflip");
else
$(".c-services__item").removeClass("applyflip");
}
$(function() {
$(window).scroll(flip_scroll);
flip_scroll();
});
You can use jQuery's nth-child-selector
I just had too lok in the docs as #nickroz pointed out, thanks :-)
https://api.jquery.com/nth-child-selector/
function flip_scroll() {
var window_top = $(window).scrollTop();
var Services = $('.c-services').offset().top;
if (window_top > Services)
$(".c-services__item:nth-child(8)").addClass("applyflip");
else
$(".c-services__item:nth-child(8)").removeClass("applyflip");
}
$(function() {
$(window).scroll(flip_scroll);
flip_scroll();
});

Jquery to check height and add class

I am trying to check which div has bigger height and than place a class inside the one that is greater.
I have this code
$(document).ready(function () {
var sideNavMenu = $(".col-md-3").height();
var mainColumn = $(".col-md-9").height();
if (sideNavMenu > mainColumn)
{
$(".col-md-3").addClass('dotRight');
}
else
{
$(".col-md-9").addClass('dotLeft');
}
});
The goal here is to check if sideNavMenu is greater than mainColumn than place dotRight on its div tag.
If the mainColumn is greater, then place dotLeft on its div tag.
But its not working.
Any suggestion how to change/improve it.
Thanks a lot
You should reference these by IDs and not classes, since there can be multiple elements with these class names on the page. There should only be one with each ID.
$(document).ready(function () {
var sideNavMenu = $("#sidebar").height();
var mainColumn = $("#main").height();
if (sideNavMenu > mainColumn) {
$("#sidebar").addClass('dotRight');
} else {
$(".#main").addClass('dotLeft');
}
});
Of course, you need to add the id's to your <div>s respectively.
The jQuery docs say:
Get the current computed height for the first element in the set of matched elements or set the height of every matched element.
But, I was just playing with it in jsfiddle and it seems to return an object containing the height of the first element.
http://jsfiddle.net/wwx2m/2/
Which means you should be able to do:
$(document).ready(function () {
var sideNavMenu = $(".col-md-3").height();
var mainColumn = $(".col-md-9").height();
if (JSON.stringify(sideNavMenu) > JSON.stringify(mainColumn)) {
$(".col-md-3").addClass('dotRight');
} else {
$(".col-md-9").addClass('dotLeft');
}
});
But the first way I said is preferred. This is not stable, since there can be more objects introduced with the same class. The only reason I'm even mentioning it is to explain why you were having problems with your original code. :)
http://jsfiddle.net/wwx2m/4/
I put the jsfiddle together for you
<html>
<div class='col-md-3'>
</div>
<div class='col-md-9'>
</div>
<script>
var sideNavMenu = $(".col-md-3").height();
var mainColumn = $(".col-md-9").height();
if (sideNavMenu > mainColumn){
$(".col-md-3").addClass('dotRight');
}
else{
$(".col-md-9").addClass('dotLeft');
}
jsFiddle
updated jsFiddle with Animation

Using :last-child and :first-child with jQuery

I'm trying to write my first self-built jQuery script, as a super simple gallery.
CSS:
#gallery li{
display:none;
}
#gallery li.current {
display: block;
}
HTML:
<div id="gallery">
<li class="current"><img src="img/1.jpg" /></li>
<li><img src="img/2.jpg" /></li>
<li><img src="img/3.jpg" /></li>
<li><img src="img/4.jpg" /></li>
</div>
<div id="controls">
<span id="left"><</span>
<span id="right">></span>
</div>
JQUERY:
$(function(){
$('#controls #left').click(function(){
var old = $('li.current');
$('li.current').removeClass('current');
if (old = $('#gallery:first-child')){
$('#gallery:last-child').addClass('current');
}else{
$(old).prev('li').addClass('current');
}
});
$('#controls #right').click(function(){
var old = $('li.current');
if (old = $('#gallery:last-child')){
$('#gallery:first-child').addClass('current');
}else{
$('li.current').removeClass('current');
$(old).next('li').addClass('current');
}
});
});
It worked fine until I added the if/else statements to check whether we're looking at the first/last gallery image. I want this statement so that the gallery loops. Can't figure out why it's not working, and debug is giving me nothing.
Can I get a little push in the right direction?
EDIT: using some suggestions below, here's where I'm at:
$(function(){
$('#left').click(function(){
var old = $('li.current');
old.removeClass('current');
if (old == $('#gallery li:first-child')){
$('#gallery li:last-child').addClass('current');
}else{
old.prev('li').addClass('current');
}
});
$('#right').click(function(){
var old = $('li.current');
old.removeClass('current');
if (old == $('#gallery li:last-child')){
$('#gallery li:first-child').addClass('current');
}else{
old.next('li').addClass('current');
}
});
});
Still isn't looping around though (pressing "left" on the first image makes the gallery blank, as does pressing "right" on the last image)
You might want to be using ==:
if (old == $('#gallery:first-child')){
and
if (old == $('#gallery:last-child')){
Although that won't work anyways, as pointed out by Jack, because they are separate jQuery calls that may select the same elements and return similar jQuery objects, but won't work with comparison because they are separate collections of DOM element(s). The correct way is to use .is like I provide below...or to compare with:
if (old[0] == $('#gallery:first-child')[0]){
Indexing them like that retrieves the first item each in the selected sets, which are the actual DOM elements, and can be compared. Probably not preferred, but its not wrong.
Here's an example of proving this is true: http://jsfiddle.net/4adSj/
You're also doing a few weird things. You don't need to use this selector: $('#controls #right') - $('#right') is unique enough thanks to how id should be used.
Also, you store var old = $('li.current'); and then the next line you don't bother using old - you re-get it like $('li.current').
Also, you are nesting <li> elements in a <div>, when they should only be nested in <ul>, <ol>, or <menu>.
One more - the variable old is a jQuery object, so you don't need to be doing $(old) every other time you want to access it after you declared it. Just use old.jQueryMethod().
Finally, the other problem is that your selector for the if statements:
$('#gallery:last-child')
Means find the element that has the id "gallery" and is a last-child. You probably want:
$('#gallery > li:last-child')
Which means find the child element that is the last li child element of the parent element with an id of "gallery".
So here's my suggestion of your final code to use:
$(function(){
$('#left').on("click", function () {
var old = $('li.current');
old.removeClass('current');
if (old.is(':first-child')){
$('#gallery > li:last-child').addClass('current');
} else {
old.prev('li').addClass('current');
}
});
$('#right').on("click", function () {
var old = $('li.current');
old.removeClass('current');
if (old.is(':last-child')){
$('#gallery > li:first-child').addClass('current');
} else {
old.next('li').addClass('current');
}
});
});
You can use .is(':first-child) and .is(':last-child') to find out if something is the first or last child respectively:
$('#controls #left').click(function() {
var old = $('li.current')
.removeClass('current');
if (old.is(':first-child')) {
// search the siblings for the last child
old.siblings(':last-child').addClass('current');
} else {
$(old).prev('li').addClass('current');
}
});
$('#controls #right').click(function() {
var old = $('li.current')
.removeClass('current');
if (old.is(':last-child')) {
old.siblings(':first-child').addClass('current');
} else {
$(old).next('li').addClass('current');
}
});
​
Btw, I would change your HTML to this:
<div id="controls">
<span class="left"><</span>
<span class="right">></span>
</div>
And then use $('#controls .left') and $('#controls .right') to target your clickable elements.
Edit
A fancier approach could be this, food for thought:
// wrap the functionality inside an anonymous function
// localizing the gallery and controls blocks
(function($gallery, $controls) {
var pos = 0;
// this function performs the actual move left and right, based on event data being passed in via evt.data.delta
function move(evt) {
var $items = $gallery.children(), // if the gallery never changes size you should cache this value
max = $items.length;
$items.eq(pos).removeClass('current');
pos = (pos + evt.data.delta) % max; // update the position
$items.eq(pos).addClass('current');
}
// attach the controls
$controls
.on('click', '.left', {
delta: -1 // left decreases the position
}, move)
.on('click', '.right', {
delta: 1 // right increases the position
}, move);
// make sure the first is always selected
$gallery.children().removeClass('current').eq(pos).addClass('current');
}($('#gallery'), $('#controls')));​​​​​​​​​ // immediate invocation
jsBin demo
var c = 0;
var imgN = $('#gallery li').length; // 4
$('#left, #right').click(function(){
c = this.id=='right' ? ++c : --c ;
$('#gallery li').hide().eq( c%imgN ).show();
});
Or even:
var c = 0;
$('#left, #right').click(function(){
$('#gallery li').hide().eq( (this.id=='right'?++c:--c) % 4 ).show();
});
gallery Demo
P.S: instead of .hide() you can use .removeClass('current')
and instead of .show() you can use .addClass('current')

Jquery Mutate Plugin

I have come across this plugin but I'm a newbie, I was wondering if anyone could give me an example on how to use this on my website.
http://www.jqui.net/jquery-projects/jquery-mutate-official/
<div id="content">
<h1>Favourite Teams</h1>
<ul>
<li>Arsenal</li>
<li>Man U</li>
<li>Liverpool</li>
</ul>
</div>
I would like to check when content div height changes to display more or less teams depending on the available height.
Updated code
This is what I managed to come up with. I don't know why it does not work.
$('content ul').mutate('height',function (element,info){
var h= $(this).height();
var calculate = h/$(this).find('li').eq(0).height();
var i = 0;
$(this).find('li').hide().each(function (){
if(i<calculate)$(this).show();
i++;
})
});
The problem is with you're Selector.
If you want to find the DIV with ID = content than you should use $("#content")
$('#content ul').mutate('height',function (element,info){
var h= $(this).height();
var calculate = h/$(this).find('li').eq(0).height();
var i = 0;
$(this).find('li').hide().each(function (){
if(i<calculate)$(this).show();
i++;
})
});

How to cycle through siblings using jQuery?

I have the folowing code:
html:
<div class="container">
<div class="selected">A</div>
<div>B</div>
<div>C</div>
<div>D</div>
</div>
<button id="next">next!</button>
jQuery:
$("#next").click(function() {
$(".selected").removeClass("selected").next().addClass("selected");
});
What i want is loop through the divs in the container. I can do this to cycle:
$("#next").click(function() {
if ($(".selected").next().length == 0) {
$(".selected").removeClass("selected").siblings(":nth-child(1)").addClass("selected");
}
else {
$(".selected").removeClass("selected").next().addClass("selected");
}
});
But i think there is a simpler way. How can i make it simpler ? (I don't mind if you don't use the next() function).
jsFiddle: http://jsfiddle.net/S28uC/
I 'd prefer siblings.first() instead of siblings(":nth-child(1)"), but in essence you won't be able to wrap around without using some variant of next().length.
Update: If I were writing this from scratch, this is how I 'd do it:
$("#next").click(function() {
var $selected = $(".selected").removeClass("selected");
var divs = $selected.parent().children();
divs.eq((divs.index($selected) + 1) % divs.length).addClass("selected");
});
This approach is motivated by two factors:
When you want to cycle over a collection indefinitely, modulo comes to mind
Getting rid of the if makes for smarter-looking code
When setting the value of divs I preferred $selected.parent().children() over the equivalent $selected.siblings().add($selected) as a matter of taste -- there are practically endless possibilities.
One simple way is this :
$("#container").find("div:eq(0)").addClass("selected");
how about this.
...
var selected = $(".selected").removeClass("selected");
if (jQuery(selected).next().addClass("selected").length == 0
{jQuery(selected).siblings().first().addClass("selected");};
...
In old good AI manner you try to do the deed (addClass), if it worked (length <> 0) nothing more to do, otherwise you try again on the first of the siblings.
You can try this
var cont = $('.container'),
i = 0;
$("#next").on('click', function() {
cont.children().removeClass('selected');
i += 1;
if ( i === document.querySelectorAll('.container div').length ) { i = 0; }
cont.children().eq(i).addClass('selected');
});
var cont = $('.container'),
i = 0;
$("#next").on('click', function() {
cont.children().removeClass('selected');
// increase index for each click
i += 1;
// reset i if it reached to last index
//(hack to force next to go back to first element when we are at the end)
if ( i === document.querySelectorAll('.container div').length ) {
i = 0;
}
cont.children().eq(i).addClass('selected');
});
.selected {
background-color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="selected">A</div>
<div>B</div>
<div>C</div>
<div>D</div>
</div>
<button id="next">next!</button>
simply you will increase i for each click and when it reach the end (divs length ) it will be reset.

Categories

Resources