Imtiaz Ahmed
Imtiaz Ahmed

Reputation: 323

Change multiple image src with jquery in a circular fashion

I have 3 img tag in my html file. I want to change all of the 3 img's src with button click from an array where I stored 9 images src link.

So when the page loads for the very first time it will show first 3 images[0,1,2]. Then on each next-btn click it will change images to the next 3 [3,4,5], [6,7,8]. And when the prev-btn is clicked it will go back to 3 images.

please help me with that. and please suggest me is there any other way(better) around it?

Here is what I've tried so far:

const $img1 = $("#img1")
const $img2 = $("#img2")
const $img3 = $("#img3")
const $nextBtn = $("#next-btn")
const $prevBtn = $("#prev-btn")


$.get("https://someApiLink.com/all.json", function (characters) {
    const charactersList = []
    for (let i=0; i<characters.length; i++) {
        // here casts is another array to match predefined characters with the 
        // character from the api
        if (casts.includes(characters[i].name)) {
            charactersList.push(characters[i])
        }
    } 
    $img1.attr("src", charactersList[0].image)
    $img2.attr("src", charactersList[1].image)
    $img3.attr("src", charactersList[2].image)

    // it will only switch back and forth 2 images on the first img tag     
    $nextBtn.on("click", function () {
        const src = ($img1.attr("src") === charactersList[0].image)
        ? charactersList[1].image
        : charactersList[0].image;
        $img1.attr("src", src)
    })
})

Upvotes: 0

Views: 515

Answers (2)

SkillGG
SkillGG

Reputation: 686

You can store a sort of "page number" for example page to keep track of what page are they on and increase/decrease it on each "press".

let page = 0;
const imgInSet = 3;

const reloadImages = ()=>{
    const imgSet = Math.abs(page); // we get abs if someone do more previous than nexts
    $img1.attr("src", characterList[imgSet*imgInSet].image); // get first image
    $img2.attr("src", characterList[imgSet*imgInSet+1].image); // get second image
    $img3.attr("src", characterList[imgSet*imgInSet+2].image); // get third image
}

$nextBtn.on("click", ()=>reloadImages(++page)); // do reloadImages after adding 1 to roll

$prevBtn.on("click", ()=>reloadImages(--page);) // do reloadImages after removing 1 from roll

You could add a numberOfPages value to restrict the number of available pages like that:

let page = 0;
const imgInSet = 3;
const numberOfPages = Math.floor(characterList.length/3);

const reloadImages = ()=>{
    const imgSet = Math.abs(page)%numberOfPages; // we get abs if someone do more previous than nexts
    $img1.attr("src", characterList[imgSet*imgInSet].image); // get first image
    $img2.attr("src", characterList[imgSet*imgInSet+1].image); // get second image
    $img3.attr("src", characterList[imgSet*imgInSet+2].image); // get third image
}

Those two swap previous/next buttons when they get to the negative numbers by doing it like that:

let page = 0;
const imgInSet = 3;
const numberOfPages = Math.floor(characterList.length/3);

const reloadImages = ()=>{
    const imgSet = page<0?numberOfPages+page%imgInSet:page)%numOfPages;
    $img1.attr("src", characterList[imgSet*imgInSet].image);
    $img2.attr("src", characterList[imgSet*imgInSet+1].image);
    $img3.attr("src", characterList[imgSet*imgInSet+2].image);
}

$nextBtn.on("click", ()=>reloadImages(++page));

$prevBtn.on("click", ()=>reloadImages(--page);)

This answer is for more "universal solution" where you won't need to change too much with each new img that you would need to be cycled through.

Upvotes: 0

Emiel Zuurbier
Emiel Zuurbier

Reputation: 20954

You'll need two things:

  • A function that sets images based on an index.
  • An index to keep track on where to in charactersList to start counting from.

With the function you can render you images based on a starting point with +1 and +2 index. So let's say you start at 2, then 3 and 4 will also be rendered.

The nextBtn should increment the index with +3 so that the next 3 images will be rendered. The prevBtn should decrement the index with -3 so that the previous 3 images will be rendered.

const $img1 = $("#img1")
const $img2 = $("#img2")
const $img3 = $("#img3")
const $nextBtn = $("#next-btn")
const $prevBtn = $("#prev-btn")

$.get("https://someApiLink.com/all.json", function (characters) {
    const charactersList = []
    for (let i=0; i<characters.length; i++) {
        if (casts.includes(characters[i].name)) {
            charactersList.push(characters[i])
        }
    }

    // Index to start counting from.
    let characterIndex = 0;

    /**
     * Sets three images based in the given index.
     * Indexes will be counted upwards starting with the index.
     * @param {number} index
     */
    const setThreeImageFromIndex = index => {
        $img1.attr("src", charactersList[index].image)
        $img2.attr("src", charactersList[index + 1].image)
        $img3.attr("src", charactersList[index + 2].image)
    });

    // Set images for the first time.
    setThreeImageFromIndex(characterIndex);
    
    // Go to next 3.
    $nextBtn.on("click", function () {
       // Don't go over the length of the characterList.
       if (characterIndex + 3 < charactersList.length) {
           characterIndex += 3;
           setThreeImageFromIndex(characterIndex);
       }
    });

    // Go to previous 3.
    $prevBtn.on("click", function () {
       // Don't go below 0.
       if (characterIndex - 3 >= 0) {
           characterIndex -= 3;
           setThreeImageFromIndex(characterIndex);
       }
    });
})

Upvotes: 2

Related Questions