This is my first time on stackoverflow, I really hope someone can help. I'm fairly novice at coding, so I hope my query is simple to solve.
I have created a simple javascript image gallery, where if you click on the left or right arrow it loops to show the next image in my array list. I also have quicklinks that jump to the specific images in this list. How can I get my next/back links to then continue on, to show the next image from the one currently selected? E.g if I have jumped to gallery image 3, for it to then show the next image along from it in the list gallery image 4, and not gallery image 2.
Below are samples of my code.
Thanks so much in advance for your help.
Here is my script:
var num=0;
imgArray = [
['../00_assets/gallery/work_00.jpg','Gallery', '1 of 6',],
['../00_assets/gallery/work_01.jpg','Gallery', '2 of 6',],
['../00_assets/gallery/work_02.jpg','Gallery', '3 of 6'],
['../00_assets/gallery/work_03.jpg','Gallery', '4 of 6'],
['../00_assets/gallery/work_04.jpg','Gallery', '5 of 6'],
['../00_assets/gallery/work_05.jpg','Gallery', '6 of 6'],
]
function slideshow(slide_num) {
document.getElementById('mypic').src=imgArray[slide_num][0];
document.getElementById('mypic').alt=imgArray[slide_num][1];
document.getElementById('number').innerHTML=imgArray[slide_num][2];
}
function slideshowUp() {
num++;
num = num % imgArray.length;
slideshow(num);
}
function slideshowBack() {
num--;
if (num < 0) {num=imgArray.length-1;}
num = num % imgArray.length;
slideshow(num);
}
Here is my HTML (I've taken out the bits that do not seem relevant):
<div align="left">
<!-- First image in array list is here -->
<img src="../00_assets/gallery/work_00.jpg" id="mypic" name="mypic" alt="Gallery">
<!-- Previous link is here -->
←
<!-- First image number is here -->
<div id="number">1 of 9</div>
<!-- Next link is here -->
→
<!-- Three quicklinks are link is here -->
Quicklink 1 |
Quicklink 2 |
Quicklink 3 |
Thank you so much.
You should update your num variable whenever you change the current slide.
Then, when a quicklink is clicked, it will have the current slide for the other methods (slideshowUp and slideshowBack) to work with and keep the navigation as expected.
In other words:
function slideshow(slide_num) {
num = slide_num; // add this line
document.getElementById('mypic').src=imgArray[slide_num][0];
document.getElementById('mypic').alt=imgArray[slide_num][1];
document.getElementById('number').innerHTML=imgArray[slide_num][2];
}
Related
I have a ngFor loop which iterates over an array of famous people (see below), this is fine but I would now like to add in image gallery which is where things get tricky. Each person will have 2 photo albums, the albums will be simply strings of urls to remote photos - the first problem is that I would like to be able to click the image tag (or element close by) and on each click I want the image src to change to the next image, when it reaches the end ideally I would like it to go back again to the start or just stop.
this is tricky enough - but each person will have a secondary photo album which is much the same as the first i.e Array however - it gets activated when the user clicks the changeAlbum() which is on a thumbnail image below - the idea is that the first image of the array not in use (as clicking changeAlbum() makes it inactive ) populates this thumbnail and the gallery then uses the images from the secondary gallery - so essentially its like a complex toggle() between the 2 galleries combined with a click to iterate over the array of each gallery - it might even be cool if when you iterate through the first gallery that it auto switches to the secondary one and vice versa
Im not entirely sure how to approach it though - the html and the json struct are the only solid things I have in place.
<div class="card" *ngFor="let c of item" >
<div class="card-content">
<div class="card-image">
<img (click)="changePhoto()" [src]="{{ output image here from the click }}" />
</div>
<div class="card-titles">
<h1>
{{ c.name }}
</h1>
</div>
<div class="card-image">
<img (click)="changeAlbum()" [src]="{{ show image from album not in use here}}" />
</div>
</div>
</div>
The data structure I have so far is like this
item = [{
id: 1,
name: "Joe Jimbob",
album_Main: [{
selected: true,
"https://via.placeholder.com/250",
"https://via.placeholder.com/250",
"https://via.placeholder.com/250",
"https://via.placeholder.com/250",
}],
album_Secondary: [{
selected: false,
"https://via.placeholder.com/250",
"https://via.placeholder.com/250",
"https://via.placeholder.com/250",
"https://via.placeholder.com/250",
}]
}]
This is also relatively solid but im very open to any help anyone can give
changeAlbum(item:any) :void {
if( item.album_Main.selected ) {
item.album_Main.selected == false
} else {
item.album_Secondary.selected == false
}
}
and the change...
changePhoto(photos: Array<string>) :void {
// not sure how to interate this one by one on click
console.log( photos.length )
}
Check this Stackblitz example I made based on your code: https://stackblitz.com/edit/angular-pk6cu8
The important changes are these in app.component.ts
photoIndex = 0;
personIndex = 0;
selectedAlbum = this.item[0].album_Main;
altAlbum = this.item[0].album_Secondary;
isMainAlbumActive = true;
changePhoto() {
if (this.photoIndex < this.selectedAlbum.length - 1) {
this.photoIndex++;
} else {
this.photoIndex = 0;
}
}
changeAlbum() {
if (this.isMainAlbumActive) {
this.selectedAlbum = this.item[this.personIndex].album_Secondary;
this.altAlbum = this.item[this.personIndex].album_Main;
} else {
this.selectedAlbum = this.item[this.personIndex].album_Main;
this.altAlbum = this.item[this.personIndex].album_Secondary;
}
this.isMainAlbumActive = !this.isMainAlbumActive;
}
I am trying to create a magazine style gallery which can fetch a number of JPGS (18) and render them in 2 divs. A Left and right button would then be used to load the next 2 pages. The first page would be the front-over which would be closed. Then afterwards the pages would be side by side like a spread.
I have created the following which is semi working, it loads in a list of JPGs and the next button pushes the image to the div and then iterates. The main issue is that when pressing the next button to change the page its iterating 1 at a time instead of changing to the next 2 pages.
I tried to change the +1 to a +2 in the for loop but it loads the first 2 page spread fine, then the rest it only iterates 1 page at a time.
Could anyone give me some advice on how this can be improved & change 2 pages at a time?
Here is a codePen to make this a bit clearer:
https://codepen.io/nolimit966/pen/JVoPJq
Thank you
var pages = [
{"name":"img1", "src":"images/1.jpg"},
{"name":"img2", "src":"images/2.jpg"},
{"name":"img3", "src":"images/3.jpg"},
{"name":"img4", "src":"images/4.jpg"},
{"name":"img5", "src":"images/5.jpg"},
{"name":"img6", "src":"img/prod-6.png"},
{"name":"img7", "src":"img/prod-7.png"},
{"name":"img8", "src":"img/prod-8.png"},
{"name":"img9", "src":"img/prod-9.png"},
];
imgIndex = 0;
document.getElementById("image2").src = pages[0].src;
document.getElementById("nextBtn").addEventListener("click", function(){
var page2 = document.getElementById("image1")
if(pages.length > imgIndex+1){
imgIndex++;
// page1.classList.toggle('is-active');
document.getElementById("image1").style.display = "block";
document.getElementById("image1").src = pages[imgIndex].src;
document.getElementById("image2").src = pages[imgIndex+1].src;
} else {
console.log("its zero");
imgIndex = 0;
}
});
<button id="prevBtn">Previous</button>
<button id="nextBtn">Next</button>
<div id="container">
<div id="page1">
<img src="" id="image1" alt="" style="display:none;"/>
</div>
<div id="page2">
<img src="" id="image2" alt=""/>
</div>
</div>
You have to add two to the index number each time when index number is not zero (not cover page)
When current page is at cover page (imgIndex=0)
imgIndex 0 -> 1: Display imgIndex 1 and 2
When current page is not at cover page (imgIndex>0)
imgIndex 1 -> 3: Display imgIndex 3 and 4
imgIndex 3 -> 5: Display imgIndex 5 and 6
So instead of
imgIndex++;
Try this
if(imgIndex == 0){
imgIndex++;
}else {
imgIndex += 2;
}
I have a carousel slider in angular, I have ng-repeat with orderBy:'id' and when i click next slide button, id change it.
Look at my JSFiddle here
I have div with ng-repeat:
<div class="slide" ng-repeat="slide in slides | orderBy:'id*1'">
<p>
{{ slide.value.name }}
</p>
</div>
And I have function to sort new item list:
$scope.nextSlide = () => {
let items = $scope.slides
let countItems = items.length
for (let i = 0; i < countItems; i++) {
let z = items[i].id % countItems;
items[i].id = z + (countItems - 1);
}
}
And my problem:
First occurs animate, then scope new ordering item and blink to new slide. Any ideas? How can I animated reordering in ng-repeat?
Why don't you reorder first, so that the first slides are in the 'normal' order and when you click next, the 'reordered' slides show up...
I just don\t understand why you would reorder on "next()"
I think you are tackling the problem the wrong way, about your animation.
Let's say you have 2 items always visible.
1 | 2 | 3 | 4
When you click next, it should:
- slide on the left (animation)
- THEN, once animation is done, you do:
- reorder items (2 first at the back) AND - at the same time - recenter the list.
I think in your small demo, you just forget to recenter the list.
I guess it all depends on the way you are doing your animation as well.
Currently I have the following:
<div class="ArrowLeft"></div>
<div class="ArrowRight"></div>
<div class="ReviewComment">
<p>“Thank you for making selling our car so painless.”</p>
</div>
<div class="ReviewName">
</div>
</div>
I've been looking at different ways to get it to work so that when click one of the "Arrow" buttons, it replaces the content in "ReviewComment". However so far i've only managed to get it to replace the content going one way. So for example when it gets to the 5th div's content, it won't then click back to the first one?
I've tried multiple different ways of doing this but I can't seem to get it to cycle through as I would like.
I also can't seem to get it to replace the content of ReviewName at the same time as ReviewComment.
Keep track of what comment you're on, and how many comments there are. If total comments == current comment, go back to the first one. Ex code:
var comments = ['comment 1', 'comment 2', 'comment 3', 'comment 4', 'comment 5'];
var currentComment = 0;
var totalComments = comments.length - 1;
$('.arrowRight').click(function(){
currentComment++;
if(currentComment > totalComments){
// past last comment, load first
$('.comments .comment').html(comments[0]);
currentComment = 0;
}else{
$('.comments .comment').html(comments[currentComment]);
}
console.log(currentComment);
})
$('.arrowLeft').click(function(){
currentComment--;
if(currentComment < 0){
// past first comment, load last
$('.comments .comment').html(comments[totalComments]);
currentComment = totalComments;
}else{
$('.comments .comment').html(comments[currentComment]);
}
console.log(currentComment);
})
T̶h̶i̶s̶ ̶c̶o̶d̶e̶ ̶a̶s̶ ̶i̶s̶ ̶w̶i̶l̶l̶ ̶n̶o̶t̶ ̶w̶o̶r̶k̶ I don't know how you're fetching your comments. But you can transplant the logic from the example in to your own code. Hopefully this gets you on your way.
I'll try and edit with a js fiddle shortly.
UPDATE
Working fiddle here: https://jsfiddle.net/mpr9j6sd/
I have a number of divs floating in several rows. The divs contain text-previews and a link to slide down the full content (see http://jsfiddle.net/yDcKu/ for an example).
What happens now: When you slide down the content-div it opens right after the connected preview.
What I want to happen: Open the content-div after the last div in the row.
I assume the could be done by:
1. find out which div is the last one in the row of the activated preview,
2. add an id to this div and
3. append the content-div to this div.
I have a solution for steps 2 und 3 using jQuery but no guess how to do the first step.
I can manage to get the document width and the x- and y-value of each div but I have no idea how to find out which div has the highest x- as well the highest y-value and as well is in the row of the activated preview-div.
Any idea anyone? Thanks
Here is an example that does what you want. I simplified your code, so you don't have to manually ID every entry and preview.
http://jsfiddle.net/jqmPc/1/
It's a little complicated. Let me know if you have questions.
Basically, when the window is resized, the script goes through and finds the first preview in each row by finding the preview with the same left offset as the very first one. It then adds a class last to the entry before (previous row) and class first to this preview. I do css clear: left on both of these so that everything wraps normally when the entries open.
I made your code generic, without IDs:
<div class="preview">
<p>Some preview text <a class="trigger" href="#">…</a></p>
</div>
<div class="entry">
<div class="close_button">
<a class="close" href="#">×</a>
</div>
<p>Some content text.</p>
</div>
This makes you not have to write the same code over and over.
The open/close script:
$('.trigger').click(function() {
$('.openEntry').slideUp(800); // Close the open entry
var preview = $(this).closest('.preview'); // Grab the parent of the link
// Now, clone the entry and stick it after the "last" item on this row:
preview.next('.entry').clone().addClass('openEntry').insertAfter(preview.nextAll('.last:first')).slideDown(800);
});
// Use "on()" here, because the "openEntry" is dynamically added
// (and it's good practice anyway)
$('body').on('click', '.close', function() {
// Close and remove the cloned entry
$('.openEntry').slideUp(800).remove();
});
This could be simplified a bit I'm sure, especially if you were willing to reformat your html a little more, by putting the entry inside of the preview element (but still hidden). Here is a slightly simpler version, with the html rearranged:
http://jsfiddle.net/jqmPc/2/
(I also color the first and last element on the line so you can see what is going on)
You could just get the last div in the array after calling getElementsByTagName.
var divArray = wrapperDiv.getElementsByTagName("div");
if(divArray.length > 0)
var lastDiv = divArray[divArray.length-1];
else
console.log("Empty!");
i am not able to correctly understand your question, but if you want to find out last div element in the document then you can do something like this
$("div:last")
so this will give you last div of the document
Reference:
http://api.jquery.com/last-selector/
$([1,2]).each(function(idx,el) {
$("#entry" + el).hide().insertAfter("div.entry:last");
$("#trigger" + el).click(function() {
$("#entry" + el).slideDown('800');
});
$("#close" + el).click(function() {
$("#entry" + el).slideUp('800');
});
});
http://jsfiddle.net/yDcKu/11/
I got same problem as yours, and I have been redirected to this question. But I think the answer is too complicated to my need. So I made my own way. Supposedly, you get your div list from a JSON, you can do this:
product[0] = {id: "name1", text: "text1"}
product[1] = {id: "name2", text: "text2"}
product[2] = {id: "name3", text: "text3"}
private getLastElement(id, products) {
const getTop = (id) => $("#" + id).position().top;
let itemPos = getTop(id);
let itemIndex = products.map(x => x.id).indexOf(id);
let lastID = itemIndex;
while (lastID < products.length - 1) {
if (getTop(products[lastID + 1].id) > itemPos) break;
lastID++;
}
return products[lastID].id;
}
But you can also find out by gathering all id inside your wrapper.
It works by scanning next id's row position, and return the last id of the same row.
I was looking for the same but on a single element to add style on first and last elements. #Jeff B answer helped me so alter and use it for me on one element. So the search phrase 'Get the last div in a row of floating divs' and someone looking for the same, this code may helpful:
Fiddle: https://jsfiddle.net/kunjsharma/qze8n97x/2/
JS:
$(function() {
$(window).on('resize', function() {
var startPosX = $('.preview:first').position().left;
$('.preview').removeClass("first last");
$('.preview').each(function() {
if ($(this).position().left == startPosX) {
$(this).addClass("first");
$(this).prevAll('.preview:first').addClass("last");
}
});
$('.preview:last').addClass("last");
});
$(window).trigger('resize');
});
CSS:
.preview {
float: left;
}
HTML:
<div class="preview">
<p>Some preview text</p>
</div>
<div class="preview">
<p>Some preview text</p>
</div>
<div class="preview">
<p>Some preview text</p>
</div>
<div class="preview">
<p>Some preview text</p>
</div>