I am attempting to add next/prev and then swipe events to a bootstrap modal image gallery. The thumbnails are displayed in a grid so when I try closest(), siblings(), and next() I am only able to go to the images below and above in the same column and not the other columns in the grid.
Each thumbnail has an id with the images ID in the database. ie:
<a class="image-gallery-item" id="img-1002" href="#showImageModal" data-toggle="modal" onclick="..."><img src="..." /></a>
<a class="image-gallery-item" id="img-4664" href="#showImageModal" data-toggle="modal" onclick="..."><img src="..." /></a>
Every link passes the images src, caption, and ID to a function which changes out the info displayed the modal. All that works fine, I just can't seem to get next/prev working when trying to trigger the next item.
Ideally, instead of using next() and closest() and sibling() methods, I would LIKE to just target the ID greater than the current id for first next and lesser than the current ID for the first previous and trigger a click if the element exists.
Thanks.
UPDATE
Per #Ersian's suggestion, I created an array and cycle thru the images by index. They're still going by column but at least they're moving to the next column after. This will present a little confusion for users, I feel, who will expect the images to display left to right before going to the next row of square thumbnails.
$('.image-gallery-item').modal('hide');
setTimeout(function () {
var thisIMG = $("#imgid").html();
var imgs = document.getElementsByClassName("image-gallery-item");
var $imgvalues = Array.prototype.map.call(imgs, function (el) {
return el.id;
});
index = $imgvalues.indexOf(thisIMG);
if (index >= 0 && index < $imgvalues.length - 1)
nextItem = $imgvalues[index + 1];
$('#' + nextItem).trigger('click');
}, 1000);
UPDATE - WORKING CODE
Found the solution by adding sort to the array and then looped the next/prev if hitting the end or start of items with the class image-gallery-item. I'll post the working code as an answer in case anyone else finds this question and wants to make a bootstrap modal image gallery with gridalicious, isotope, or masonry layouts with columns.
Keep in mind you will need to add buttons with show-next-image and show-previous-image classes to your modal. After that, the following code will let you cycle thru images with the class image-gallery-item.
$('#show-next-image, #show-previous-image').click(function () {
if ($(this).attr('id') == 'show-previous-image') {
$('#showImageModal').modal('hide');
setTimeout(function () {
var thisIMG = $("#imgid").html();
var imgs = document.getElementsByClassName("image-gallery-item");
var $imgvalues = Array.prototype.map.call(imgs, function (el) {
return el.id;
});
var lastIMG = $('.image-gallery-item').length;
$imgvalues.sort();
index = $imgvalues.indexOf(thisIMG);
if (index <= lastIMG - 2) {
nextItem = $imgvalues[index + 1];
} else {
nextItem = $imgvalues[0];
}
$('#' + nextItem).trigger('click');
}, 1000);
} else {
$('#showImageModal').modal('hide');
setTimeout(function () {
var thisIMG = $("#imgid").html();
var imgs = document.getElementsByClassName("image-gallery-item");
var $imgvalues = Array.prototype.map.call(imgs, function (el) {
return el.id;
});
var lastIMG = $('.image-gallery-item').length;
$imgvalues.sort();
index = $imgvalues.indexOf(thisIMG);
if (index >= 1) {
nextItem = $imgvalues[index - 1];
} else {
nextItem = $imgvalues[lastIMG - 1];
}
$('#' + nextItem).trigger('click');
}, 1000);
}
});
Related
function nextSlideFunc() {
var currentSlide = $(".slide.active-slide");
var currentSlideIndex = $(".slide.active-slide").index();
var nextSlideIndex = currentSlideIndex + 1;
var nextSlide = $(".slide").eq(nextSlideIndex);
$("#nextBtn").on("click", function(e) {
e.preventDefault();
currentSlide.removeClass("active-slide");
if(nextSlideIndex === $(".slide").last().index() + 1) {
//stay at last slide when reached.
$(".slide").eq(nextSlideIndex - 1).addClass("active-slide");
} else {
nextSlide.addClass("active-slide");
}
});
}
After I clicked on the next button, the slide goes to the next slide which is what I want, but when I continue to click, it just stopped going forward.
I checked my HTML in the dev tool, it has the class name "active-slide" on one of the slides which fulfills the condition, but I'm not sure why it's not working.
As for the previous button, it's not removing class "active-slide" like it's supposed to, any idea why this is happening?
You have to set your variables inside the listener of your click event:
https://codepen.io/anon/pen/OxMxwd
$("#prevBtn").on("click", function(e) {
var currentSlide = $(".slide.active-slide");
var currentSlideIndex = $(".slide.active-slide").index();
var prevSlideIndex = currentSlideIndex - 1;
var prevSlide = $(".slide").eq(prevSlideIndex);
}
That way you will calculate your index and next index every time you click the button. The way you did it, is calculating it once and reusing it over and over again, so you will do the same thing on the same index over and over again.
I've created a script that attaches an event listener to a collection of pictures by default. When the elements are clicked, the listener swaps out for another event that changes the image source and pushes the id of the element to an array, and that reverses if you click on the swapped image (the source changes back and the last element in the array is removed). There is a button to "clear" all of the images by setting the default source and resetting the event listener, but it doesn't fire reliably and sometimes fires with a delay, causing only the last element in a series to be collected.
TL;DR: An event fires very unreliably for no discernible reason, and I'd love to know why this is happening and how I should fix it. The JSFiddle and published version are available below.
I've uploaded the current version here, and you can trip the error by selecting multiple tables, pressing "Cancel", and selecting those buttons again. Normally the error starts on the second or third pass.
I've also got a fiddle.
The layout will be a bit wacky on desktops and laptops since it was designed for phone screens, but you'll be able to see the issue and inspect the code so that shouldn't be a problem.
Code blocks:
Unset all the selected tables:
function tableClear() {
//alert(document.getElementsByClassName('eatPlace')[tableResEnum].src);
//numResTables = document.getElementsByClassName('eatPlace').src.length;
tableArrayLength = tableArray.length - 1;
for (tableResEnum = 0; tableResEnum <= tableArrayLength; tableResEnum += 1) {
tableSrces = tableArray[tableResEnum].src;
//alert(tableSrcTapped);
if (tableSrces === tableSrcTapped) {
tableArray[tableResEnum].removeEventListener('click', tableUntap);
tableArray[tableResEnum].addEventListener('click', tableTap);
tableArray[tableResEnum].src = window.location + 'resources/tableBase.svg';
} /*else if () {
}*/
}
resTableArray.splice(0, resTableArray.length);
}
Set/Unset a particular table:
tableUntap = function () {
$(this).unbind('click', tableUntap);
$(this).bind('click', tableTap);
this.setAttribute('src', 'resources/tableBase.svg');
resTableArray.shift(this);
};
tableTap = function () {
$(this).unbind('click', tableTap);
$(this).bind('click', tableUntap);
this.setAttribute('src', 'resources/tableTapped.svg');
resTableArray.push($(this).attr('id'));
};
Convert the elements within the 'eatPlace' class to an array:
$('.eatPlace').bind('click', tableTap);
tableList = document.getElementsByClassName('eatPlace');
tableArray = Array.prototype.slice.call(tableList);
Table instantiation:
for (tableEnum = 1; tableEnum <= tableNum; tableEnum += 1) {
tableImg = document.createElement('IMG');
tableImg.setAttribute('src', 'resources/tableBase.svg');
tableImg.setAttribute('id', 'table' + tableEnum);
tableImg.setAttribute('class', 'eatPlace');
tableImg.setAttribute('width', '15%');
tableImg.setAttribute('height', '15%');
$('#tableBox').append(tableImg, tableEnum);
if (tableEnum % 4 === 0) {
$('#tableBox').append("\n");
}
if (tableEnum === tableNum) {
$('#tableBox').append("<div id='subbles' class='ajaxButton'>Next</div>");
$('#tableBox').append("<div id='cazzles' class='ajaxButton'>Cancel</div>");
}
}
First mistake is in tapping and untapping tables.
When you push a Table to your array, your pushing its ID.
resTableArray.push($(this).attr('id'));
It will add id's of elements, depending on the order of user clicking the tables.
While untapping its always removing the first table.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift
resTableArray.shift(this);
So, when user clicks tables 1, 2, 3. And unclicks 3, the shift will remove table 1.
Lets fix this by removing untapped table
tableUntap = function () {
$(this).unbind('click', tableUntap);
$(this).bind('click', tableTap);
this.setAttribute('src', 'http://imgur.com/a7J8OJ5.png');
var elementID = $(this).attr('id');
var elementIndex = resTableArray.indexOf(elementID);
resTableArray.splice(elementIndex, 1);
};
So you were missing some tables after untapping.
Well lets fix tableClear,
You have a array with tapped tables, but you are searching in main array.
function tableClear() {
tableLen = resTableArray.length;
for (var i = 0; i < tableLen; i++) {
var idString = "#" + resTableArray[i];
var $element = $(idString);
$element.unbind('click', tableUntap);
$element.bind('click', tableTap);
$element.attr("src", 'http://imgur.com/a7J8OJ5.png');
}
resTableArray = [];
}
Im searching only tapped tables, and then just untap them and remove handlers.
fiddle: http://jsfiddle.net/r9ewnxzs/
Your mistake was to wrongly remove at untapping elements.
I have a <div> and i want to add images into it. The number of images will vary randomly.
here is what i am trying to do
$(document).ready(function () {
var img = document.getElementById("img");
$('#button').click(function () {
var randomnumber = Math.floor(Math.random() * 11) + 1;
for (var i = 1; i < = randomnumber; i++) {
$(this).append(img);
}
});
});
But it is not working. Please help
here is my code JSFiddle
You should probably use clone as simon suggests, or you can create new images:
function getImage(){
var img = new Image();
img.src = "http://cdn.acidcow.com/pics/20110830/lolcats_ever_13.jpg"
img.width = 200;
return img;
}
var rand = Math.floor(Math.random() * 11) + 1,
imgContainer = $("#imgContainer"),
i;
$("#imgNo").text(rand);
for (i=0; i<rand; i++){
imgContainer.append(getImage());
}
fiddle
uhm, you aren't defining any new images. I am not sure from where you are getting your images. If you have differeny images, you can use the next loop. Besides that, the this points to the #button element. Not sure which item it is, but if it's an input button, then it won't work. you have to use a div or article or section ... as target.
$(document).ready(function () {
$('#button').click(function () {
// random number
var randomnumber = Math.floor(Math.random() * 11) + 1;
// insert images
for (var i = 1; i < = randomnumber; i++) {
// create a new img - element
var img = document.createElement('img');
// give it an id
img.attr("id","img_" + i);
// source, link
img.attr("src","your_URL_here");
// put newly created image in the div with id yourDivIdHere
$('#yourDivIdHere').append(img);
}
});
});
the id has to be unique, that's why i'm using the index of the for loop for the id of the newly created element. Having same id for multiple HTML elements can lead to issues.
#yourDivIdHere means the div with the id yourDivIdHere, like
<div id="yourDivIdHere"></div>
When you are re-using the button, simply clear the content by using $('#yourDivIdHere').empty() method if you don't want to see that old images are still there after clicking on the button.
You need to clone the image:
$(this).append( $(img).clone() );
Your way always puts the same image (only one instance!) inside of div random amount of times. So in the end it is only one image.
If you clone it every time then you will have N amount of images
You are getting elements by id, so appended element is always the same element with id="img". Read about jQuery find() to find all elements.
I have this simple next and previous function that i wrote but i am having one simple issue. On the last slider on click next, it shows a blank slider then on click next it starts all over as it is supposed to. What am i missing? Below is the jquery code;
$('div.contsliders').each(function(e) {
if (e != 0)
$(this).hide();
});
$('span.next').click(function(){
if ($('div.contsliders:visible').next().length != 0)
$('div.contsliders:visible').next().fadeIn(1000).prev().hide();
else {
$('div.contsliders:visible').hide();
$('div.contsliders:first').fadeIn(1000);
}
return false;
});
$('span.prev').click(function(){
if ($('div.contsliders:visible').prev().length != 0)
$('div.contsliders:visible').prev().fadeIn(1000).next().hide();
else {
$('div.contsliders:visible').hide();
$('div.contsliders:last').fadeIn(1000);
}
return false;
});
HERE IS THE JSFIDDLE LINK
I will really appreciate it mates, thanks.
That is because when it checks for the following condition for the div which you think it is the last using $('div.contsliders:visible').next().length gives .contsnextprev (hence length will still be 1 instead of 0 as assumed) so it shows that one instead of moving to the beginning, which happens when you click on it again. It is because .contsnextprev is the div next to the last slide #five.
if ($('div.contsliders:visible').next().length != 0)
$('div.contsliders:visible').next().fadeIn(1000).prev().hide();
You can change it to:
var $nxt = $('div.contsliders:visible').next('.contsliders');
if ($nxt.length != 0)
$nxt.fadeIn(1000).prev().hide();
Demo
Infact you can simplify this to just one handler as well:
$('div.contsliders:gt(0)').hide(); //Hide all but the first one
var $allSlides = $('div.contsliders'),
traverseDefault = "first", //set the defaults
actionDefault ="next";
$('span.next, span.prev').click(function(){
var traverse = traverseDefault,
action = actionDefault;
if($(this).is('.prev')){ //if action is prev
traverse = "last"; //set traverse to last in case nothing is available
action = "prev"; //set action to prev
}
var $curr = $allSlides.filter(':visible'), //get the visible slide
$nxtTarget = $curr[action](".contsliders"); //get the next target based on the action.
$curr.stop(true, true).fadeIn(1000).hide(); //hide current one
if (!$nxtTarget.length){ //if no next
$nxtTarget = $allSlides[traverse](); //based on traverse pick the next one
}
$nxtTarget.stop(true, true).fadeIn(1000); //show the target
});
Demo
I'm currently working on a site that is using ajax to pull content in when an anchor link is clicked. I'm hoping to create a custom next/prev button using an array of predefined page links.
I'm trying to use a array as a counter to move through the pages when the next button is clicked. But I would like to use the current href attribute as a starting point then would move through the array by plus or minus one depend which button is click.
Here's the current codepen I'm working on http://codepen.io/veryrobert/pen/ocIhl
HTML:
<a id="value1" href="one.html">NEXT</a>
<a id="value2" href="">PREV</a>
Jquery:
$(function(){
var pages = [ "one.html", "two.html", "three.html", "four.html" ];
var prev = "#value2";
var next = "#value1";
// This works as a starting point
counter = 0;
// But I'd really like this to be the starting point
// counter = $(next).attr("href");
$(next).click(function(e){
e.preventDefault();
counter = (counter + 1) % pages.length;
});
$(prev).click(function(e){
e.preventDefault();
counter = (counter - 1) % pages.length;
$(prev).attr( "href", counter );
});
});
I'm not really great a JavaScript so please forgive me if this is a stupid approach or I'm going about this completely the wrong way.
You can try this
function getCounter(element, array) {
var href = element.getAttribute('href');
for ( var i=0; i < array.length; i++) {
if ( array[i] === href ) {
return i;
}
}
return -1;
}
You use it like this:
counter = getCounter( document.getElementById(next), pages );
Note: If you intend to use jQuery I am not sure what it returns when you call $(next).attr('href').
element.getAttribute('href') would return 'one.html' but
element.href would return 'host.com/one.html'