Trying to loop a function to run on multiple elements - jQuery - javascript

I'm trying to get this jQuery parallax code to work but I don't want to spaghetti everything. How can it be looped to apply to multiple element IDs?
(it doesn't work with classes because the function needs to run multiple times specific to each particular div) - I'm not very good when it comes to looping, still learning how to do this stuff.
Anyway, this is a functioning code for one section (a div with a child div, #about > #pAbout in this instance):
$(document).ready(function() {
if ($("#pAbout").length) {
parallax();
}
});
$(window).scroll(function(e) {
if ($("#pAbout").length) {
parallax();
}
});
function parallax(){
if( $("#pAbout").length > 0 ) {
var plxBackground = $("#pAbout");
var plxWindow = $("#about");
var plxWindowTopToPageTop = $(plxWindow).offset().top;
var windowTopToPageTop = $(window).scrollTop();
var plxWindowTopToWindowTop = plxWindowTopToPageTop - windowTopToPageTop;
var plxBackgroundTopToPageTop = $(plxBackground).offset().top;
var windowInnerHeight = window.innerHeight;
var plxBackgroundTopToWindowTop = plxBackgroundTopToPageTop - windowTopToPageTop;
var plxBackgroundTopToWindowBottom = windowInnerHeight - plxBackgroundTopToWindowTop;
var plxSpeed = 0.35;
plxBackground.css('top', - (plxWindowTopToWindowTop * plxSpeed) + 'px');
}
}
I was hoping to create an array like this:
var ids = ['#pAbout', '#pConcept', '#pBroadcast', '#pDigital', '#pDesign', '#pContact'];
But I can't get the e business to work unfortunately, it's very frustrating for me. Any help would be greatly appreciated!

You can use multiple selector in jQuery to select disparate elements by simply using a comma between the selectors.
$("#pAbout, #pConcept, #pBroadcast, #pDigital, #pDesign, #pContact")
.each(function(){
//manipulate element here
});
That each() iterates over all matched elements so no need to check for length etc.

Related

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

jQuery iteration though all items of a class regardless of their position in the DOM

i'm building a webpage where many spanĀ­ needs to be transitioned from one class to another to create a bg-color fadein effect. Distribution of elements of same classes is mixed through the page, but they are all grouped under common classes.
I want to create a behavior that does the following: when you click any elements of class-n, the other elements of that class transitions, with the clicked element acting as the starting point.
This is mostly figured out, thanks to some help on SO; see the jsfiddle.
$(".div").click(function () {
var itemClasses = this.classList;
var itemThread = itemClasses[1];
colorThread($(this), itemThread);
console.log(itemThread);
});
function colorThread($div, tId) {
tId = '.'+tId;
$div.toggleClass('div-clicked');
setTimeout(function () {
(function togglePrev($div) {
$div.toggleClass('div-clicked');
setTimeout(function () {
togglePrev($div.prev(tId));
}, 100);
})($div.prev(tId));
(function toggleNext($div) {
$div.toggleClass('div-clicked');
setTimeout(function () {
toggleNext($div.next(tId));
}, 100);
})($div.next(tId));
}, 100);
}
However, I am still struggling around a particular issue: I don't want the transition to stop if if encounter different class, I just want it not to toggle and keep iterating. If the jsfiddle, that would translate in all of the same color div to transition, regardless of their placement in the DOM tree.
In my togglePrev/toggleNext function, I have tried something along
if($div.hasClass(".classToTransition"))
{
$div.toggleClass(".div-clicked");
}
but couldn't get it to work properly (it doesn't ieterate to the next elements). There is something that I can't seem to grasp in the structure of that conditional. Anyone has a lead?
You really did manage to complicate something that should be pretty simple ?
$(".div").click(function () {
var coll = $('.'+this.className.replace(/(div-clicked|div)/g, '').trim()),
idx = coll.index($(this).toggleClass('div-clicked'));
$.each(coll, function(i) {
setTimeout(function() {
if (idx + i <= coll.length) coll.eq(idx + i).toggleClass('div-clicked');
if (idx - i >= 0) coll.eq(idx - i).toggleClass('div-clicked');
},i*200);
});
});
FIDDLE
It gets all the elements with the same class as the one currently clicked, and the index of the currently clicked, and then just adds and subtract 1 to the current index to get the next and previous elements. The checks are to make sure it stops when it reaches the end.
I don't want the transition to stop if if encounter different class, I just want it not to toggle and keep iterating
You might want to use nextAll(tId).first()/prevAll(tId).first() to select the next to-be-toggled element: http://jsfiddle.net/35uNW/4/. .next() does only look at the next sibling, and if that doesn't match your tId selector, no element will be selected.
If you want to iterate the different-classed elements so that you wait for each one, but don't want to toggle it, you can use your if-condition but you must remove the tId selector from the next()/prev() calls: http://jsfiddle.net/35uNW/3/.
This was a fun one. I did it a slightly different way, getting all of the matched elements and splitting them into before and after arrays.
var $allItems = $(".div");
$(".div").click(function () {
var itemClasses = this.classList;
var itemThread = itemClasses[1];
colorThread($(this), itemThread);
});
function colorThread($div, classname) {
var tId = '.'+classname,
$divs = $allItems.filter(tId),
index = $divs.index($div),
$before = $divs.slice(0, index),
before = $before.get().reverse(),
$after = $divs.slice(index+1);
$div.toggleClass('div-clicked');
$(before).each(function(i, item){
setTimeout(function () {
$(item).toggleClass('div-clicked');
}, i*100);
});
$($after).each(function(i, item){
setTimeout(function () {
$(item).toggleClass('div-clicked');
}, i*100);
});
}
Here's a working fiddle: http://jsfiddle.net/5sUr4/

JQuery If Statement using each value from an array

I am writing a function that will be executed on multiple views of an application, and each view can have up to 50 instances of the same element: '.console'. I need to be able to perform an action every time the viewport scrolls to each instance. I have the following code setting up the variables:
//Create empty array with variable values, up to 50
var console = [];
//Find each instance of ".console" and populate the array with its pixel position.
$('.console').each(function() {
console.push($(this)[0].offsetTop);
});
//Determine the current pixel position of the scroll
var scroll = $(document).scrollTop();
Those variables all work fine and dandy, but after hours of pouring over jquery docs I can't figure the if statement out. Here is what I have that works well for the first item in the array:
if (scroll == console[0]){
$('.container').show();
} else {
$('.container').hide();
}
However, I want it to be anytime the scroll position matches each of the values in that array, hopefully something like this:
if (scroll == console[0-50])
Here is the full chunk as is:
$(document).on('scroll', function(){
//Create empty array with variable values, up to 50
var console = [];
//Find each instance of ".console" and populate the array with its pixel position.
$('.console').each(function() {
console.push($(this)[0].offsetTop);
});
//Determine the current pixel position of the scroll
var scroll = $(document).scrollTop();
//Anytime the scroll matches any of the instances of console, show a div
if (scroll == console[0]){
$('.container').show();
} else {
$('.container').hide();
}
});
Any help would be appreciated. I am pretty new to Javascript/JQuery so if I'm approaching the problem in the wrong way altogether, please let me know. Thanks!
Since you said it works for the first one, I'm guessing this may work.
// cache the container
var container = $('.container');
$(document).on('scroll', function(){
//Determine the current pixel position of the scroll
var scroll = $(document).scrollTop();
//Create empty array with variable values, up to 50
var console = [];
//Find each instance of ".console" and populate the array with its pixel position.
$('.console').each(function(index) {
console.push($(this)[0].offsetTop);
if (scroll == console[index]){
$(container).show();
} else {
$(container).hide();
}
});
});
You may wish to take a look at Waypoints. It's a jQuery plugin that is well suited for what you're trying to accomplish.
I whipped up a quick jsFiddle to show it in action: http://jsfiddle.net/dmillz/4xqMb/
$(".console").waypoint(function(direction) {
// Hide or show your ".container" object
});
More Waypoint examples: http://imakewebthings.com/jquery-waypoints/#get-started
Hopefully I understand your problem, which is as follows:
You have a bunch of elements with the .console class, and you want to appear as soon as they are in the viewport. When these elements aren't in the viewport you want them to dissapear?
Since you're interested in when these objects with the .console class are in the viewport, I suggest using this jQuery plugin
http://plugins.jquery.com/appear/
https://github.com/morr/jquery.appear
I suggest wrapping each of the .console objects in a container with another class, and then as these containers appear and disappear show and hide them.
At document ready just do the following:
$(document).ready(function() {
$('<.container-class>').appear();
$('<.container-class>').on('appear', function() { $(this).find('.console').show(); });
$('<.container-class>').on('disappear', function() { $(this).find('.console').hide(); });
});
To answer the question, you could do this:
var cons = $.map($('.console'), function(el) {
return $(el).offset().top;
});
$(document).on('scroll', function(){
var scroll = $(window).scrollTop();
$('.container').toggle( $.inArray(scroll, cons) != -1 );
});
But creating something for a range, considering the height of each element, the height of the window etc. would be a lot more involved.
While the problem was solved via another answer, figuring out how to perform a loop for each value in the array wasn't really solved ... UNTIL NOW!
This is probably a really gross and bloated way to do it, but if you essentially count how many items are in the array, you can then run a loop that many times, putting in the index for each value in the array. Code below:
//Create empty array with variable values
var console = [];
//Find each instance of ".console" and populate the array with its pixel position.
$('.console').each(function() {
console.push($(this)[0].offsetTop);
});
//Count the number of items in the array
var consoleIndex = console.length - 1;
$(document).on('scroll', function(){
//Determine the current pixel position of the scroll
var scroll = $(document).scrollTop();
//Anytime the scroll matches any of the instances of console, show a div
for (var i = 0; i <= consoleIndex; i++) {
if (scroll = console[i]) {
$('.container').toggle();
}
}
});

How to determine the top element?

I have a complex structure of many nested, absolutely positioned elements.
These elements may or may not have their z-index set.
They also may or may not have the same parent element.
I am wondering what is the best / simplest way to return which element is on 'top'. Something like the following...
$(".panel").topMost()
Thanks (in advance) for your help
Do you mean the element with highest z-index:
$(document).ready(function() {
var array = [];
$("*").each(function() {
array.push($(this).css("z-index"));
});
var highest = Math.max.apply(Math, array);
console.log(highest);
});
A plugin is there ..topZindex
$.topZIndex("div");
Try this:
var z = [];
$('.panel').each(function(i, el) {
var $panel = $(el),
zindex = $panel.css('z-index');
z[zindex] = $panel;
});
var topMost = z.slice(-1);
See if you don't specify z-index to absolute elems then last of the element will be on top of other elems, means last element will have a greater highest default z-index calculated by browser itself.
Try this fiddle: http://jsfiddle.net/fLB2W/
var array = [];
$("*").each(function () {
if ($(this).css('position') == 'absolute') {
array.push($(this).css("position")+'<--pos & class -->'+$(this).attr('class'));
}
});
console.log(array[array.length-1]);
I faced similar issue with Modal dialog while displaying jQuery UI datepicker and using event parameters to figure out the clicked icon. Modal dialog overlay was preventing the new datepicker from showing on top of the modal dialog.
The best solution worked in three browsers (IE, Firefox, and Chrome) is:
function topZIndex(target, selector) {
var objs = $(target).parents(selector + '[z-index > 0]');
var a1 = -1;
$.each(objs, function (index, z1) {a1=(z1.style.zIndex > a1)? z1.style.zIndex : a1; });
return a1;
};
using event parameters as follows:
var zIndex = topZIndex(event.currentTarget, 'div')+1;
or
var zIndex = topZIndex(event.currentTarget, '*')+1;
Both combinations will generate same result, however it is more efficient to be specific by specifying 'div' instead of '*'
Then assuming my date picker id is datepickerpanel to set the new zIndex for datepicker
$('#datepickerpanel').css('z-index', zIndex);
This solution provides proper z-index value to place the new object on top of modal dialog.

making function with multiple variables to pass javascript/jquery

I have a little snippet I want to make into a function. But I'm new to javascript. Obviously there is something wrong with the way I pass variables or the way I call them...
So in nutshell, this works: http://jsfiddle.net/kkvbz/
But this doesn't: http://jsfiddle.net/PrtD4/
Problem is I need it as a function, so I've to make 1 version work.
Full snippet:
function cutandMakeslides (containerid,liperslide) {
//This is for footer slider, it rewrites 1 ul into several uls that contain 4 li max.
// get the container, useful for later too...
var container = $(containerid);
// get all available UL and LI elements...
var li_elements = container.find("> UL > LI").clone();
// remove the current content so that we can rebuild it for the slider...
container.find("> UL").remove();
// build the slider container...
var slide_container = $("<div />");
// tricky part: looping through the LI's and building each of the slides...
// first create some helpful variables...
var li_elements_per_slide = liperslide;
var li_counter = 0;
// create the first slide, with a UL to hold the LI's...
var current_li_div = $("<div />");
current_li_div.append($("<ul />"));
// loop through the LI's...
li_elements.each(function(index, element){
li_counter++;
var current_li = $(element).clone();
current_li_div.find("> UL").append(current_li);
if (li_counter % li_elements_per_slide == 0)
{
// we've hit 4 in this list, so add the slide and make
// a new one, using same code as before...
container.append(current_li_div);
current_li_div = $("<div />");
current_li_div.append($("<ul />"));
}
});
// we might have an uneven number of LI's, so we need to check for this...
if (li_counter % li_elements_per_slide != 0)
container.append(current_li_div);
} // end function cutandMakeslides
//activate function above
$(function() { cutandMakeslides(".fproductslides",3); });
Problematic parts:
function cutandMakeslides (containerid,liperslide) {
var container = $(containerid);
var li_elements_per_slide = liperslide;
}
$(function() { cutandMakeslides(".fproductslides",3); });
So after extensive testing and moving the code to a fiddle, the problem seems to have resolved itself during moving it to the fiddle, so we believe there was a minor spelling or syntax error...however using a code comparison tool I was unable to find anything...
none of the problematic parts seemed to have an error:
function cutandMakeslides (containerid,liperslide) {
var container = $(containerid);
var li_elements_per_slide = liperslide;
}
$(function() { cutandMakeslides(".fproductslides",3); });
Here's a copy of the working fiddle
From your 'problematic parts' section it appears you are trying to pass a class(".fproductslides" is a class, classes start with '.' and Id's start with '#') instead of an Id as your variable names lead me to believe you want to do...

Categories

Resources