Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions InfiniteImageSlider/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Infinite Image Slider

A modular infinite slider implementation in plain HTML/CSS/JS.

## Architecture Overview

The project follows a clear separation of concerns, treating each module as a "black box":

- **DataSource**: Manages slide list and circular index logic. No DOM knowledge.
- **SlideRenderer**: Converts slide data into DOM elements. Pure rendering.
- **SliderController**: Handles events and coordinates updates between data and view.

This design makes the code easy to test, extend, and maintain.

## How to Run

Open `index.html` in a browser. For reliable local testing, color blocks are used instead of external images.

## Contribution

- This PR closes #954.
- Author: MELS1922
14 changes: 14 additions & 0 deletions InfiniteImageSlider/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Infinite Image Slider</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="slider-container" id="sliderContainer"></div>
<button id="prevBtn">← Prev</button>
<button id="nextBtn">Next →</button>
<script src="script.js"></script>
</body>
</html>
83 changes: 83 additions & 0 deletions InfiniteImageSlider/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/**
* DataSource: manages slide data and circular navigation logic.
* Acts as a pure "black box" for state — no DOM or UI knowledge.
*/
const DataSource = (() => {
const slides = [
{ id: 1, color: "#ff4444", text: "SLIDE 1" },
{ id: 2, color: "#44ff44", text: "SLIDE 2" },
{ id: 3, color: "#4444ff", text: "SLIDE 3" },
];

let currentIndex = 0;

return {
/** Returns the current slide object */
getCurrent: () => slides[currentIndex],

/** Moves to the next slide with wrap-around */
getNext: () => {
currentIndex = (currentIndex + 1) % slides.length;
return slides[currentIndex];
},

/** Moves to the previous slide with wrap-around */
getPrev: () => {
currentIndex = (currentIndex - 1 + slides.length) % slides.length;
return slides[currentIndex];
},
};
})();

/**
* SlideRenderer: transforms slide data into a DOM element.
* Pure rendering logic — no state or event handling.
*/
const SlideRenderer = {
render: (slide) => {
const div = document.createElement("div");
div.style.width = "100%";
div.style.height = "100%";
div.style.backgroundColor = slide.color;
div.style.display = "flex";
div.style.justifyContent = "center";
div.style.alignItems = "center";
div.style.color = "#fff";
div.style.fontSize = "40px";
div.style.fontFamily = "Arial, sans-serif";
div.textContent = slide.text;
return div;
},
};

/**
* SliderController: orchestrates user interactions and updates the view.
* Bridges DataSource and SlideRenderer; handles event listeners.
*/
const SliderController = (() => {
const container = document.getElementById("sliderContainer");
const nextBtn = document.getElementById("nextBtn");
const prevBtn = document.getElementById("prevBtn");

const renderCurrent = () => {
container.innerHTML = ""; // simple re-render for clarity
const slide = DataSource.getCurrent();
const el = SlideRenderer.render(slide);
container.appendChild(el);
};

nextBtn.addEventListener("click", () => {
DataSource.getNext();
renderCurrent();
});

prevBtn.addEventListener("click", () => {
DataSource.getPrev();
renderCurrent();
});

return { init: renderCurrent };
})();

// Initialize slider on load
SliderController.init();
13 changes: 13 additions & 0 deletions InfiniteImageSlider/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
:root {
--slider-width: 600px;
--slider-height: 400px;
}

.slider-container {
display: flex;
overflow: hidden;
width: var(--slider-width);
height: var(--slider-height);
border: 1px solid #ccc;
box-sizing: border-box;
}