How to use a data identifier on an array of divs? - javascript

Hi there I'm currently building a slider and I got pretty much all nailed down except one last thing.
My bullet points are identifying what image you are currently looking at and can also be used for navigation as illustrated here (2 sliders since this is where im running into issues):
http://puu.sh/hAYp5/15477cd325.png
For the actual dots I've been able to use this code:
$(this.dots).click(function() {
var selected = $(this).data("img");
sliderEle.goTo(selected);
$(dots).removeClass("active");
$(this).addClass("active")
})
The prev and next buttons however I'm having an issue figuring out, this is what I currently got and it affects both sliders as it is none specific to the individual slider like I want it to be:
goTo: function(index) {
if (index < 0)
return;
// move <ul> left
this.ul.style.left = '-' + (100 * index) + '%';
this.currentIndex = index
},
goToPrev: function() {
this.goTo(this.currentIndex - 1)
$(this.dots).removeClass("active");
$('.slider-dot[data-img="'+this.currentIndex+'"]').addClass("active");
},
goToNext: function() {
if(this.currentIndex + 1 > this.li.length - 1) {
this.goTo(0)
}else {
this.goTo(this.currentIndex + 1)
}
$(this.dots).removeClass("active");
$('.slider-dot[data-img="'+this.currentIndex+'"]').addClass("active")
}
How do I change this line:
$('.slider-dot[data-img="'+this.currentIndex+'"]').addClass("active")
To work with something like this:
$(this.dots)
So it's targeted on the individual slider rather than all sliders.
Full js source: http://pastebin.com/NaDw0jib

Solved by using .filter from jquery
var currentDot = $(this.dots).filter('[data-img="'+this.currentIndex+'"]');
$(currentDot).addClass("active");

add a function to your prototype
getNav: function(index) {
return $(this.nav).filter(function() {
return $(this).data('img') === index;
});
});
ten use it like this:
this.getNav(3).addClass('active');
As an aside, I'd probably either expand the initialize method to actually create the DOM representation, or failing that, at least use classes rather than hard coding to children[i] references. It'll save you a headache later.

Related

jQuery run code after chunked $.each() is finished

With the below code:
$('#button').on('click', function () {
var longArray = searchArray; // assume this has 100 or more postalcodes init
var shortArrays = [], i, len;
for (i = 0, len = longArray.length; i < len; i += 100) {
shortArrays.push(longArray.slice(i, i + 100));
}
// Now we iterate over shortArrays which is an array of arrays where each array has 100 or fewer
// of the original postalcodes in it
for (i = 0, len = shortArrays.length; i < len; i++) {
// shortArrays[i] is an array of postalcodes of 100 or less
$.each(shortArrays[i], function(index, value){
setTimeout( function() {
// Each parent gets its own searchToggle class
$('.postcodes input[data-postcode*="' + value + '"]').parent().parent().addClass('searchToggle');
// Each parent also gets a data filter attribute for ordering the results
$('.postcodes input[data-postcode*="' + value + '"]').parent().parent().attr('data-filter' , index);
// We display the items in the search array
$('.postcodes input[data-postcode*="' + value + '"]').parent().parent().css('display', 'flex');
$('.postcodes .searchToggle .postcode input[data-postcode*="' + value + '"]').parent().css('display', 'flex');
}, 0 );
})
} // /for
alert('Finished message');
});
I try to show an alert message(for debugging) once the $.each() is finished. Since this each goes through an array that could be 1000s of postal codes long I broke it up in chunks of 100. This to prevent the dreaded browser is unresponsive. This is all working fine but the alert fires immediately on click.
I have tried several things already:
I tried by using a count: ABOVE THE EACH var count = 0; INSIDE THE EACH count++ if ( count == longArray.length ) { ALERT } But this also fired the alert immediately???
I tried it by using an interval but that became a mess almost instantly.
I tried a couple of other SO answers but all of them resulted in the alert to fire immediately.
When looking through the jQuery docs and previous codes that I have written it should just run the code after the each is finished but in this case it does not.
Any idea on why this is and how I can fix it.
PS: This alert could be other codes! Like sorting the results or something else.
PS2: I can change all the js/jQuery you see but I cannot change any of the HTML selectors.
PS3: Thank you for thinking about this issue and especially for commenting/answering!
I have solved it by adding another setTimeout.
So I replaced the alert (see Question) from
alert(Finished message);
To
setTimeout( function() {
// As an example I used alert in my question and here in this answer.
// This can be offcourse anything else. I use it for instance to sort the results.
alert(Finished message);
}, 0 );
This works for me, but it might not be the best way to deal with it. So I am still looking forward to what more experienced people think about the question or the answer.

Image shows if condition is met

I am making a cookie clicker-esque game and i am making an upgrade bar. One icon starts off invisible and once you have 1 cursor it becomes visible. The problem is it isn't.
I have looked thoroughly and still can't find the bug.
This is in JSFiddle.
Here it is-https://jsfiddle.net/wizviper/mq0qwnvr/
Main Code-
document.getElementById("reinforcedFingerShop").addEventListener(cursorAmount >= 1, function() {
if (reinforcedFingerActive = 0) {
$(this).show();
}
});
addEventListener listens to events but you are assigning a condition to it "cursorAmount >= 1".
I guess you probably want to know when (cursorAmount >= 1) and also (reinforcedFingerActive == 0), please provide the related part of your code, so that we will be able to help you better
UPDATE
You are changing cursorAmount inside "cursorShop" function so the best place to check "reinforcedFingerActive == 0" condition is there.
document.getElementById("cursorShop").onclick = function() {
if (cookies >= cursorPrice) {
cookies = cookies - cursorPrice;
cursorPrice = cursorPrice * 1.15;
cps = cps + 0.1;
updateValue();
cursorAmount = cursorAmount + 1;
if (reinforcedFingerActive == 0) {
$(this).show();
}
}
}
I have not tested but it should work.
I think the problem come from :
if (reinforcedFingerActive = 0) {
Maybe did you forgot the second = ?
Read official MDN addEventListener documentation on how to use this function. First argument is type
A string representing the event type to listen for.
in your code your first argument is cursorAmount >= 1

How do I remove variable randomly using jquery?

I'm trying to find a way to remove variable from certain div on the web using jquery. This does not involve using array. If I can do so with using fadeIn() or search() and remove(), that's even better.
var something = '#img' + count;
on the web, images will be added to div as time passes (using setTimeout). Those images have been assigned to variable (something) and I need to find a way to remove it from certain div on the web. It can be hide, remove, whatever, it has to disappear from user's view randomly (both time and which image will disappear).
Thanks for help and your time in advance.
my function code:
var count = 0;
function foo() {
var xPos = xPosition();
var yPos = yPosition();
var someTime;
$("div").append('<img id="Img" ' + count + ' src = "img.png" style="top:' + yPos + 'px; left: ' + xPos + 'px; " />');
var something = "#Img" + count;
someTime = setTimeout('foo()', randInterval());
$(something).hide();
count++;
if (timeRemaining == 0) {
clearTimeout(someTime);
return;
}
Give all the images a class. You can then use $(".class").length() to get the number of images, pick a random number in this range, and delete that element with .eq().
function addImage() {
var xPos = xPosition();
var yPos = yPosition();
$("div").append($("<img>", {
src: "img.png",
"class": "imageclass",
style: {
top: yPos+"px",
left: xPos+"px"
}
}));
setTimeout(addImage, randInterval());
}
setTimeout(addImage, randInterval());
function removeImage() {
var images = $(".imageclass");
if (images.length) {
var rand = Math.floor(Math.random() * images.length);
images.eq(rand).remove();
}
setTimeout(removeImage, randInterval());
}
setTimeout(removeImage, randInterval());
In my code I'm using separate timers for adding and removing images. If you prefer, you could remove the setTimeout from removeImage(), and just call it from addImage so it will always remove an image whenever it's adding a new one.
Please, never ever append a number to an id and piece together numbered names of things. It is unmaintainable and bad. Use class.
Assign a purpose or functionality to an element or elements by adding a class name to them. If you want to add information to an element, that is great, use data- prefix on the attribute name and it is all legal. data-itemid is an example.
You can query for matching elements with var those = $('.that-class-name'), stored for reuse. From there you can access individual elements using those.eq(0) through those.eq(x.length - 1). For example, if you somehow knew that the 3rd one needs to be removed, then those.eq(3).remove();. If you want to pick through them and only select ones that match a condition, use those.filter(callback).remove(), where callback returns true if the element referred to by this should be removed. If you want to filter those with another selector, .filter will accept a selector too.
Is that what you meant?

Displaying a Random div on Click

I am using the Colorbox Lightbox script to call a hidden div on a page. It works great but there is a catch. I have 15 hidden divs. When a link is clicked I would like a new lightbox to show each time without repeating until all have been shown. I do not know how to do this.
Here is my code to call the lightbox:
$(".colorbox").colorbox({
inline:true
});
Here is the HTML of the hidden divs
<div class="hide">
<div id="lightbox1">
<!-- Content -->
</div>
<div id="lightbox2">
<!-- Content -->
</div>
<!-- etc -->
</div>
How would I call each div at random until all have been shown then start over?
Also is there a way that once divs 1 - 15 have been shown to then show one last div (id="last-div") before restarting?
Note: All divs would be called on a click and I am using jQuery 1.8.2.
I do not know where to start, I have seen scripts using Math.random() but I do not understand enough to make that work.
UPDATE
I have tried Ian's answer but the lightbox is not showing (but I can see in the console log that the script is working)
Originally he has this in his script:
$(selector).show();
which I changed to this:
$(selector).colorbox({inline:true });
What do I need to do to call the lightbox?
Note: No errors are thrown.
So my idea was similar to Eric's, but I wanted to make it work "completely". So instead of storing references to all the divs in an array, I just decided to store an array of ints representing each div. The way I eventually select them with jQuery is "#lightbox + i", so if you don't have this exact structure (where the divs have an id like "lightbox" and an int - from 1 to the last count), then you can use .eq() or nth-child. It won't be the exact same results, but it will have the same random effect, just done in a different way. I found a function that "randomizes" an array - I'm guessing like what Eric's Shuffle does. But here's where I got it from - How to randomize (shuffle) a JavaScript array? . I had to modify it to return a new array instead of modify the one passed to the function. Also, I kept everything in the document.ready scope, instead of the global scope, so things are passed/returned a lot. It worked fine before when I had all and randomed declared globally and didn't pass them around, I just thought this would be "better" since they weren't global.
Here's the fiddle:
http://jsfiddle.net/6qYCL/1/
And here's the Javascript:
$(document).ready(function () {
var all,
randomed;
all = generateAll();
randomed = generateRandomed(all);
$("#generator").on("click", function (evt) {
evt.preventDefault();
randomed = doNext(all, randomed);
});
});
function generateAll() {
// Generates the array of "all" divs to work on
var a = [];
var divs = $(".hide > div.lightbox");
for (var i = 1; i <= divs.length; i++) {
a.push(i);
}
console.log("List of divs available to toggle: " + a);
return a;
}
function generateRandomed(all) {
// Randomizes the original array
randomed = fisherYates(all);
console.log("Setting randomized array: " + randomed);
return randomed;
}
function doNext(all, randomed) {
$(".lightbox, #last-div").hide();
if (randomed.length < 1) {
console.log("All lightboxes toggled, showing last, then starting over");
$("#last-div").show();
randomed = generateRandomed(all);
} else {
var next = randomed.shift();
var selector = "#lightbox" + next;
console.log("Showing " + selector);
$(selector).show();
console.log("What's left: " + randomed);
}
return randomed;
}
// Randomizes an array and returns the new one (doesn't modify original)
function fisherYates ( myArray ) {
var return_arr = myArray.slice(0);
var i = return_arr.length;
if ( i == 0 ) return false;
while ( --i ) {
var j = Math.floor( Math.random() * ( i + 1 ) );
var tempi = return_arr[i];
var tempj = return_arr[j];
return_arr[i] = tempj;
return_arr[j] = tempi;
}
return return_arr;
}
It accounts for getting to the end of the list and display #new-div like you mentioned, then starting the process over. If you look in your browser's console, you can "watch" what's happening during initialization and when clicking the link.
I think this is close to what you were looking for. I'm not sure which is a better solution - storing references to the elements or just an array of ints to loop through and eventually find. I know there are many variations on how to do this - when/how to store the counting stuff, when/how to randomize the array or retrieve a random value (and how to keep track of which has been used), where to store all references, and plenty more. I hope this at least helps!
Create an array of all of them, then shuffle that array, then pull the next one each time you get a click. When you run out, you can repopulate the array if necessary.
Something like this (using the Shuffle method from this source):
Fiddle
var array = $(".hide div").toArray(); // Add all divs within the hide div to an array
var randomArray = Shuffle(array); // Shuffle the array
$("a").click(function() {
if (randomArray.length > 0)
alert(randomArray.shift().innerHTML); // Show contents of div, as an example
else
alert("None left!");
return false;
});
The solution below works by passing an array of elements to a function. As each div is displayed it is taken out of the array. Then from the divs left in the array the next one is picked at random.
// call this function on page load
function begin( ) {
var arr = $(".hide div").toArray();
// further elements can be added to arr i.e. last-div
showDivs( arr.length, arr );
}
// begin displaying divs
function showDivs( numberOfDivs, divArray ) {
var i, lastDiv;
function nextDiv( ) {
// depending on number of slides left get random number
i = randomInt( numberOfDivs );
if( lastDiv ) { $(lastDiv).hide() };
$( divArray[ i ] ).fadeIn( 3000 );
// now that this div has been displayed
// remove from array and cache
lastDiv = divArray.splice( i, 1 );
numberOfDivs--;
// no more divs to display
if( numberOfDivs == 0 ) { return };
setTimeout( nextDiv, 4000);
}
setTimeout( nextDiv, 1000);
}
// calculate next random index
function randomInt( divsLeft ) {
var i = Math.random() * divsLeft;
return Math.round( i );
}
Fiddle here

How do I change the order of several tables based on mouse wheel scrolling in jQuery?

I have a div (#thelist) that contains a bunch of html tables. When the mousewheel is turned i want the first table to be removed and added to the bottom. (And the other way around if the wheel is turned in the other direction).
For some reason the code below works also from my understanding the list should juts get longer and longer. And since i don't understand why it works this way i can't get it to work the other way around...
Any help ? Thank you!!!
$("#thelist").bind("mousewheel",function(ev, delta)
{
if (delta > 0)
{
var children = $("#thelist").children('table');
var tmpChild = children[0];
children.push(tmpChild);
}
if (delta < 0)
{
// How to do this, btw ?
}
$("#thelist").html(children);
}
I'm not sure how that would work either, but it could be cleaned up a little using the Javascript Array methods.
pop - Remove the last item from the array and return it.
push - Add the item to the end of the list.
shift - Remove the first item from the array and return it.
unshift - Add the item to the beginning of the list.
So your code would look like:
var children = $("#thelist").children('table');
if(delta > 0)
{
var tmpChild = children.shift();
children.push(tmpChild);
}
if(delta < 0)
{
var tmpChild = children.pop();
children.unshift(tmpChild);
}
The pop() method should remove entries in your array one by one and add splice() (see the EDIT) them to the top:
if(delta < 0){
var child = children.pop();
children.unshift(child);
}
And you should put the children declaration and initialization statement before the if.
And use a if/else if
$("#thelist").bind("mousewheel",function(ev, delta) {
var children = $("#thelist").children('table');
if (delta > 0){
var tmpChild = children[0];
children.push(tmpChild);
}else if (delta < 0) {
var tmpChild = children.pop();
children.unshift(tmpChild);
}
$("#thelist").html(children);
}
EDIT :
you should use the unshift() instead of splice()
I'd go for something like this, to more clearly convey our intentions, "take the first child of #thelist and put it at the end of #thelist"
$("#thelist").bind("mousewheel",function(ev, delta)
{
var list = $("#thelist");
if (delta > 0)
{
list.children('table').first().appendTo(list);
}
if (delta < 0)
{
list.children('table').last().prependTo(list);
}
});
I suspect that this may also be a bit more efficient since it just rearranges the existing DOM elements rather than calling html() to update the whole content of the list. The effect may be negligible, though.

Categories

Resources