From 220d9e154024489a072e6d8c3011d2c2c783ce1a Mon Sep 17 00:00:00 2001 From: bukvaechkavk-rgb Date: Thu, 10 Sep 2026 19:50:01 +0300 Subject: [PATCH] feat: infinite slider with modular architecture + JSDoc --- InfiniteImageSlider/README.md | 22 +++++++++ InfiniteImageSlider/index.html | 14 ++++++ InfiniteImageSlider/script.js | 83 ++++++++++++++++++++++++++++++++++ InfiniteImageSlider/style.css | 13 ++++++ 4 files changed, 132 insertions(+) create mode 100644 InfiniteImageSlider/README.md create mode 100644 InfiniteImageSlider/index.html create mode 100644 InfiniteImageSlider/script.js create mode 100644 InfiniteImageSlider/style.css diff --git a/InfiniteImageSlider/README.md b/InfiniteImageSlider/README.md new file mode 100644 index 000000000..9340113bb --- /dev/null +++ b/InfiniteImageSlider/README.md @@ -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 diff --git a/InfiniteImageSlider/index.html b/InfiniteImageSlider/index.html new file mode 100644 index 000000000..721c5b733 --- /dev/null +++ b/InfiniteImageSlider/index.html @@ -0,0 +1,14 @@ + + + + + Infinite Image Slider + + + +
+ + + + + diff --git a/InfiniteImageSlider/script.js b/InfiniteImageSlider/script.js new file mode 100644 index 000000000..ed66e518e --- /dev/null +++ b/InfiniteImageSlider/script.js @@ -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(); diff --git a/InfiniteImageSlider/style.css b/InfiniteImageSlider/style.css new file mode 100644 index 000000000..9ab5e3d18 --- /dev/null +++ b/InfiniteImageSlider/style.css @@ -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; +}