I'm using gsap.js for the popup/modal. I use forEach so that no matter how many identical parts of this site I add, it will work fine. My only goal is to make this work perfectly now, somehow. Whenever you click on the "button" that pops up, then you get 9 images and select 4 of them and click "Save Edits" and when you press "Save Edits" then the body text When the image has 4 image bodies in it, it changes automatically. And you can change it again and again.
const items = document.querySelectorAll(".mdlsc"); const modal = document.querySelector(".modal"); items.forEach((item, index) => { item.querySelector(".opnBtn").addEventListener("click", () => { item.querySelector(".modal").style.display = "grid"; gsap.to(item.querySelector(".modalwrap"), { scale: 1, ease: "elastic.out(1, 0.3)", }); }); item.querySelector(".ovlybg").addEventListener("click", () => { gsap.to(item.querySelector(".modalwrap"), { scale: 0, ease: "elastic.out(1, 0.3)", }); item.querySelector(".modal").style.display = "none"; }); });
body { width: 100%; overflow-x: hidden; color: #fff; background: url(https://polite-figolla-02d41d.netlify.app/img/wefdf.png) no-repeat; background-size: cover; background-position: center center; height: 100vh; } body img { width: 100%; } body button { background: transparent; border: none; cursor: pointer; } .main { width: 500px; margin: auto; } .modal { position: fixed; z-index: 9; left: 0%; top: 0%; width: 100%; height: 100vh; place-content: center; place-items: center; display: none; } .modal .ovlybg { position: absolute; background: rgba(0, 0, 0, 0.5); top: 0px; left: 0%; z-index: 1; width: 100%; height: 100%; } .modal .modalwrap { transform: scale(0); width: 400px; margin: auto; height: -webkit-fit-content; height: -moz-fit-content; height: fit-content; border: 5px solid #fff; border-radius: 77px; position: relative; z-index: 3; background: linear-gradient(to right, #400df0, #6203b3, #940599); text-align: center; text-transform: uppercase; font-weight: 600; padding: 45px 0px; } .edtchp { text-align: center; padding: 25px 0px 2px; } .edtchp span { font-size: 1em; margin: 0; } .edtchp h1 { font-size: 2.2em; color: #fff; margin: 0; transform: translate(0px, 0px); } .clsebtn img { width: 120px; } .mdlsc { margin-left: 10px; } .grypnk { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; padding: 18px 5px; width: 80%; margin: auto; } .grypnk img { width: 100% !important; } .coinsc { display: flex; align-items: center; width: 85%; margin: auto; gap: 8px; justify-content: center; margin: 10px auto; } .coinsc .imdwidth { display: flex; align-items: center; } .coinsc .imdwidth img { width: 45px; } .coin { display: grid; grid-template-columns: repeat(4, 1fr); gap: 5px; align-items: center; }
<div class="main"> <div class="coinsc"> <div class="coin"> <img src="https://polite-figolla-02d41d.netlify.app/img/Chips/chip-100.png" alt="" /> <img src="https://polite-figolla-02d41d.netlify.app/img/Chips/chip-500.png" alt="" /> <img src="https://polite-figolla-02d41d.netlify.app/img/Chips/chip-1000.png" alt="" /> <img src="https://polite-figolla-02d41d.netlify.app/img/Chips/chip-3000.png" alt="" /> </div> <div class="mdlsc"> <div class="modal"> <div class="modalwrap antclr"> <div class="edtchp"> <h1>Edit Chip Rack</h1> <span>SELECT 4 CHIPS TO DISPLAY</span> </div> <div class="grypnk"> <img src="https://polite-figolla-02d41d.netlify.app/img/Chips/chip-1.png" alt="" /> <img src="https://polite-figolla-02d41d.netlify.app/img/Chips/chip-50.png" alt="" /> <img src="https://polite-figolla-02d41d.netlify.app/img/Chips/chip-1000.png" alt="" /> <img src="https://polite-figolla-02d41d.netlify.app/img/Chips/chip-5.png" alt="" /> <img src="https://polite-figolla-02d41d.netlify.app/img/Chips/chip-100.png" alt="" /> <img src="https://polite-figolla-02d41d.netlify.app/img/Chips/chip-3000.png" alt="" /> <img src="https://polite-figolla-02d41d.netlify.app/img/Chips/chip-10.png" alt="" /> <img src="https://polite-figolla-02d41d.netlify.app/img/Chips/chip-500.png" alt="" /> <img src="https://polite-figolla-02d41d.netlify.app/img/Chips/chip-5000.png" alt="" /> </div> <a href="#" class="clsebtn" > <img src="https://polite-figolla-02d41d.netlify.app/img/saveedit.png" alt="" /> </a> </div> <div class="ovlybg"></div> </div> <button class="opnBtn"> <div class="imdwidth"> <img src="https://polite-figolla-02d41d.netlify.app/img/Chips/chip-editchip.png" alt="" /> </div> </button> </div> </div> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.3/gsap.min.js"></script>
P粉5909293922024-01-30 00:26:54
This is my method. The GsapJS library was not an obstacle when developing this solution. You'll see that I've published the image separately because your image has been automatically unpublished.
Your changes will not appear unless you save. The number of chips the user selects here is 4. It will alert you whenever you try to select more or save edits without at least 4 chips selected. Therefore, you must deselect the gray chip before selecting the new chip. I've used the term "chip" here rather than "coin".
The tool I use is CSS animation to make the chip look like it flips when clicked. These materials/sources are helpful in my work,
//All items declared in a single object const allChips = [{ name: 'chip-val-1', img: 'https://i.im.ge/2022/11/28/S0jFH4.image.png', bk: 'https://i.im.ge/2022/11/28/S0wuFC.S0jFH4-image.png' }, { name: 'chip-val-50', img: 'https://i.im.ge/2022/11/28/S0j11C.image.png', bk: 'https://i.im.ge/2022/11/28/S0wlk4.S0j11C-image.png' }, { name: 'chip-val-1000', img: 'https://i.im.ge/2022/11/28/S0j2wq.image.png', bk: 'https://i.im.ge/2022/11/28/S0wORp.S0j2wq-image.png' }, { name: 'chip-val-5', img: 'https://i.im.ge/2022/11/28/S0jSZp.image.png', bk: 'https://i.im.ge/2022/11/28/S0wd3f.S0jSZp-image.png' }, { name: 'chip-val-100', img: 'https://i.im.ge/2022/11/28/S0jqXP.image.png', bk: 'https://i.im.ge/2022/11/28/S0wSU1.S0jqXP-image.png' }, { name: 'chip-val-3000', img: 'https://i.im.ge/2022/11/28/S0j7Gm.chip-3000.png', bk: 'https://i.im.ge/2022/11/28/S0wFjq.S0j7Gm-chip-3000.png' }, { name: 'chip-val-10', img: 'https://i.im.ge/2022/11/28/S0jI7r.chip-10.png', bk: 'https://i.im.ge/2022/11/28/S0wXtD.S0jI7r-chip-10.png' }, { name: 'chip-val-500', img: 'https://i.im.ge/2022/11/28/S0jLAW.chip-500.png', bk: 'https://i.im.ge/2022/11/28/S0w2TP.S0jLAW-chip-500.png' }, { name: 'chip-val-5000', img: 'https://i.im.ge/2022/11/28/S0jUp0.chip-5000.png', bk: 'https://i.im.ge/2022/11/28/S0wq4m.S0jUp0-chip-5000.png' } ] //Dedicated array for selected chips let selectedChips = ['chip-val-100', "chip-val-500", "chip-val-1000", "chip-val-3000"]; const items = document.querySelectorAll(".mdlsc"); const modal = document.querySelector(".modal"); items.forEach((item, index) => { item.querySelector(".opnBtn").addEventListener("click", () => { item.querySelector(".modal").style.display = "grid"; gsap.to(item.querySelector(".modalwrap"), { scale: 1, ease: "elastic.out(1, 0.3)", }); try { popupBoard(); } catch (e) { console.error(e); } }); item.querySelector(".ovlybg").addEventListener("click", () => { refreshSelectedChips(); gsap.to(item.querySelector(".modalwrap"), { scale: 0, ease: "elastic.out(1, 0.3)", }); item.querySelector(".modal").style.display = "none"; }); item.querySelector(".clsebtn").addEventListener("click", () => { refreshSelectedChips('save'); item.querySelector(".modal").style.display = "none"; }) }); //Function for displaying selected chips const refreshSelectedChips = (b) => { document.getElementById("selected-chips").innerHTML = ''; const dyChips = document.querySelectorAll('.fliped'); if (b === 'save') { if (dyChips.length !== 4) { alert("Please select 4 chips.") item.querySelector(".modal").style.display = "grid"; } else { selectedChips = []; for (let i = 0; i < dyChips.length; i++) { selectedChips.push(dyChips[i].id); } } } document.getElementById("popup-board").innerHTML = ''; populateBoard(); } //Function for edit panel const popupBoard = () => { for (let i = 0; i < allChips.length; i++) { let chipID = allChips[i].name; let chipFrontID = 'chip-front-' + Math.round(Math.random() * 1000) + '-' + i; let chipBackID = 'chip-front-' + Math.round(Math.random() * 1000) + '-' + i; const flipedStatus = (x) => { for (let y = 0; y < selectedChips.length; y++) { if (x === selectedChips[y]) { return `fliped` } } } //"popup-board" gets updated on save document.getElementById("popup-board").innerHTML += `` const dyChips = document.querySelectorAll('.chip-inner'); for (let dy of dyChips) { dy.addEventListener('click', function flipClick() { if (dy.classList.contains('fliped')) { dy.classList.remove('fliped'); } else { if (document.querySelectorAll('.fliped').length >= 4) { alert("Only 4 chips can be selected."); } else { dy.classList.add('fliped'); } } }) } } } //Displaying the selected items at startup const populateBoard = () => { selectedChips.forEach(name => { const img = document.createElement("img"); img.alt = name; for (let i = 0; i < allChips.length; i++) { if (name === allChips[i].name) { img.src = allChips[i].img; } } window["selected-chips"].appendChild(img); }) } //Initial trigger for displaying the selected items try { populateBoard(); } catch (e) { console.error(e); }
body { width: 100%; overflow-x: hidden; color: #fff; background: url(https://i.im.ge/2022/11/28/S0jypz.download.png) no-repeat; background-size: cover; background-position: center center; height: 100vh; } body img { width: 100%; } body button { background: transparent; border: none; cursor: pointer; } .main { width: 500px; margin: auto; } .modal { position: fixed; z-index: 9; left: 0%; top: 0%; width: 100%; height: 100vh; place-content: center; place-items: center; display: none; } .modal .ovlybg { position: absolute; background: rgba(0, 0, 0, 0.5); top: 0px; left: 0%; z-index: 1; width: 100%; height: 100%; } .modal .modalwrap { transform: scale(0); width: 400px; margin: auto; height: -webkit-fit-content; height: -moz-fit-content; height: fit-content; border: 5px solid #fff; border-radius: 77px; position: relative; z-index: 3; background: linear-gradient(to right, #400df0, #6203b3, #940599); text-align: center; text-transform: uppercase; font-weight: 600; padding: 45px 0px; } .edtchp { text-align: center; padding: 25px 0px 2px; } .edtchp span { font-size: 1em; margin: 0; } .edtchp h1 { font-size: 2.2em; color: #fff; margin: 0; transform: translate(0px, 0px); } .clsebtn img { width: 120px; } .mdlsc { margin-left: 10px; } .grypnk { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; padding: 18px 5px; width: 80%; margin: auto; } .grypnk img { width: 100% !important; } .coinsc { display: flex; align-items: center; width: 85%; margin: auto; gap: 8px; justify-content: center; margin: 10px auto; } .coinsc .imdwidth { display: flex; align-items: center; } .coinsc .imdwidth img { width: 45px; } .coin { display: grid; grid-template-columns: repeat(4, 1fr); gap: 5px; align-items: center; } /*I have used the term chip instead of coin here*/ .chip:nth-child(n+4) { margin-top: 100px; } .chip:nth-child(n+7) { margin-bottom: 100px; } .chip { background-color: transparent; perspective: 1000px; cursor: pointer; } /*Animation when a chip is clicked/selected*/ .chip-inner { position: relative; text-align: center; transition: transform 0.6s; transform-style: preserve-3d; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2); cursor: pointer; } .chip .chip-inner.fliped { transform: rotateY(180deg); } .chip-front, .chip-back { position: absolute; -webkit-backface-visibility: hidden; /*Backface is hidden since it reveals as chip flips*/ backface-visibility: hidden; } .chip-back { transform: rotateY(180deg); }
sssccc sssccc